components-test-pb 0.2.4 → 0.2.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/dist/components/Button/src/renderButton.d.ts +1 -1
  2. package/dist/components/Button/src/useButton.js +9 -10
  3. package/dist/components/Button/src/useButtonStyles.styles.js +5 -2
  4. package/dist/components/Text/Text.d.ts +2 -0
  5. package/dist/components/Text/Text.js +8 -0
  6. package/dist/components/Text/Text.types.d.ts +16 -0
  7. package/dist/components/Text/Text.types.js +1 -0
  8. package/dist/components/Text/index.d.ts +5 -0
  9. package/dist/components/Text/index.js +4 -0
  10. package/dist/components/Text/renderText.d.ts +3 -0
  11. package/dist/components/Text/renderText.js +6 -0
  12. package/dist/components/Text/useText.d.ts +2 -0
  13. package/dist/components/Text/useText.js +19 -0
  14. package/dist/components/Text/useTextStyles.styles.d.ts +4 -0
  15. package/dist/components/Text/useTextStyles.styles.js +71 -0
  16. package/dist/components/index.d.ts +3 -1
  17. package/dist/components/index.js +2 -0
  18. package/dist/index.d.ts +3 -1
  19. package/dist/index.js +2 -1
  20. package/dist/theme/defaultTheme.js +3 -0
  21. package/dist/theme/types.d.ts +3 -0
  22. package/dist/utilities/index.d.ts +1 -1
  23. package/dist/utilities/index.js +1 -1
  24. package/dist/utilities/src/compose/getIntrinsicElementProps.d.ts +2 -0
  25. package/dist/utilities/src/compose/getIntrinsicElementProps.js +53 -0
  26. package/dist/utilities/src/compose/index.d.ts +1 -0
  27. package/dist/utilities/src/compose/index.js +1 -0
  28. package/dist/utilities/src/index.d.ts +1 -1
  29. package/dist/utilities/src/index.js +1 -1
  30. package/package.json +1 -1
  31. package/src/components/Button/src/renderButton.tsx +2 -1
  32. package/src/components/Button/src/useButton.ts +15 -16
  33. package/src/components/Button/src/useButtonStyles.styles.ts +5 -2
  34. package/src/components/Text/Text.tsx +10 -0
  35. package/src/components/Text/Text.types.ts +34 -0
  36. package/src/components/Text/index.ts +9 -0
  37. package/src/components/Text/renderText.tsx +13 -0
  38. package/src/components/Text/useText.ts +25 -0
  39. package/src/components/Text/useTextStyles.styles.ts +100 -0
  40. package/src/components/index.ts +26 -7
  41. package/src/index.ts +15 -1
  42. package/src/theme/defaultTheme.ts +3 -0
  43. package/src/theme/types.ts +3 -0
  44. package/src/utilities/index.ts +1 -1
  45. package/src/utilities/src/compose/getIntrinsicElementProps.ts +67 -0
  46. package/src/utilities/src/compose/index.ts +1 -0
  47. package/src/utilities/src/index.ts +1 -1
@@ -1,3 +1,3 @@
1
- import { JSXElement } from '../../../utilities/src';
1
+ import type { JSXElement } from '../../../utilities/src';
2
2
  import type { ButtonState } from './Button.types';
3
3
  export declare const renderButton: (state: ButtonState) => JSXElement;
