diff --git a/package.json b/package.json index 0fe2ae0b8..01f8ee098 100644 --- a/package.json +++ b/package.json @@ -139,6 +139,7 @@ "@docusaurus/preset-classic": "2.1.0", "@docusaurus/remark-plugin-npm2yarn": "2.1.0", "@docusaurus/theme-live-codeblock": "2.1.0", + "@emotion/css": "11.13.5", "@emotion/native": "11.9.3", "@emotion/react": "11.10.4", "@emotion/styled": "11.10.4", diff --git a/packages/vibrant-core/src/cssConstants.ts b/packages/vibrant-core/src/cssConstants.ts new file mode 100644 index 000000000..6691ccbaf --- /dev/null +++ b/packages/vibrant-core/src/cssConstants.ts @@ -0,0 +1,123 @@ +export const staticClassName = new Set([ + 'margin-0', + 'margin-1', + 'margin-2', + 'margin-3', + 'margin-4', + 'margin-5', + 'margin-6', + 'margin-8', + 'margin-10', + 'margin-12', + 'margin-16', + 'margin-20', + 'margin-24', + 'margin-32', + 'margin-40', + 'margin-48', + 'margin-56', + 'margin-64', + 'margin-72', + 'padding-0', + 'padding-1', + 'padding-2', + 'padding-3', + 'padding-4', + 'padding-5', + 'padding-6', + 'padding-8', + 'padding-10', + 'padding-12', + 'padding-16', + 'padding-20', + 'padding-24', + 'padding-32', + 'padding-40', + 'padding-48', + 'padding-56', + 'padding-64', + 'padding-72', + 'display-flex', + 'display-inline-flex', + 'display-block', + 'display-inline-block', + 'display-inline', + 'display-hidden', + 'justify-start', + 'justify-end', + 'justify-center', + 'justify-between', + 'justify-around', + 'alignItems-flex-start', + 'alignItems-flex-end', + 'alignItems-center', + 'alignItems-baseline', + 'alignItems-stretch', + 'alignSelf-flex-start', + 'alignSelf-flex-end', + 'alignSelf-center', + 'alignSelf-baseline', + 'alignSelf-stretch', + 'flexWrap-nowrap', + 'flexWrap-wrap', + 'flexWrap-wrap-reverse', + 'flex-grow-0', + 'flex-grow-1', + 'flexShrink-0', + 'flexShrink-1', + 'flexDirection-row', + 'flexDirection-row-reverse', + 'flexDirection-column', + 'flexDirection-column-reverse', + 'position-relative', + 'position-absolute', + 'position-fixed', + 'position-sticky', + 'boxSizing-border-box', + 'boxSizing-content-box', + 'overflow-auto', + 'overflow-hidden', + 'overflow-visible', + 'overflow-scroll', + 'borderStyle-solid', + 'borderStyle-dashed', + 'borderStyle-dotted', + 'borderStyle-double', + 'borderStyle-none', + 'borderWidth-0', + 'borderWidth-1', + 'borderWidth-2', + 'borderWidth-3', + 'borderWidth-4', + 'borderWidth-5', + 'borderWidth-6', + 'borderWidth-7', + 'borderWidth-8', + 'alignItems-start', + 'alignItems-end', + 'alignItems-center', + 'alignContent-stretch', + 'borderRadius-0', + 'borderRadius-1', + 'borderRadius-2', + 'borderRadius-3', + 'borderRadius-4', + 'borderRadius-5', + 'borderRadius-6', + 'borderRadius-7', + 'borderRadius-8', + 'borderRadius-9', + 'borderRadius-10', + 'borderRadius-11', + 'borderRadius-12', + 'borderRadius-13', + 'borderRadius-14', + 'borderRadius-15', + 'borderRadius-16', + 'borderRadius-17', + 'borderRadius-18', + 'borderRadius-19', + 'borderRadius-20', + 'borderRadius-21', + 'borderRadius-22', +]); diff --git a/packages/vibrant-core/src/index.module.css b/packages/vibrant-core/src/index.module.css new file mode 100644 index 000000000..054a87b6c --- /dev/null +++ b/packages/vibrant-core/src/index.module.css @@ -0,0 +1,592 @@ +:global(.margin-0) { + margin: 0; + } + + :global(.margin-1) { + margin: 1px; + } + + :global(.margin-2) { + margin: 2px; + } + + :global(.margin-3) { + margin: 3px; + } + + :global(.margin-4) { + margin: 4px; + } + + :global(.margin-5) { + margin: 5px; + } + + :global(.margin-6) { + margin: 6px; + } + + :global(.margin-8) { + margin: 8px; + } + + :global(.margin-10) { + margin: 10px; + } + + :global(.margin-12) { + margin: 12px; + } + + :global(.margin-16) { + margin: 16px; + } + + :global(.margin-20) { + margin: 20px; + } + + :global(.margin-24) { + margin: 24px; + } + + :global(.margin-32) { + margin: 32px; + } + + :global(.margin-40) { + margin: 40px; + } + + :global(.margin-48) { + margin: 48px; + } + + :global(.margin-56) { + margin: 56px; + } + + :global(.margin-64) { + margin: 64px; + } + + :global(.margin-72) { + margin: 72px; + } + +:global(.padding-0) { + padding: 0; + } + + :global(.padding-1) { + padding: 1px; + } + + :global(.padding-2) { + padding: 2px; + } + + :global(.padding-3) { + padding: 3px; + } + + :global(.padding-4) { + padding: 4px; + } + + :global(.padding-5) { + padding: 5px; + } + + :global(.padding-6) { + padding: 6px; + } + + :global(.padding-8) { + padding: 8px; + } + + :global(.padding-10) { + padding: 10px; + } + + :global(.padding-12) { + padding: 12px; + } + + :global(.padding-16) { + padding: 16px; + } + + :global(.padding-20) { + padding: 20px; + } + + :global(.padding-24) { + padding: 24px; + } + + :global(.padding-32) { + padding: 32px; + } + + :global(.padding-40) { + padding: 40px; + } + + :global(.padding-48) { + padding: 48px; + } + + :global(.padding-56) { + padding: 56px; + } + + :global(.padding-64) { + padding: 64px; + } + + :global(.padding-72) { + padding: 72px; + } + +/* display */ +:global(.display-flex) { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; +} + +:global(.display-inline-flex) { + display: -webkit-inline-box; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; +} + +:global(.display-block) { + display: block; +} + +:global(.display-inline-block) { + display: inline-block; +} + +:global(.display-inline) { + display: inline; +} + +:global(.display-hidden) { + display: none; +} + +/* justify-content */ +:global(.justify-start) { + -webkit-box-pack: start; + -webkit-justify-content: flex-start; + -ms-flex-pack: start; + justify-content: flex-start; +} + +:global(.justify-end) { + -webkit-box-pack: end; + -webkit-justify-content: flex-end; + -ms-flex-pack: end; + justify-content: flex-end; +} + +:global(.justify-center) { + -webkit-box-pack: center; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; +} + +:global(.justify-between) { + -webkit-box-pack: justify; + -webkit-justify-content: space-between; + -ms-flex-pack: justify; + justify-content: space-between; +} + +:global(.justify-around) { + -webkit-box-pack: distribute; + -webkit-justify-content: space-around; + -ms-flex-pack: distribute; + justify-content: space-around; +} + +/* align-items */ + +:global(.alignItems-flex-start) { + -webkit-box-align: start; + -webkit-align-items: flex-start; + -ms-flex-align: start; + align-items: flex-start; +} + +:global(.alignItems-flex-end) { + -webkit-box-align: end; + -webkit-align-items: flex-end; + -ms-flex-align: end; + align-items: flex-end; +} + +:global(.alignItems-center) { + -webkit-box-align: center; + -webkit-align-items: center; + -ms-flex-align: center; + align-items: center; +} + +:global(.alignItems-baseline) { + -webkit-box-align: baseline; + -webkit-align-items: baseline; + -ms-flex-align: baseline; + align-items: baseline; +} + +:global(.alignItems-stretch) { + -webkit-box-align: stretch; + -webkit-align-items: stretch; + -ms-flex-align: stretch; + align-items: stretch; +} + +/* align-self */ + +:global(.alignSelf-flex-start) { + -webkit-align-self: flex-start; + -ms-flex-item-align: start; + align-self: flex-start; +} + +:global(.alignSelf-flex-end) { + -webkit-align-self: flex-end; + -ms-flex-item-align: end; + align-self: flex-end; +} + +:global(.alignSelf-center) { + -webkit-align-self: center; + -ms-flex-item-align: center; + align-self: center; +} + +:global(.alignSelf-baseline) { + -webkit-align-self: baseline; + -ms-flex-item-align: baseline; + align-self: baseline; +} + +:global(.alignSelf-stretch) { + -webkit-align-self: stretch; + -ms-flex-item-align: stretch; + align-self: stretch; +} + +/* flex-wrap */ + +:global(.flexWrap-nowrap) { + -webkit-flex-wrap: nowrap; + -ms-flex-wrap: nowrap; + flex-wrap: nowrap; +} + +:global(.flexWrap-wrap) { + -webkit-flex-wrap: wrap; + -ms-flex-wrap: wrap; + flex-wrap: wrap; +} + +:global(.flexWrap-wrap-reverse) { + -webkit-flex-wrap: wrap-reverse; + -ms-flex-wrap: wrap-reverse; + flex-wrap: wrap-reverse; +} + +/* flex-grow */ + +:global(.flex-grow-0) { + -webkit-box-flex: 0; + -webkit-flex: 0 0 auto; + -ms-flex: 0 0 auto; + flex: 0 0 auto; +} + +:global(.flex-grow-1) { + -webkit-box-flex: 1; + -webkit-flex: 1 1 0%; + -ms-flex: 1 1 0%; + flex: 1 1 0%; +} + +/* flex-shrink */ + +:global(.flexShrink-0) { + -ms-flex-negative: 0; + -webkit-flex-shrink: 0; + flex-shrink: 0; +} + +:global(.flexShrink-1) { + -ms-flex-negative: 1; + -webkit-flex-shrink: 1; + flex-shrink: 1; +} + +/* flex-direction */ + +:global(.flexDirection-row) { + -webkit-flex-direction: row; + -ms-flex-direction: row; + flex-direction: row; +} + +:global(.flexDirection-row-reverse) { + -webkit-flex-direction: row-reverse; + -ms-flex-direction: row-reverse; + flex-direction: row-reverse; +} + +:global(.flexDirection-column) { + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; +} + +:global(.flexDirection-column-reverse) { + -webkit-flex-direction: column-reverse; + -ms-flex-direction: column-reverse; + flex-direction: column-reverse; +} + +/* position */ +:global(.position-relative) { + position: relative; +} + +:global(.position-absolute) { + position: absolute; +} + +:global(.position-fixed) { + position: fixed; +} + +:global(.position-sticky) { + position: sticky; +} + +/* box-sizing */ +:global(.boxSizing-border-box) { + box-sizing: border-box; +} + +:global(.boxSizing-content-box) { + box-sizing: content-box; +} + + +/* overflow */ +:global(.overflow-auto) { + overflow: auto; +} + +:global(.overflow-hidden) { + overflow: hidden; +} + +:global(.overflow-visible) { + overflow: visible; +} + +:global(.overflow-scroll) { + overflow: scroll; +} + +/* border style */ +:global(.borderStyle-solid) { + border-style: solid; +} + +:global(.borderStyle-dashed) { + border-style: dashed; +} + +:global(.borderStyle-dotted) { + border-style: dotted; +} + +:global(.borderStyle-double) { + border-style: double; +} + +:global(.borderStyle-none) { + border-style: none; +} + +/* border width */ +:global(.borderWidth-0) { + border-width: 0; +} + +:global(.borderWidth-1) { + border-width: 1px; +} + +:global(.borderWidth-2) { + border-width: 2px; +} + +:global(.borderWidth-3) { + border-width: 3px; +} + +:global(.borderWidth-4) { + border-width: 4px; +} + +:global(.borderWidth-5) { + border-width: 5px; +} + +:global(.borderWidth-6) { + border-width: 6px; +} + +:global(.borderWidth-7) { + border-width: 7px; +} + +:global(.borderWidth-8) { + border-width: 8px; +} + +/* flex-align */ +:global(.alignItems-start) { + -webkit-align-items: flex-start; + -webkit-box-align: flex-start; + -ms-flex-align: flex-start; + align-items: flex-start; + } + +:global(.alignItems-end) { + -webkit-align-items: flex-end; + -webkit-box-align: flex-end; + -ms-flex-align: flex-end; + align-items: flex-end; +} + +:global(.alignItems-center) { + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; +} + +:global(.alignContent-stretch) { + align-content: stretch +} + +/* border-radius */ +:global(.borderRadius-0) { + border-radius: 0; +} + +:global(.borderRadius-1) { + border-radius: 1px; +} + +:global(.borderRadius-2) { + border-radius: 2px; +} + +:global(.borderRadius-3) { + border-radius: 3px; +} + +:global(.borderRadius-4) { + border-radius: 4px; +} + +:global(.borderRadius-5) { + border-radius: 5px; +} + +:global(.borderRadius-6) { + border-radius: 6px; +} + +:global(.borderRadius-7) { + border-radius: 7px; +} + +:global(.borderRadius-8) { + border-radius: 8px; +} + +:global(.borderRadius-9) { + border-radius: 9px; +} + +:global(.borderRadius-10) { + border-radius: 10px; +} + +:global(.borderRadius-11) { + border-radius: 11px; +} + +:global(.borderRadius-12) { + border-radius: 12px; +} + +:global(.borderRadius-13) { + border-radius: 13px; +} + +:global(.borderRadius-14) { + border-radius: 14px; +} + +:global(.borderRadius-15) { + border-radius: 15px; +} + +:global(.borderRadius-16) { + border-radius: 16px; +} + +:global(.borderRadius-17) { + border-radius: 17px; +} + +:global(.borderRadius-18) { + border-radius: 18px; +} + +:global(.borderRadius-19) { + border-radius: 19px; +} + +:global(.borderRadius-20) { + border-radius: 20px; +} + +:global(.borderRadius-21) { + border-radius: 21px; +} + +:global(.borderRadius-22) { + border-radius: 22px; +} + +:global(.borderRadius-23) { + border-radius: 23px; +} + +:global(.borderRadius-24) { + border-radius: 24px; +} \ No newline at end of file diff --git a/packages/vibrant-core/src/index.ts b/packages/vibrant-core/src/index.ts index 53bd62183..4b9a71a1e 100644 --- a/packages/vibrant-core/src/index.ts +++ b/packages/vibrant-core/src/index.ts @@ -1,3 +1,4 @@ +import './index.module.css'; export { Box } from './lib/Box'; export type { BoxElements, BoxProps, LayoutEvent } from './lib/Box'; export { Svg } from './lib/Svg'; diff --git a/packages/vibrant-core/src/lib/Box/Box.tsx b/packages/vibrant-core/src/lib/Box/Box.tsx index b88326922..22a88048f 100644 --- a/packages/vibrant-core/src/lib/Box/Box.tsx +++ b/packages/vibrant-core/src/lib/Box/Box.tsx @@ -1,54 +1,56 @@ import type { ComponentType, FC, ReactElement } from 'react'; import { createElement, forwardRef, memo } from 'react'; -import styled from '@emotion/styled'; import { useComposedRef, useLayoutEvent } from '@vibrant-ui/utils'; +import { convertStyleToClassName } from '../convertStyleToClassName'; import { OnColorContainer } from '../OnColorContainer'; import type { BoxElements, BoxProps } from './BoxProps'; import { interpolation, shouldForwardProp } from './BoxProps'; export const Box = memo( - styled( - forwardRef( - ( - { - as, - base, - onLayout, - ariaLabel, - ariaChecked, - ariaLabelledBy, - ariaCurrent, - ariaSelected, - backgroundColor, - ...restProps - }, - ref - ) => { - const { ref: layoutEventRef } = useLayoutEvent(onLayout); - const composeRef = useComposedRef(ref, layoutEventRef); + forwardRef( + ( + { + as, + base, + onLayout, + ariaLabel, + ariaChecked, + ariaLabelledBy, + ariaCurrent, + ariaSelected, + backgroundColor, + ...restProps + }, + ref + ) => { + const { ref: layoutEventRef } = useLayoutEvent(onLayout); + const composeRef = useComposedRef(ref, layoutEventRef); - const element = createElement(base ?? as ?? 'div', { - ref: composeRef, - ...(base && as ? { as } : {}), - 'aria-label': ariaLabel, - 'aria-checked': ariaChecked, - 'aria-labelledby': ariaLabelledBy, - 'aria-current': ariaCurrent, - 'aria-selected': ariaSelected, - ...restProps, - }); + const className = convertStyleToClassName(interpolation({ ...restProps, backgroundColor })).join(' '); - if (backgroundColor) { - return {element}; - } + const domAttributeProps = Object.fromEntries( + Object.entries(restProps).filter(([key, _]) => shouldForwardProp(key)) + ); - return element; + const element = createElement(base ?? as ?? 'div', { + ref: composeRef, + ...(base && as ? { as } : {}), + 'aria-label': ariaLabel, + 'aria-checked': ariaChecked, + 'aria-labelledby': ariaLabelledBy, + 'aria-current': ariaCurrent, + 'aria-selected': ariaSelected, + ...domAttributeProps, + className, + }); + + if (backgroundColor) { + return {element}; } - ), - { - shouldForwardProp, + + return element; } - )(interpolation) + ) ) as < BaseComponent extends ComponentType | undefined = undefined, ElementName extends BoxElements | undefined = undefined diff --git a/packages/vibrant-core/src/lib/ScrollBox/ScrollBox.tsx b/packages/vibrant-core/src/lib/ScrollBox/ScrollBox.tsx index f7ca9106c..06a30f5b9 100644 --- a/packages/vibrant-core/src/lib/ScrollBox/ScrollBox.tsx +++ b/packages/vibrant-core/src/lib/ScrollBox/ScrollBox.tsx @@ -1,40 +1,46 @@ import { createElement, forwardRef } from 'react'; -import styled from '@emotion/styled'; import { useComposedRef, useLayoutEvent } from '@vibrant-ui/utils'; -import { transformResponsiveValue } from '../transformResponsiveValue'; +import { convertStyleToClassName } from '../convertStyleToClassName'; import type { ScrollBoxProps } from './ScrollBoxProps'; import { interpolation, shouldForwardProp } from './ScrollBoxProps'; -const SystemScrollBox = styled( - forwardRef( - ({ as = 'div', ariaChecked, ariaCurrent, ariaLabel, ariaLabelledBy, ariaSelected, ...restProps }, ref) => - createElement(as, { - ref, - 'aria-label': ariaLabel, - 'aria-checked': ariaChecked, - 'aria-labelledby': ariaLabelledBy, - 'aria-current': ariaCurrent, - 'aria-selected': ariaSelected, - ...restProps, - }) - ), - { - shouldForwardProp, - } -)(interpolation); - -export const ScrollBox = forwardRef( - ({ keyboardShouldPersistTaps: _, scrollEnabled = true, onLayout, ...restProps }, ref) => { +export const ScrollBox = forwardRef( + ( + { + as = 'div', + ariaChecked, + ariaCurrent, + ariaLabel, + ariaLabelledBy, + ariaSelected, + // eslint-disable-next-line @typescript-eslint/naming-convention + scrollEnabled = true, + onLayout, + ...restProps + }, + ref + ) => { const { ref: layoutEventRef } = useLayoutEvent(onLayout); const composeRef = useComposedRef(ref, layoutEventRef); - return ( - (value ? 'auto' : 'hidden'))} - /> + const className = convertStyleToClassName(interpolation(restProps)).join(' '); + + const domAttributeProps = Object.fromEntries( + Object.entries(restProps).filter(([key, _]) => shouldForwardProp(key)) ); + + const element = createElement(as, { + ref: composeRef, + 'aria-label': ariaLabel, + 'aria-checked': ariaChecked, + 'aria-labelledby': ariaLabelledBy, + 'aria-current': ariaCurrent, + 'aria-selected': ariaSelected, + ...domAttributeProps, + className, + }); + + return element; } ); diff --git a/packages/vibrant-core/src/lib/Text/Text.tsx b/packages/vibrant-core/src/lib/Text/Text.tsx index 5d0f0ccc6..dec6fd3d2 100644 --- a/packages/vibrant-core/src/lib/Text/Text.tsx +++ b/packages/vibrant-core/src/lib/Text/Text.tsx @@ -1,21 +1,20 @@ import type { FC } from 'react'; import { createElement, forwardRef } from 'react'; -import styled from '@emotion/styled'; +import { convertStyleToClassName } from '../convertStyleToClassName'; import { nl2br } from '../nl2br'; import type { TextProps } from './TextProps'; import { interpolation, shouldForwardProp } from './TextProps'; -export const Text: FC = styled( - forwardRef(({ as = 'span', children, ...restProps }, ref) => - createElement(as, { - ref, - children: typeof children === 'string' ? nl2br(children) : children, - ...restProps, - }) - ), - { - shouldForwardProp, - } -)(interpolation); +export const Text: FC = forwardRef(({ as = 'span', children, ...restProps }, ref) => { + const className = convertStyleToClassName(interpolation(restProps)).join(' '); + const domAttributeProps = Object.fromEntries(Object.entries(restProps).filter(([key, _]) => shouldForwardProp(key))); + + return createElement(as, { + ref, + children: typeof children === 'string' ? nl2br(children) : children, + domAttributeProps, + className, + }); +}); (Text as FC).displayName = 'Text'; diff --git a/packages/vibrant-core/src/lib/TextInput/TextInput.tsx b/packages/vibrant-core/src/lib/TextInput/TextInput.tsx index 248b19d07..9e7055bd5 100644 --- a/packages/vibrant-core/src/lib/TextInput/TextInput.tsx +++ b/packages/vibrant-core/src/lib/TextInput/TextInput.tsx @@ -1,6 +1,6 @@ -import { forwardRef, useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react'; +import { createElement, forwardRef, useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react'; import type { FormEvent, KeyboardEvent } from 'react'; -import styled from '@emotion/styled'; +import { convertStyleToClassName } from '../convertStyleToClassName'; import { createShouldForwardProp } from '../createShouldForwardProp'; import type { SystemProps, TextInputProps, TextInputRef } from './TextInputProps'; import { HTMLAutoCompleteOptions, interpolation, replaceValue, systemPropNames } from './TextInputProps'; @@ -9,10 +9,6 @@ type HTMLInputProps = Exclude(systemPropNames); -const SystemTextInput = styled<'input', HTMLInputProps>('input', { - shouldForwardProp, -})(interpolation); - export const TextInput = forwardRef( ( { @@ -74,74 +70,94 @@ export const TextInput = forwardRef( clear: () => { setValue(''); - onValueChange?.({ value: '', prevent: () => {}, target: innerRef.current }); + onValueChange?.({ + value: '', + prevent: () => {}, + target: innerRef.current, + }); }, isFocused: () => document.activeElement === innerRef.current, })); - return ( - { - setIsFocused(true); - - onFocus?.(); - }} - onBlur={() => { - setIsFocused(false); - - onBlur?.(); - }} - onKeyDown={(event: KeyboardEvent) => { - const { key } = event.nativeEvent; - - if (key === 'Enter') { - onSubmit?.(value); - - return; + const styleProps = interpolation({ + ...restProps, + ...(hidden + ? { + position: 'absolute', + height: 0, + opacity: 0, } + : {}), + ...(isFocused ? focusStyle : {}), + }); - onKeyPress?.({ key, prevent: () => event.preventDefault() }); - }} - onInput={(event: FormEvent) => { - const replacedValue = replaceValue({ - pattern: type === 'number' ? /\d/ : pattern, - value: event.currentTarget.value, - }); + const className = convertStyleToClassName(interpolation(styleProps)).join(' '); - let isPrevented = false; + const domAttributeProps = Object.fromEntries( + Object.entries(restProps).filter(([key, _]) => shouldForwardProp(key)) + ); - if (value === replacedValue) { - event.preventDefault(); + return createElement('input', { + ref: innerRef, + type: type === 'number' ? 'text' : type, + value, + enterKeyHint: enterKeyType, + inputMode, + autoCapitalize, + autoComplete: HTMLAutoCompleteOptions[autoComplete], + onFocus: () => { + setIsFocused(true); - return; - } + onFocus?.(); + }, + onBlur: () => { + setIsFocused(false); - onValueChange?.({ - value: replacedValue, - prevent: () => { - isPrevented = true; + onBlur?.(); + }, - event.preventDefault(); - }, - target: innerRef.current, - }); + onKeyDown: (event: KeyboardEvent) => { + const { key } = event.nativeEvent; - if (!isPrevented) { - setValue(replacedValue); - } - }} - {...restProps} - {...(isFocused ? focusStyle : {})} - {...(hidden ? { position: 'absolute', height: 0, opacity: 0 } : {})} - /> - ); + if (key === 'Enter') { + onSubmit?.(value); + + return; + } + + onKeyPress?.({ key, prevent: () => event.preventDefault() }); + }, + onInput: (event: FormEvent) => { + const replacedValue = replaceValue({ + pattern: type === 'number' ? /\d/ : pattern, + value: event.currentTarget.value, + }); + + let isPrevented = false; + + if (value === replacedValue) { + event.preventDefault(); + + return; + } + + onValueChange?.({ + value: replacedValue, + prevent: () => { + isPrevented = true; + + event.preventDefault(); + }, + target: innerRef.current, + }); + + if (!isPrevented) { + setValue(replacedValue); + } + }, + ...domAttributeProps, + className, + }); } ); diff --git a/packages/vibrant-core/src/lib/convertStyleToClassName/convertStyleToClassName.ts b/packages/vibrant-core/src/lib/convertStyleToClassName/convertStyleToClassName.ts new file mode 100644 index 000000000..ef8b8a9ee --- /dev/null +++ b/packages/vibrant-core/src/lib/convertStyleToClassName/convertStyleToClassName.ts @@ -0,0 +1,15 @@ +import { css } from '@emotion/css'; +import { staticClassName } from '../../cssConstants'; + +export const convertStyleToClassName = (styleObj: Record) => + Object.entries(styleObj).map(([key, value]) => { + const staticClassName = `${key}-${value}`; + + if (isExistInStaticStyle(staticClassName)) { + return staticClassName; + } + + return css({ [key]: value }); + }); + +const isExistInStaticStyle = (value: string) => staticClassName.has(value); diff --git a/packages/vibrant-core/src/lib/convertStyleToClassName/index.ts b/packages/vibrant-core/src/lib/convertStyleToClassName/index.ts new file mode 100644 index 000000000..6b9699774 --- /dev/null +++ b/packages/vibrant-core/src/lib/convertStyleToClassName/index.ts @@ -0,0 +1 @@ +export { convertStyleToClassName } from './convertStyleToClassName'; diff --git a/yarn.lock b/yarn.lock index 71a03de30..0fad02343 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4278,6 +4278,25 @@ __metadata: languageName: node linkType: hard +"@emotion/babel-plugin@npm:^11.13.5": + version: 11.13.5 + resolution: "@emotion/babel-plugin@npm:11.13.5" + dependencies: + "@babel/helper-module-imports": ^7.16.7 + "@babel/runtime": ^7.18.3 + "@emotion/hash": ^0.9.2 + "@emotion/memoize": ^0.9.0 + "@emotion/serialize": ^1.3.3 + babel-plugin-macros: ^3.1.0 + convert-source-map: ^1.5.0 + escape-string-regexp: ^4.0.0 + find-root: ^1.1.0 + source-map: ^0.5.7 + stylis: 4.2.0 + checksum: c41df7e6c19520e76d1939f884be878bf88b5ba00bd3de9d05c5b6c5baa5051686ab124d7317a0645de1b017b574d8139ae1d6390ec267fbe8e85a5252afb542 + languageName: node + linkType: hard + "@emotion/cache@npm:11.9.3": version: 11.9.3 resolution: "@emotion/cache@npm:11.9.3" @@ -4304,6 +4323,19 @@ __metadata: languageName: node linkType: hard +"@emotion/cache@npm:^11.13.5": + version: 11.14.0 + resolution: "@emotion/cache@npm:11.14.0" + dependencies: + "@emotion/memoize": ^0.9.0 + "@emotion/sheet": ^1.4.0 + "@emotion/utils": ^1.4.2 + "@emotion/weak-memoize": ^0.4.0 + stylis: 4.2.0 + checksum: 0a81591541ea43bc7851742e6444b7800d72e98006f94e775ae6ea0806662d14e0a86ff940f5f19d33b4bb2c427c882aa65d417e7322a6e0d5f20fe65ed920c9 + languageName: node + linkType: hard + "@emotion/css-prettifier@npm:^1.0.1": version: 1.1.3 resolution: "@emotion/css-prettifier@npm:1.1.3" @@ -4314,6 +4346,19 @@ __metadata: languageName: node linkType: hard +"@emotion/css@npm:11.13.5": + version: 11.13.5 + resolution: "@emotion/css@npm:11.13.5" + dependencies: + "@emotion/babel-plugin": ^11.13.5 + "@emotion/cache": ^11.13.5 + "@emotion/serialize": ^1.3.3 + "@emotion/sheet": ^1.4.0 + "@emotion/utils": ^1.4.2 + checksum: 1f96c612603f2a6ad3e288c6ec90ac457e75e09b8a0bd4fb6e9bc1cd552ed9edd4a1e40880060ed30a285e1141e354a3b41a815f22871d2178a882e3c1f79426 + languageName: node + linkType: hard + "@emotion/hash@npm:^0.9.1": version: 0.9.1 resolution: "@emotion/hash@npm:0.9.1" @@ -4321,6 +4366,13 @@ __metadata: languageName: node linkType: hard +"@emotion/hash@npm:^0.9.2": + version: 0.9.2 + resolution: "@emotion/hash@npm:0.9.2" + checksum: 379bde2830ccb0328c2617ec009642321c0e009a46aa383dfbe75b679c6aea977ca698c832d225a893901f29d7b3eef0e38cf341f560f6b2b56f1ff23c172387 + languageName: node + linkType: hard + "@emotion/is-prop-valid@npm:^1.2.0": version: 1.2.1 resolution: "@emotion/is-prop-valid@npm:1.2.1" @@ -4365,6 +4417,13 @@ __metadata: languageName: node linkType: hard +"@emotion/memoize@npm:^0.9.0": + version: 0.9.0 + resolution: "@emotion/memoize@npm:0.9.0" + checksum: 038132359397348e378c593a773b1148cd0cf0a2285ffd067a0f63447b945f5278860d9de718f906a74c7c940ba1783ac2ca18f1c06a307b01cc0e3944e783b1 + languageName: node + linkType: hard + "@emotion/native@npm:11.9.3": version: 11.9.3 resolution: "@emotion/native@npm:11.9.3" @@ -4429,6 +4488,19 @@ __metadata: languageName: node linkType: hard +"@emotion/serialize@npm:^1.3.3": + version: 1.3.3 + resolution: "@emotion/serialize@npm:1.3.3" + dependencies: + "@emotion/hash": ^0.9.2 + "@emotion/memoize": ^0.9.0 + "@emotion/unitless": ^0.10.0 + "@emotion/utils": ^1.4.2 + csstype: ^3.0.2 + checksum: 510331233767ae4e09e925287ca2c7269b320fa1d737ea86db5b3c861a734483ea832394c0c1fe5b21468fe335624a75e72818831d303ba38125f54f44ba02e7 + languageName: node + linkType: hard + "@emotion/sheet@npm:^1.1.1, @emotion/sheet@npm:^1.2.2": version: 1.2.2 resolution: "@emotion/sheet@npm:1.2.2" @@ -4436,6 +4508,13 @@ __metadata: languageName: node linkType: hard +"@emotion/sheet@npm:^1.4.0": + version: 1.4.0 + resolution: "@emotion/sheet@npm:1.4.0" + checksum: eeb1212e3289db8e083e72e7e401cd6d1a84deece87e9ce184f7b96b9b5dbd6f070a89057255a6ff14d9865c3ce31f27c39248a053e4cdd875540359042586b4 + languageName: node + linkType: hard + "@emotion/styled@npm:11.10.4": version: 11.10.4 resolution: "@emotion/styled@npm:11.10.4" @@ -4459,6 +4538,13 @@ __metadata: languageName: node linkType: hard +"@emotion/unitless@npm:^0.10.0": + version: 0.10.0 + resolution: "@emotion/unitless@npm:0.10.0" + checksum: d79346df31a933e6d33518e92636afeb603ce043f3857d0a39a2ac78a09ef0be8bedff40130930cb25df1beeee12d96ee38613963886fa377c681a89970b787c + languageName: node + linkType: hard + "@emotion/unitless@npm:^0.8.1": version: 0.8.1 resolution: "@emotion/unitless@npm:0.8.1" @@ -4482,6 +4568,13 @@ __metadata: languageName: node linkType: hard +"@emotion/utils@npm:^1.4.2": + version: 1.4.2 + resolution: "@emotion/utils@npm:1.4.2" + checksum: 04cf76849c6401205c058b82689fd0ec5bf501aed6974880fe9681a1d61543efb97e848f4c38664ac4a9068c7ad2d1cb84f73bde6cf95f1208aa3c28e0190321 + languageName: node + linkType: hard + "@emotion/weak-memoize@npm:^0.2.5": version: 0.2.5 resolution: "@emotion/weak-memoize@npm:0.2.5" @@ -4496,6 +4589,13 @@ __metadata: languageName: node linkType: hard +"@emotion/weak-memoize@npm:^0.4.0": + version: 0.4.0 + resolution: "@emotion/weak-memoize@npm:0.4.0" + checksum: db5da0e89bd752c78b6bd65a1e56231f0abebe2f71c0bd8fc47dff96408f7065b02e214080f99924f6a3bfe7ee15afc48dad999d76df86b39b16e513f7a94f52 + languageName: node + linkType: hard + "@esbuild/android-arm@npm:0.15.18": version: 0.15.18 resolution: "@esbuild/android-arm@npm:0.15.18" @@ -16543,6 +16643,7 @@ __metadata: "@docusaurus/theme-live-codeblock": 2.1.0 "@electron/remote": 2.0.8 "@emotion/cache": 11.9.3 + "@emotion/css": 11.13.5 "@emotion/jest": 11.9.3 "@emotion/native": 11.9.3 "@emotion/react": 11.10.4