diff --git a/src/types/core.ts b/src/types/core.ts index a6996c85..20728d86 100644 --- a/src/types/core.ts +++ b/src/types/core.ts @@ -91,7 +91,17 @@ export type DimensionValue = | (string & {}); export type BorderRadiusValue = 'small' | 'medium'; - export type BorderColorValue = 'light' | 'dark'; - export type BackgroundColorValue = 'light' | 'dark'; + +export type ColorValue = + | 'gray-100' + | 'gray-200' + | 'gray-300' + | 'gray-400' + | 'gray-500' + | 'gray-600' + | 'gray-700' + | 'gray-800' + | 'gray-900' + | 'danger'; diff --git a/src/types/index.ts b/src/types/index.ts index 6a144e97..49a6b4fe 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -15,3 +15,4 @@ export * from './button'; export * from './style'; export * from './progress'; export * from './style'; +export * from './locale'; diff --git a/src/types/style.ts b/src/types/style.ts index 28c00a5d..b052043b 100644 --- a/src/types/style.ts +++ b/src/types/style.ts @@ -1,4 +1,9 @@ -import { DimensionValue } from './core'; +import { + BackgroundColorValue, + BorderColorValue, + BorderRadiusValue, + DimensionValue, +} from './core'; export interface StyleProps { /** Sets the CSS [className](https://developer.mozilla.org/en-US/docs/Web/API/Element/className) for the element. Only use as a **last resort**. **/ @@ -25,21 +30,21 @@ export interface ViewStyleProps extends StyleProps { backgroundColor?: Responsive; /** The width of the element's border on all four sides. See [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/border-width). */ - borderWidth?: Responsive; + // borderWidth?: Responsive; /** The width of the border on the logical start side, depending on the layout direction. See [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/border-inline-start-width). */ - borderStartWidth?: Responsive; + // borderStartWidth?: Responsive; /** The width of the border on the logical end side, depending on the layout direction. See [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/border-inline-end-width). */ - borderEndWidth?: Responsive; + // borderEndWidth?: Responsive; // borderLeftWidth?: BorderSizeValue, // borderRightWidth?: BorderSizeValue, /** The width of the top border. See [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/border-top-width). */ - borderTopWidth?: Responsive; + // borderTopWidth?: Responsive; /** The width of the bottom border. See [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/border-bottom-width). */ - borderBottomWidth?: Responsive; + // borderBottomWidth?: Responsive; /** The width of the left and right borders. See [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/border-width). */ - borderXWidth?: Responsive; + // borderXWidth?: Responsive; /** The width of the top and bottom borders. See [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/border-width). */ - borderYWidth?: Responsive; + // borderYWidth?: Responsive; /** The color of the element's border on all four sides. See [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/border-color). */ borderColor?: Responsive; diff --git a/src/utils/styleProps.ts b/src/utils/styleProps.ts index 1dc6388c..1e537342 100644 --- a/src/utils/styleProps.ts +++ b/src/utils/styleProps.ts @@ -1,5 +1,133 @@ import { CSSProperties } from 'react'; -import { DimensionValue } from '../types'; +import { + BackgroundColorValue, + BorderColorValue, + BorderRadiusValue, + ColorValue, + DimensionValue, + Direction, + Responsive, + ViewStyleProps, +} from '../types'; + +type Breakpoint = 'base' | 'S' | 'M' | 'L' | string; +type StyleName = string | string[] | ((dir: Direction) => string); +type StyleHandler = (value: any) => string; +export interface StyleHandlers { + [key: string]: [StyleName, StyleHandler]; +} + +export const baseStyleProps: StyleHandlers = { + margin: ['margin', dimensionValue], + marginStart: [rtl('marginLeft', 'marginRight'), dimensionValue], + marginEnd: [rtl('marginRight', 'marginLeft'), dimensionValue], + // marginLeft: ['marginLeft', dimensionValue], + // marginRight: ['marginRight', dimensionValue], + marginTop: ['marginTop', dimensionValue], + marginBottom: ['marginBottom', dimensionValue], + marginX: [['marginLeft', 'marginRight'], dimensionValue], + marginY: [['marginTop', 'marginBottom'], dimensionValue], + width: ['width', dimensionValue], + height: ['height', dimensionValue], + minWidth: ['minWidth', dimensionValue], + minHeight: ['minHeight', dimensionValue], + maxWidth: ['maxWidth', dimensionValue], + maxHeight: ['maxHeight', dimensionValue], + isHidden: ['display', hiddenValue], + alignSelf: ['alignSelf', passthroughStyle], + justifySelf: ['justifySelf', passthroughStyle], + position: ['position', anyValue], + zIndex: ['zIndex', anyValue], + top: ['top', dimensionValue], + bottom: ['bottom', dimensionValue], + start: [rtl('left', 'right'), dimensionValue], + end: [rtl('right', 'left'), dimensionValue], + left: ['left', dimensionValue], + right: ['right', dimensionValue], + order: ['order', anyValue], + flex: ['flex', flexValue], + flexGrow: ['flexGrow', passthroughStyle], + flexShrink: ['flexShrink', passthroughStyle], + flexBasis: ['flexBasis', passthroughStyle], + gridArea: ['gridArea', passthroughStyle], + gridColumn: ['gridColumn', passthroughStyle], + gridColumnEnd: ['gridColumnEnd', passthroughStyle], + gridColumnStart: ['gridColumnStart', passthroughStyle], + gridRow: ['gridRow', passthroughStyle], + gridRowEnd: ['gridRowEnd', passthroughStyle], + gridRowStart: ['gridRowStart', passthroughStyle], +}; + +export const viewStyleProps: StyleHandlers = { + ...baseStyleProps, + backgroundColor: ['backgroundColor', backgroundColorValue], + borderWidth: ['borderWidth', borderSizeValue], + borderStartWidth: [ + rtl('borderLeftWidth', 'borderRightWidth'), + borderSizeValue, + ], + borderEndWidth: [rtl('borderRightWidth', 'borderLeftWidth'), borderSizeValue], + borderLeftWidth: ['borderLeftWidth', borderSizeValue], + borderRightWidth: ['borderRightWidth', borderSizeValue], + borderTopWidth: ['borderTopWidth', borderSizeValue], + borderBottomWidth: ['borderBottomWidth', borderSizeValue], + borderXWidth: [['borderLeftWidth', 'borderRightWidth'], borderSizeValue], + borderYWidth: [['borderTopWidth', 'borderBottomWidth'], borderSizeValue], + borderColor: ['borderColor', borderColorValue], + borderStartColor: [ + rtl('borderLeftColor', 'borderRightColor'), + borderColorValue, + ], + borderEndColor: [ + rtl('borderRightColor', 'borderLeftColor'), + borderColorValue, + ], + borderLeftColor: ['borderLeftColor', borderColorValue], + borderRightColor: ['borderRightColor', borderColorValue], + borderTopColor: ['borderTopColor', borderColorValue], + borderBottomColor: ['borderBottomColor', borderColorValue], + borderXColor: [['borderLeftColor', 'borderRightColor'], borderColorValue], + borderYColor: [['borderTopColor', 'borderBottomColor'], borderColorValue], + borderRadius: ['borderRadius', borderRadiusValue], + borderTopStartRadius: [ + rtl('borderTopLeftRadius', 'borderTopRightRadius'), + borderRadiusValue, + ], + borderTopEndRadius: [ + rtl('borderTopRightRadius', 'borderTopLeftRadius'), + borderRadiusValue, + ], + borderBottomStartRadius: [ + rtl('borderBottomLeftRadius', 'borderBottomRightRadius'), + borderRadiusValue, + ], + borderBottomEndRadius: [ + rtl('borderBottomRightRadius', 'borderBottomLeftRadius'), + borderRadiusValue, + ], + borderTopLeftRadius: ['borderTopLeftRadius', borderRadiusValue], + borderTopRightRadius: ['borderTopRightRadius', borderRadiusValue], + borderBottomLeftRadius: ['borderBottomLeftRadius', borderRadiusValue], + borderBottomRightRadius: ['borderBottomRightRadius', borderRadiusValue], + padding: ['padding', dimensionValue], + paddingStart: [rtl('paddingLeft', 'paddingRight'), dimensionValue], + paddingEnd: [rtl('paddingRight', 'paddingLeft'), dimensionValue], + paddingLeft: ['paddingLeft', dimensionValue], + paddingRight: ['paddingRight', dimensionValue], + paddingTop: ['paddingTop', dimensionValue], + paddingBottom: ['paddingBottom', dimensionValue], + paddingX: [['paddingLeft', 'paddingRight'], dimensionValue], + paddingY: [['paddingTop', 'paddingBottom'], dimensionValue], + overflow: ['overflow', passthroughStyle], +}; + +const borderStyleProps = { + borderWidth: 'borderStyle', + borderLeftWidth: 'borderLeftStyle', + borderRightWidth: 'borderRightStyle', + borderTopWidth: 'borderTopStyle', + borderBottomWidth: 'borderBottomStyle', +}; const UNIT_RE = /(%|px|em|rem|vw|vh|auto|cm|mm|in|pt|pc|ex|ch|rem|vmin|vmax|fr)$/; const FUNC_RE = /^\s*\w+\(/; @@ -62,3 +190,56 @@ export function convertStyleProps( return style; } + +function rtl(ltr: string, rtl: string) { + return (direction: Direction) => (direction === 'rtl' ? rtl : ltr); +} + +type ColorType = 'default' | 'background' | 'border' | 'icon' | 'status'; +function colorValue(value: ColorValue, type: ColorType = 'default') { + // TODO actually support semantic colors + return `var(--ac-global-color-${value}, var(--ac-semantic-${value}-color-${type}))`; +} + +function backgroundColorValue(value: BackgroundColorValue) { + return `var(--ac-alias-background-color-${value}, ${colorValue( + value as ColorValue, + 'background' + )})`; +} + +function borderColorValue(value: BorderColorValue) { + // TODO support default color + // if (value === 'default') { + // return 'var(--ac-alias-border-color)'; + // } + + return `var(--ac-alias-border-color-${value}, ${colorValue( + value as ColorValue, + 'border' + )})`; +} + +// function borderSizeValue(value: BorderSizeValue) { +// return `var(--ac-alias-border-size-${value})`; +// } + +function borderRadiusValue(value: BorderRadiusValue) { + return `var(--ac-alias-border-radius-${value})`; +} + +export function getResponsiveProp( + prop: Responsive, + matchedBreakpoints: Breakpoint[] +): T { + if (prop && typeof prop === 'object' && !Array.isArray(prop)) { + for (let i = 0; i < matchedBreakpoints.length; i++) { + let breakpoint = matchedBreakpoints[i]; + if (prop[breakpoint] != null) { + return prop[breakpoint]; + } + } + return (prop as ResponsiveProp).base; + } + return prop as T; +}