@@ -1,15 +1,14 @@
1
- import { slot, useARIAButtonProps } from '../../../utilities';
1
+ import { getIntrinsicElementProps, slot, useARIAButtonProps } from '../../../utilities';
2
2
  export const useButton = (props) => {
3
- const { appearance = 'secondary', disabled = false, shape = 'rounded', size = 'medium', ...rest } = props;
4
- const rootProps = slot.always(rest, {
5
- elementType: 'button',
6
- });
7
- return {
8
- appearance,
9
- disabled,
10
- shape,
11
- size,
3
+ const { appearance, disabled, shape, size } = props;
4
+ const rootProps = slot.always(getIntrinsicElementProps('button', props), { elementType: 'button' });
5
+ const state = {
6
+ appearance: appearance ?? 'secondary',
7
+ disabled: disabled ?? false,
8
+ shape: shape ?? 'rounded',
9
+ size: size ?? 'medium',
12
10
  components: { root: 'button' },
13
11
  root: useARIAButtonProps(rootProps.as ?? 'button', rootProps),
14
12
  };
13
+ return state;
15
14
  };
@@ -59,13 +59,16 @@ const useVariationStyles = makeStyles({
59
59
  ghost: {
60
60
  backgroundColor: tokens.colorTransparentBackground,
61
61
  ...shorthands.borderColor('transparent'),
62
+ color: tokens.colorNeutralForeground2,
62
63
  ':hover': {
63
64
  backgroundColor: tokens.colorTransparentBackgroundHover,
64
- ...shorthands.borderColor('transparent')
65
+ ...shorthands.borderColor('transparent'),
66
+ color: tokens.colorNeutralForeground2BrandHover
65
67
  },
66
68
  ':hover:active,:active:focus-visible': {
67
69
  backgroundColor: tokens.colorTransparentBackgroundPressed,
68
- ...shorthands.borderColor('transparent')
70
+ ...shorthands.borderColor('transparent'),
71
+ color: tokens.colorNeutralForeground2BrandPressed
69
72
  }
70
73
  },
71
74
  square: { borderRadius: 0 },
@@ -0,0 +1,2 @@
1
+ import type { TextProps } from './Text.types';
2
+ export declare const Text: (props: TextProps) => import("jsx-framework-test-pb").ValidElement;
@@ -0,0 +1,8 @@
1
+ import { useText } from './useText';
2
+ import { useTextStyles } from './useTextStyles.styles';
3
+ import { renderText } from './renderText';
4
+ export const Text = (props) => {
5
+ const state = useText(props);
6
+ useTextStyles(state);
7
+ return renderText(state);
8
+ };
@@ -0,0 +1,16 @@
1
+ import type { ComponentProps, ComponentState, Slot } from '../../utilities';
2
+ export type TextSlots = {
3
+ root: Slot<'span', 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'p' | 'pre' | 'strong' | 'b' | 'em' | 'i'>;
4
+ };
5
+ export type TextProps = ComponentProps<TextSlots> & {
6
+ font?: 'base' | 'monospace' | 'numeric';
7
+ italic?: boolean;
8
+ size?: 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | 1000;
9
+ strikethrough?: boolean;
10
+ truncate?: boolean;
11
+ underline?: boolean;
12
+ weight?: 'regular' | 'medium' | 'semibold' | 'bold';
13
+ wrap?: boolean;
14
+ };
15
+ export type TextPresetprops = Omit<TextProps, 'font' | 'size' | 'weight'>;
16
+ export type TextState = ComponentState<TextSlots> & Required<Pick<TextProps, 'font' | 'italic' | 'size' | 'strikethrough' | 'truncate' | 'underline' | 'weight' | 'wrap'>>;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,5 @@
1
+ export { Text } from './Text';
2
+ export { useText } from './useText';
3
+ export { renderText } from './renderText';
4
+ export { useTextStyles, textClassNames } from './useTextStyles.styles';
5
+ export type { TextSlots, TextProps, TextState, } from './Text.types';
@@ -0,0 +1,4 @@
1
+ export { Text } from './Text';
2
+ export { useText } from './useText';
3
+ export { renderText } from './renderText';
4
+ export { useTextStyles, textClassNames } from './useTextStyles.styles';
@@ -0,0 +1,3 @@
1
+ import type { JSXElement } from '../../utilities/src/compose/types';
2
+ import type { TextState } from './Text.types';
3
+ export declare const renderText: (state: TextState) => JSXElement;
@@ -0,0 +1,6 @@
1
+ import { jsx as _jsx } from "jsx-framework-test-pb/jsx-runtime";
2
+ import { assertSlots } from '../../utilities/src';
3
+ export const renderText = (state) => {
4
+ assertSlots(state);
5
+ return (_jsx(state.root, { children: state.root.children }));
6
+ };
@@ -0,0 +1,2 @@
1
+ import type { TextProps, TextState } from './Text.types';
2
+ export declare const useText: (props: TextProps) => TextState;
@@ -0,0 +1,19 @@
1
+ import { getIntrinsicElementProps, slot } from '../../utilities';
2
+ export const useText = (props) => {
3
+ const { wrap, truncate, italic, underline, strikethrough, size, font, weight } = props;
4
+ const state = {
5
+ font: font ?? 'base',
6
+ italic: italic ?? false,
7
+ size: size ?? 300,
8
+ strikethrough: strikethrough ?? false,
9
+ truncate: truncate ?? false,
10
+ underline: underline ?? false,
11
+ weight: weight ?? 'regular',
12
+ wrap: wrap ?? false,
13
+ components: { root: 'span' },
14
+ root: slot.always(getIntrinsicElementProps('span', props), {
15
+ elementType: 'span',
16
+ })
17
+ };
18
+ return state;
19
+ };
@@ -0,0 +1,4 @@
1
+ import type { SlotClassNames } from '../../utilities';
2
+ import type { TextSlots, TextState } from './Text.types';
3
+ export declare const textClassNames: SlotClassNames<TextSlots>;
4
+ export declare const useTextStyles: (state: TextState) => TextState;
@@ -0,0 +1,71 @@
1
+ import { makeResetStyles, makeStyles, mergeClasses } from 'css-engine-test-pb';
2
+ import { tokens } from '../../theme';
3
+ export const textClassNames = {
4
+ root: 'c-text',
5
+ };
6
+ const useResetStyles = makeResetStyles({
7
+ fontFamily: tokens.fontFamilyBase,
8
+ fontSize: tokens.fontSizeBase300,
9
+ fontWeight: tokens.fontWeightRegular,
10
+ lineHeight: tokens.lineHeightBase300,
11
+ color: tokens.colorNeutralForeground1,
12
+ textAlign: 'start',
13
+ whiteSpace: 'normal',
14
+ overflow: 'visible',
15
+ textOverflow: 'clip',
16
+ margin: 0,
17
+ padding: 0,
18
+ display: 'inline',
19
+ });
20
+ const useVariationStyles = makeStyles({
21
+ base: { fontFamily: tokens.fontFamilyBase },
22
+ monospace: { fontFamily: tokens.fontFamilyMonospace },
23
+ numeric: { fontFamily: tokens.fontFamilyNumeric },
24
+ 100: {
25
+ fontSize: tokens.fontSizeBase100,
26
+ lineHeight: tokens.lineHeightBase100,
27
+ },
28
+ 200: {
29
+ fontSize: tokens.fontSizeBase200,
30
+ lineHeight: tokens.lineHeightBase200,
31
+ },
32
+ 300: {
33
+ fontSize: tokens.fontSizeBase300,
34
+ lineHeight: tokens.lineHeightBase300,
35
+ },
36
+ 400: {
37
+ fontSize: tokens.fontSizeBase400,
38
+ lineHeight: tokens.lineHeightBase400,
39
+ },
40
+ 500: {
41
+ fontSize: tokens.fontSizeBase500,
42
+ lineHeight: tokens.lineHeightBase500,
43
+ },
44
+ 600: {
45
+ fontSize: tokens.fontSizeBase600,
46
+ lineHeight: tokens.lineHeightBase600,
47
+ },
48
+ regular: { fontWeight: tokens.fontWeightRegular },
49
+ medium: { fontWeight: tokens.fontWeightMedium },
50
+ semibold: { fontWeight: tokens.fontWeightSemibold },
51
+ bold: { fontWeight: tokens.fontWeightBold },
52
+ italic: { fontStyle: 'italic' },
53
+ strikethrough: { textDecorationLine: 'line-through' },
54
+ underline: { textDecorationLine: 'underline' },
55
+ strikethroughUnderline: { textDecorationLine: 'line-through underline' },
56
+ truncate: {
57
+ overflow: 'hidden',
58
+ textOverflow: 'ellipsis',
59
+ whiteSpace: 'nowrap',
60
+ },
61
+ nowrap: {
62
+ whiteSpace: 'nowrap',
63
+ },
64
+ });
65
+ export const useTextStyles = (state) => {
66
+ const resetStyles = useResetStyles();
67
+ const styles = useVariationStyles();
68
+ const { font, italic, size, strikethrough, truncate, underline, weight, wrap } = state;
69
+ state.root.className = mergeClasses(textClassNames.root, resetStyles, styles[font], styles[size], styles[weight], italic && styles.italic, strikethrough && !underline && styles.strikethrough, underline && !strikethrough && styles.underline, strikethrough && underline && styles.strikethroughUnderline, truncate && styles.truncate, !wrap && styles.nowrap, state.root.className);
70
+ return state;
71
+ };
@@ -1,2 +1,4 @@
1
- export { Button, useButton, renderButton, useButtonStyles, buttonClassNames, } from './Button/src';
2
1
  export type { ButtonSlots, ButtonAppearance, ButtonShape, ButtonSize, ButtonProps, ButtonState, } from './Button/src';
2
+ export { Button, useButton, renderButton, useButtonStyles, buttonClassNames, } from './Button/src';
3
+ export type { TextSlots, TextProps, TextState, } from './Text';
4
+ export { Text, useText, renderText, useTextStyles, textClassNames, } from './Text';
@@ -1 +1,3 @@
1
+ // <Button />
1
2
  export { Button, useButton, renderButton, useButtonStyles, buttonClassNames, } from './Button/src';
3
+ export { Text, useText, renderText, useTextStyles, textClassNames, } from './Text';
package/dist/index.d.ts CHANGED
@@ -1,6 +1,8 @@
1
- export { assertSlots, slot, useARIAButtonProps } from './utilities';
1
+ export { assertSlots, getIntrinsicElementProps, slot, useARIAButtonProps } from './utilities';
2
2
  export { tokens, defaultTheme, themeToCSS, insertTheme } from './theme';
3
3
  export type { Theme } from './theme';
4
4
  export { Button, useButton, renderButton, useButtonStyles, buttonClassNames, } from './components';
5
5
  export type { ButtonSlots, ButtonAppearance, ButtonShape, ButtonSize, ButtonProps, ButtonState, } from './components';
6
+ export { Text, useText, renderText, useTextStyles, textClassNames, } from './components';
7
+ export type { TextSlots, TextProps, TextState, } from './components';
6
8
  export type { JSXIntrinsicElementKeys, JSXIntrinsicElement, SlotRenderFunction, SlotPropsRecord, SlotShorthandValue, UnknownSlotProps, WithSlotRenderFunction, WithoutSlotRenderFunction, IsSingleton, AsIntrinsicElement, Slot, ExtractSlotProps, ComponentProps, ComponentState, SlotClassNames, EventData, EventHandler, DistributiveOmit, UnionToIntersection, ARIAButtonType, ARIAButtonElement, ARIAButtonElementIntersection, ARIAButtonProps, ARIAButtonSlotProps, ARIAButtonAlteredProps, ARIAButtonResultProps, } from './utilities';
package/dist/index.js CHANGED
@@ -1,3 +1,4 @@
1
- export { assertSlots, slot, useARIAButtonProps } from './utilities';
1
+ export { assertSlots, getIntrinsicElementProps, slot, useARIAButtonProps } from './utilities';
2
2
  export { tokens, defaultTheme, themeToCSS, insertTheme } from './theme';
3
3
  export { Button, useButton, renderButton, useButtonStyles, buttonClassNames, } from './components';
4
+ export { Text, useText, renderText, useTextStyles, textClassNames, } from './components';
@@ -16,6 +16,9 @@ export const defaultTheme = {
16
16
  colorNeutralForeground2: '#424242',
17
17
  colorNeutralForeground2Hover: '#242424',
18
18
  colorNeutralForeground2Pressed: '#242424',
19
+ colorNeutralForeground2BrandHover: '#0f6cbd',
20
+ colorNeutralForeground2BrandPressed: '#0c3b5e',
21
+ colorNeutralForeground2BrandSelected: '#0f548c',
19
22
  colorNeutralForeground3: '#616161',
20
23
  colorNeutralForegroundDisabled: '#bdbdbd',
21
24
  // Colors — Neutral Background
@@ -14,6 +14,9 @@ export interface Theme {
14
14
  colorNeutralForeground2: string;
15
15
  colorNeutralForeground2Hover: string;
16
16
  colorNeutralForeground2Pressed: string;
17
+ colorNeutralForeground2BrandHover: string;
18
+ colorNeutralForeground2BrandPressed: string;
19
+ colorNeutralForeground2BrandSelected: string;
17
20
  colorNeutralForeground3: string;
18
21
  colorNeutralForegroundDisabled: string;
19
22
  colorNeutralBackground1: string;
@@ -1,2 +1,2 @@
1
- export { assertSlots, slot, useARIAButtonProps } from './src';
1
+ export { assertSlots, getIntrinsicElementProps, slot, useARIAButtonProps } from './src';
2
2
  export type { JSXIntrinsicElementKeys, JSXIntrinsicElement, SlotRenderFunction, SlotPropsRecord, SlotShorthandValue, UnknownSlotProps, WithSlotRenderFunction, WithoutSlotRenderFunction, IsSingleton, AsIntrinsicElement, Slot, ExtractSlotProps, ComponentProps, ComponentState, SlotClassNames, EventData, EventHandler, DistributiveOmit, UnionToIntersection, ARIAButtonType, ARIAButtonElement, ARIAButtonElementIntersection, ARIAButtonProps, ARIAButtonSlotProps, ARIAButtonAlteredProps, ARIAButtonResultProps, } from './src';
@@ -1 +1 @@
1
- export { assertSlots, slot, useARIAButtonProps } from './src';
1
+ export { assertSlots, getIntrinsicElementProps, slot, useARIAButtonProps } from './src';
@@ -0,0 +1,2 @@
1
+ import type { UnknownSlotProps, JSXIntrinsicElementKeys } from './types';
2
+ export declare function getIntrinsicElementProps<Props extends UnknownSlotProps & Record<string, any>>(tagName: JSXIntrinsicElementKeys, props: Props): Props;
@@ -0,0 +1,53 @@
1
+ // Global HTML attributes valid on all elements
2
+ const nativeProps = new Set([
3
+ // Core
4
+ 'as', 'children', 'className', 'style', 'id', 'key',
5
+ // HTML global attributes
6
+ 'accessKey', 'autoFocus', 'contentEditable', 'dir', 'draggable',
7
+ 'hidden', 'lang', 'nonce', 'placeholder', 'slot', 'spellCheck',
8
+ 'tabIndex', 'title', 'translate', 'role',
9
+ // Data & ARIA (handled separately via prefix check)
10
+ // Event handlers
11
+ 'onAbort', 'onAnimationEnd', 'onAnimationIteration', 'onAnimationStart',
12
+ 'onBlur', 'onChange', 'onClick', 'onCompositionEnd', 'onCompositionStart',
13
+ 'onCompositionUpdate', 'onContextMenu', 'onCopy', 'onCut', 'onDoubleClick',
14
+ 'onDrag', 'onDragEnd', 'onDragEnter', 'onDragExit', 'onDragLeave',
15
+ 'onDragOver', 'onDragStart', 'onDrop', 'onError', 'onFocus', 'onFocusIn',
16
+ 'onFocusOut', 'onGotPointerCapture', 'onInput', 'onInvalid', 'onKeyDown',
17
+ 'onKeyPress', 'onKeyUp', 'onLoad', 'onLostPointerCapture', 'onMouseDown',
18
+ 'onMouseEnter', 'onMouseLeave', 'onMouseMove', 'onMouseOut', 'onMouseOver',
19
+ 'onMouseUp', 'onPaste', 'onPointerCancel', 'onPointerDown', 'onPointerEnter',
20
+ 'onPointerLeave', 'onPointerMove', 'onPointerOut', 'onPointerOver',
21
+ 'onPointerUp', 'onScroll', 'onSelect', 'onSubmit', 'onTouchCancel',
22
+ 'onTouchEnd', 'onTouchMove', 'onTouchStart', 'onTransitionEnd', 'onWheel',
23
+ // Form element attributes
24
+ 'accept', 'acceptCharset', 'action', 'allowFullScreen', 'alt', 'async',
25
+ 'autoCapitalize', 'autoComplete', 'autoPlay', 'capture', 'cellPadding',
26
+ 'cellSpacing', 'charSet', 'checked', 'cite', 'colSpan', 'cols', 'controls',
27
+ 'coords', 'crossOrigin', 'dateTime', 'default', 'defer', 'disabled',
28
+ 'download', 'encType', 'form', 'formAction', 'formEncType', 'formMethod',
29
+ 'formNoValidate', 'formTarget', 'frameBorder', 'headers', 'height', 'high',
30
+ 'href', 'hrefLang', 'htmlFor', 'httpEquiv', 'icon', 'inputMode', 'integrity',
31
+ 'is', 'kind', 'label', 'list', 'loop', 'low', 'max', 'maxLength', 'media',
32
+ 'method', 'min', 'minLength', 'multiple', 'muted', 'name', 'noValidate',
33
+ 'open', 'optimum', 'pattern', 'playsInline', 'poster', 'preload',
34
+ 'readOnly', 'rel', 'required', 'reversed', 'rowSpan', 'rows', 'sandbox',
35
+ 'scope', 'scoped', 'scrolling', 'seamless', 'selected', 'shape', 'size',
36
+ 'sizes', 'span', 'src', 'srcDoc', 'srcLang', 'srcSet', 'start', 'step',
37
+ 'summary', 'target', 'type', 'useMap', 'value', 'width', 'wrap',
38
+ ]);
39
+ function isNativeProp(key) {
40
+ return nativeProps.has(key) || key.startsWith('data-') || key.startsWith('aria-');
41
+ }
42
+ export function getIntrinsicElementProps(tagName, props) {
43
+ const result = {};
44
+ for (const key of Object.keys(props)) {
45
+ if (isNativeProp(key)) {
46
+ result[key] = props[key];
47
+ }
48
+ }
49
+ if (!result.as) {
50
+ result.as = tagName;
51
+ }
52
+ return result;
53
+ }
@@ -1,3 +1,4 @@
1
1
  export { assertSlots } from './assertSlots';
2
+ export { getIntrinsicElementProps } from './getIntrinsicElementProps';
2
3
  export { slot } from './slot';
3
4
  export type { JSXIntrinsicElementKeys, JSXIntrinsicElement, SlotRenderFunction, SlotPropsRecord, SlotShorthandValue, UnknownSlotProps, WithSlotRenderFunction, WithoutSlotRenderFunction, IsSingleton, AsIntrinsicElement, Slot, ExtractSlotProps, ComponentProps, ComponentState, SlotClassNames, EventData, EventHandler, DistributiveOmit, UnionToIntersection, JSXElement, } from './types';
@@ -1,2 +1,3 @@
1
1
  export { assertSlots } from './assertSlots';
2
+ export { getIntrinsicElementProps } from './getIntrinsicElementProps';
2
3
  export { slot } from './slot';
@@ -1,4 +1,4 @@
1
- export { assertSlots, slot } from './compose';
1
+ export { assertSlots, getIntrinsicElementProps, slot } from './compose';
2
2
  export { useARIAButtonProps } from './ARIA';
3
3
  export type { JSXIntrinsicElementKeys, JSXIntrinsicElement, SlotRenderFunction, SlotPropsRecord, SlotShorthandValue, UnknownSlotProps, WithSlotRenderFunction, WithoutSlotRenderFunction, IsSingleton, AsIntrinsicElement, Slot, ExtractSlotProps, ComponentProps, ComponentState, SlotClassNames, EventData, EventHandler, DistributiveOmit, UnionToIntersection, JSXElement, } from './compose';
4
4
  export type { ARIAButtonType, ARIAButtonElement, ARIAButtonElementIntersection, ARIAButtonProps, ARIAButtonSlotProps, ARIAButtonAlteredProps, ARIAButtonResultProps, } from './ARIA';
@@ -1,2 +1,2 @@
1
- export { assertSlots, slot } from './compose';
1
+ export { assertSlots, getIntrinsicElementProps, slot } from './compose';
2
2
  export { useARIAButtonProps } from './ARIA';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "components-test-pb",
3
- "version": "0.2.4",
3
+ "version": "0.2.6",
4
4
  "description": "",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -1,4 +1,5 @@
1
- import { assertSlots, JSXElement } from '../../../utilities/src';
1
+ import { assertSlots } from '../../../utilities/src';
2
+ import type { JSXElement } from '../../../utilities/src';
2
3
  import type { ButtonSlots, ButtonState } from './Button.types';
3
4
 
4
5
  export const renderButton = (state: ButtonState): JSXElement => {
@@ -1,26 +1,25 @@
1
- import { slot, useARIAButtonProps } from '../../../utilities';
1
+ import { getIntrinsicElementProps, slot, useARIAButtonProps } from '../../../utilities';
2
2
  import type { ARIAButtonSlotProps } from '../../../utilities';
3
3
  import type { ButtonProps, ButtonState } from './Button.types';
4
4
 
5
5
  export const useButton = (props: ButtonProps): ButtonState => {
6
- const {
7
- appearance = 'secondary',
8
- disabled = false,
9
- shape = 'rounded',
10
- size = 'medium',
11
- ...rest
12
- } = props;
6
+ const { appearance, disabled, shape, size } = props;
13
7
 
14
- const rootProps = slot.always<ARIAButtonSlotProps<'a'>>(rest, {
15
- elementType: 'button',
16
- });
8
+ const rootProps = slot.always<ARIAButtonSlotProps<'a'>>(
9
+ getIntrinsicElementProps('button', props),
10
+ { elementType: 'button' },
11
+ );
12
+
13
+ const state: ButtonState = {
14
+ appearance: appearance ?? 'secondary',
15
+ disabled: disabled ?? false,
16
+ shape: shape ?? 'rounded',
17
+ size: size ?? 'medium',
17
18
 
18
- return {
19
- appearance,
20
- disabled,
21
- shape,
22
- size,
23
19
  components: { root: 'button' },
20
+
24
21
  root: useARIAButtonProps(rootProps.as ?? 'button', rootProps) as ButtonState['root'],
25
22
  };
23
+
24
+ return state;
26
25
  };
@@ -76,15 +76,18 @@ const useVariationStyles = makeStyles({
76
76
  ghost: {
77
77
  backgroundColor: tokens.colorTransparentBackground,
78
78
  ...shorthands.borderColor('transparent'),
79
+ color: tokens.colorNeutralForeground2,
79
80
 
80
81
  ':hover': {
81
82
  backgroundColor: tokens.colorTransparentBackgroundHover,
82
- ...shorthands.borderColor('transparent')
83
+ ...shorthands.borderColor('transparent'),
84
+ color: tokens.colorNeutralForeground2BrandHover
83
85
  },
84
86
 
85
87
  ':hover:active,:active:focus-visible': {
86
88
  backgroundColor: tokens.colorTransparentBackgroundPressed,
87
- ...shorthands.borderColor('transparent')
89
+ ...shorthands.borderColor('transparent'),
90
+ color: tokens.colorNeutralForeground2BrandPressed
88
91
  }
89
92
  },
90
93
 
@@ -0,0 +1,10 @@
1
+ import type { TextProps } from './Text.types';
2
+ import { useText } from './useText';
3
+ import { useTextStyles } from './useTextStyles.styles';
4
+ import { renderText } from './renderText';
5
+
6
+ export const Text = (props: TextProps) => {
7
+ const state = useText(props);
8
+ useTextStyles(state);
9
+ return renderText(state);
10
+ };
@@ -0,0 +1,34 @@
1
+ import type { ComponentProps, ComponentState, Slot } from '../../utilities'
2
+
3
+
4
+ export type TextSlots = {
5
+ root: Slot<'span', 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'p' | 'pre' | 'strong' | 'b' | 'em' | 'i'>;
6
+ };
7
+
8
+ export type TextProps = ComponentProps<TextSlots> & {
9
+ font?: 'base' | 'monospace' | 'numeric';
10
+
11
+ italic?: boolean;
12
+
13
+ size?: 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | 1000;
14
+
15
+ strikethrough?: boolean;
16
+
17
+ truncate?: boolean;
18
+
19
+ underline?: boolean;
20
+
21
+ weight?: 'regular' | 'medium' | 'semibold' | 'bold';
22
+
23
+ wrap?: boolean;
24
+ };
25
+
26
+ export type TextPresetprops = Omit<TextProps, 'font' | 'size' | 'weight'>;
27
+
28
+ export type TextState = ComponentState<TextSlots> &
29
+ Required<
30
+ Pick<
31
+ TextProps,
32
+ 'font' | 'italic' | 'size' | 'strikethrough' | 'truncate' | 'underline' | 'weight' | 'wrap'
33
+ >
34
+ >;
@@ -0,0 +1,9 @@
1
+ export { Text } from './Text';
2
+ export { useText } from './useText';
3
+ export { renderText } from './renderText';
4
+ export { useTextStyles, textClassNames } from './useTextStyles.styles';
5
+ export type {
6
+ TextSlots,
7
+ TextProps,
8
+ TextState,
9
+ } from './Text.types';
@@ -0,0 +1,13 @@
1
+ import { assertSlots } from '../../utilities/src';
2
+ import type { JSXElement } from '../../utilities/src/compose/types';
3
+ import type { TextSlots, TextState } from './Text.types';
4
+
5
+ export const renderText = (state: TextState): JSXElement => {
6
+ assertSlots<TextSlots>(state);
7
+
8
+ return (
9
+ <state.root>
10
+ {state.root.children}
11
+ </state.root>
12
+ );
13
+ };
@@ -0,0 +1,25 @@
1
+ import { getIntrinsicElementProps, slot } from '../../utilities';
2
+ import type { TextProps, TextState } from './Text.types';
3
+
4
+ export const useText = (props: TextProps): TextState => {
5
+ const { wrap, truncate, italic, underline, strikethrough, size, font, weight } = props;
6
+
7
+ const state: TextState = {
8
+ font: font ?? 'base',
9
+ italic: italic ?? false,
10
+ size: size ?? 300,
11
+ strikethrough: strikethrough ?? false,
12
+ truncate: truncate ?? false,
13
+ underline: underline ?? false,
14
+ weight: weight ?? 'regular',
15
+ wrap: wrap ?? false,
16
+
17
+ components: { root: 'span' },
18
+
19
+ root: slot.always(getIntrinsicElementProps('span', props), {
20
+ elementType: 'span',
21
+ })
22
+ };
23
+
24
+ return state;
25
+ };
@@ -0,0 +1,100 @@
1
+ import { makeResetStyles, makeStyles, mergeClasses } from 'css-engine-test-pb';
2
+ import type { SlotClassNames } from '../../utilities';
3
+ import type { TextSlots, TextState } from './Text.types';
4
+ import { tokens } from '../../theme';
5
+
6
+ export const textClassNames: SlotClassNames<TextSlots> = {
7
+ root: 'c-text',
8
+ };
9
+
10
+ const useResetStyles = makeResetStyles({
11
+ fontFamily: tokens.fontFamilyBase,
12
+ fontSize: tokens.fontSizeBase300,
13
+ fontWeight: tokens.fontWeightRegular,
14
+ lineHeight: tokens.lineHeightBase300,
15
+ color: tokens.colorNeutralForeground1,
16
+ textAlign: 'start',
17
+ whiteSpace: 'normal',
18
+ overflow: 'visible',
19
+ textOverflow: 'clip',
20
+ margin: 0,
21
+ padding: 0,
22
+ display: 'inline',
23
+ });
24
+
25
+ const useVariationStyles = makeStyles({
26
+ base: { fontFamily: tokens.fontFamilyBase },
27
+ monospace: { fontFamily: tokens.fontFamilyMonospace },
28
+ numeric: { fontFamily: tokens.fontFamilyNumeric },
29
+
30
+ 100: {
31
+ fontSize: tokens.fontSizeBase100,
32
+ lineHeight: tokens.lineHeightBase100,
33
+ },
34
+ 200: {
35
+ fontSize: tokens.fontSizeBase200,
36
+ lineHeight: tokens.lineHeightBase200,
37
+ },
38
+ 300: {
39
+ fontSize: tokens.fontSizeBase300,
40
+ lineHeight: tokens.lineHeightBase300,
41
+ },
42
+ 400: {
43
+ fontSize: tokens.fontSizeBase400,
44
+ lineHeight: tokens.lineHeightBase400,
45
+ },
46
+ 500: {
47
+ fontSize: tokens.fontSizeBase500,
48
+ lineHeight: tokens.lineHeightBase500,
49
+ },
50
+ 600: {
51
+ fontSize: tokens.fontSizeBase600,
52
+ lineHeight: tokens.lineHeightBase600,
53
+ },
54
+
55
+ regular: { fontWeight: tokens.fontWeightRegular },
56
+ medium: { fontWeight: tokens.fontWeightMedium },
57
+ semibold: { fontWeight: tokens.fontWeightSemibold },
58
+ bold: { fontWeight: tokens.fontWeightBold },
59
+
60
+ italic: { fontStyle: 'italic' },
61
+ strikethrough: { textDecorationLine: 'line-through' },
62
+ underline: { textDecorationLine: 'underline' },
63
+ strikethroughUnderline: { textDecorationLine: 'line-through underline' },
64
+
65
+ truncate: {
66
+ overflow: 'hidden',
67
+ textOverflow: 'ellipsis',
68
+ whiteSpace: 'nowrap',
69
+ },
70
+ nowrap: {
71
+ whiteSpace: 'nowrap',
72
+ },
73
+ });
74
+
75
+ export const useTextStyles = (state: TextState): TextState => {
76
+ const resetStyles = useResetStyles();
77
+ const styles = useVariationStyles();
78
+
79
+ const { font, italic, size, strikethrough, truncate, underline, weight, wrap } = state;
80
+
81
+ state.root.className = mergeClasses(
82
+ textClassNames.root,
83
+ resetStyles,
84
+
85
+ styles[font],
86
+ styles[size],
87
+ styles[weight],
88
+
89
+ italic && styles.italic,
90
+ strikethrough && !underline && styles.strikethrough,
91
+ underline && !strikethrough && styles.underline,
92
+ strikethrough && underline && styles.strikethroughUnderline,
93
+ truncate && styles.truncate,
94
+ !wrap && styles.nowrap,
95
+
96
+ state.root.className,
97
+ );
98
+
99
+ return state;
100
+ };
@@ -1,10 +1,4 @@
1
- export {
2
- Button,
3
- useButton,
4
- renderButton,
5
- useButtonStyles,
6
- buttonClassNames,
7
- } from './Button/src';
1
+ // <Button />
8
2
 
9
3
  export type {
10
4
  ButtonSlots,
@@ -14,3 +8,28 @@ export type {
14
8
  ButtonProps,
15
9
  ButtonState,
16
10
  } from './Button/src';
11
+
12
+ export {
13
+ Button,
14
+ useButton,
15
+ renderButton,
16
+ useButtonStyles,
17
+ buttonClassNames,
18
+ } from './Button/src';
19
+
20
+ // <Text />
21
+
22
+ export type {
23
+ TextSlots,
24
+ TextProps,
25
+ TextState,
26
+ } from './Text';
27
+
28
+ export {
29
+ Text,
30
+ useText,
31
+ renderText,
32
+ useTextStyles,
33
+ textClassNames,
34
+ } from './Text';
35
+
package/src/index.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { assertSlots, slot, useARIAButtonProps } from './utilities';
1
+ export { assertSlots, getIntrinsicElementProps, slot, useARIAButtonProps } from './utilities';
2
2
 
3
3
  export { tokens, defaultTheme, themeToCSS, insertTheme } from './theme';
4
4
  export type { Theme } from './theme';
@@ -20,6 +20,20 @@ export type {
20
20
  ButtonState,
21
21
  } from './components';
22
22
 
23
+ export {
24
+ Text,
25
+ useText,
26
+ renderText,
27
+ useTextStyles,
28
+ textClassNames,
29
+ } from './components';
30
+
31
+ export type {
32
+ TextSlots,
33
+ TextProps,
34
+ TextState,
35
+ } from './components';
36
+
23
37
  export type {
24
38
  JSXIntrinsicElementKeys,
25
39
  JSXIntrinsicElement,
@@ -19,6 +19,9 @@ export const defaultTheme: Theme = {
19
19
  colorNeutralForeground2: '#424242',
20
20
  colorNeutralForeground2Hover: '#242424',
21
21
  colorNeutralForeground2Pressed: '#242424',
22
+ colorNeutralForeground2BrandHover: '#0f6cbd',
23
+ colorNeutralForeground2BrandPressed: '#0c3b5e',
24
+ colorNeutralForeground2BrandSelected: '#0f548c',
22
25
  colorNeutralForeground3: '#616161',
23
26
  colorNeutralForegroundDisabled: '#bdbdbd',
24
27
 
@@ -17,6 +17,9 @@ export interface Theme {
17
17
  colorNeutralForeground2: string;
18
18
  colorNeutralForeground2Hover: string;
19
19
  colorNeutralForeground2Pressed: string;
20
+ colorNeutralForeground2BrandHover: string;
21
+ colorNeutralForeground2BrandPressed: string;
22
+ colorNeutralForeground2BrandSelected: string;
20
23
  colorNeutralForeground3: string;
21
24
  colorNeutralForegroundDisabled: string;
22
25
 
@@ -1,4 +1,4 @@
1
- export { assertSlots, slot, useARIAButtonProps } from './src';
1
+ export { assertSlots, getIntrinsicElementProps, slot, useARIAButtonProps } from './src';
2
2
 
3
3
  export type {
4
4
  JSXIntrinsicElementKeys,
@@ -0,0 +1,67 @@
1
+ import type { UnknownSlotProps, JSXIntrinsicElementKeys } from './types';
2
+
3
+ // Global HTML attributes valid on all elements
4
+ const nativeProps = new Set([
5
+ // Core
6
+ 'as', 'children', 'className', 'style', 'id', 'key',
7
+
8
+ // HTML global attributes
9
+ 'accessKey', 'autoFocus', 'contentEditable', 'dir', 'draggable',
10
+ 'hidden', 'lang', 'nonce', 'placeholder', 'slot', 'spellCheck',
11
+ 'tabIndex', 'title', 'translate', 'role',
12
+
13
+ // Data & ARIA (handled separately via prefix check)
14
+
15
+ // Event handlers
16
+ 'onAbort', 'onAnimationEnd', 'onAnimationIteration', 'onAnimationStart',
17
+ 'onBlur', 'onChange', 'onClick', 'onCompositionEnd', 'onCompositionStart',
18
+ 'onCompositionUpdate', 'onContextMenu', 'onCopy', 'onCut', 'onDoubleClick',
19
+ 'onDrag', 'onDragEnd', 'onDragEnter', 'onDragExit', 'onDragLeave',
20
+ 'onDragOver', 'onDragStart', 'onDrop', 'onError', 'onFocus', 'onFocusIn',
21
+ 'onFocusOut', 'onGotPointerCapture', 'onInput', 'onInvalid', 'onKeyDown',
22
+ 'onKeyPress', 'onKeyUp', 'onLoad', 'onLostPointerCapture', 'onMouseDown',
23
+ 'onMouseEnter', 'onMouseLeave', 'onMouseMove', 'onMouseOut', 'onMouseOver',
24
+ 'onMouseUp', 'onPaste', 'onPointerCancel', 'onPointerDown', 'onPointerEnter',
25
+ 'onPointerLeave', 'onPointerMove', 'onPointerOut', 'onPointerOver',
26
+ 'onPointerUp', 'onScroll', 'onSelect', 'onSubmit', 'onTouchCancel',
27
+ 'onTouchEnd', 'onTouchMove', 'onTouchStart', 'onTransitionEnd', 'onWheel',
28
+
29
+ // Form element attributes
30
+ 'accept', 'acceptCharset', 'action', 'allowFullScreen', 'alt', 'async',
31
+ 'autoCapitalize', 'autoComplete', 'autoPlay', 'capture', 'cellPadding',
32
+ 'cellSpacing', 'charSet', 'checked', 'cite', 'colSpan', 'cols', 'controls',
33
+ 'coords', 'crossOrigin', 'dateTime', 'default', 'defer', 'disabled',
34
+ 'download', 'encType', 'form', 'formAction', 'formEncType', 'formMethod',
35
+ 'formNoValidate', 'formTarget', 'frameBorder', 'headers', 'height', 'high',
36
+ 'href', 'hrefLang', 'htmlFor', 'httpEquiv', 'icon', 'inputMode', 'integrity',
37
+ 'is', 'kind', 'label', 'list', 'loop', 'low', 'max', 'maxLength', 'media',
38
+ 'method', 'min', 'minLength', 'multiple', 'muted', 'name', 'noValidate',
39
+ 'open', 'optimum', 'pattern', 'playsInline', 'poster', 'preload',
40
+ 'readOnly', 'rel', 'required', 'reversed', 'rowSpan', 'rows', 'sandbox',
41
+ 'scope', 'scoped', 'scrolling', 'seamless', 'selected', 'shape', 'size',
42
+ 'sizes', 'span', 'src', 'srcDoc', 'srcLang', 'srcSet', 'start', 'step',
43
+ 'summary', 'target', 'type', 'useMap', 'value', 'width', 'wrap',
44
+ ]);
45
+
46
+ function isNativeProp(key: string): boolean {
47
+ return nativeProps.has(key) || key.startsWith('data-') || key.startsWith('aria-');
48
+ }
49
+
50
+ export function getIntrinsicElementProps<Props extends UnknownSlotProps & Record<string, any>>(
51
+ tagName: JSXIntrinsicElementKeys,
52
+ props: Props,
53
+ ): Props {
54
+ const result = {} as Record<string, any>;
55
+
56
+ for (const key of Object.keys(props)) {
57
+ if (isNativeProp(key)) {
58
+ result[key] = props[key];
59
+ }
60
+ }
61
+
62
+ if (!result.as) {
63
+ result.as = tagName;
64
+ }
65
+
66
+ return result as Props;
67
+ }
@@ -1,4 +1,5 @@
1
1
  export { assertSlots } from './assertSlots';
2
+ export { getIntrinsicElementProps } from './getIntrinsicElementProps';
2
3
  export { slot } from './slot';
3
4
 
4
5
  export type {
@@ -1,4 +1,4 @@
1
- export { assertSlots, slot } from './compose';
1
+ export { assertSlots, getIntrinsicElementProps, slot } from './compose';
2
2
  export { useARIAButtonProps } from './ARIA';
3
3
 
4
4
  export type {