@castui/cast-ui 4.1.1 → 4.2.1

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 (126) hide show
  1. package/README.md +129 -19
  2. package/dist/components/Alert/Alert.d.ts +40 -0
  3. package/dist/components/Alert/Alert.js +71 -0
  4. package/dist/components/Alert/index.d.ts +1 -0
  5. package/dist/components/Alert/index.js +5 -0
  6. package/dist/components/Avatar/Avatar.d.ts +31 -0
  7. package/dist/components/Avatar/Avatar.js +55 -0
  8. package/dist/components/Avatar/index.d.ts +1 -0
  9. package/dist/components/Avatar/index.js +5 -0
  10. package/dist/components/Badge/Badge.d.ts +41 -0
  11. package/dist/components/Badge/Badge.js +71 -0
  12. package/dist/components/Badge/index.d.ts +1 -0
  13. package/dist/components/Badge/index.js +5 -0
  14. package/dist/components/Button/Button.d.ts +0 -1
  15. package/dist/components/Button/Button.js +21 -19
  16. package/dist/components/Button/index.d.ts +0 -1
  17. package/dist/components/Button/index.js +5 -2
  18. package/dist/components/Card/Card.d.ts +41 -0
  19. package/dist/components/Card/Card.js +91 -0
  20. package/dist/components/Card/index.d.ts +1 -0
  21. package/dist/components/Card/index.js +5 -0
  22. package/dist/components/Checkbox/Checkbox.d.ts +32 -0
  23. package/dist/components/Checkbox/Checkbox.js +107 -0
  24. package/dist/components/Checkbox/index.d.ts +1 -0
  25. package/dist/components/Checkbox/index.js +5 -0
  26. package/dist/components/Chip/Chip.d.ts +46 -0
  27. package/dist/components/Chip/Chip.js +82 -0
  28. package/dist/components/Chip/index.d.ts +1 -0
  29. package/dist/components/Chip/index.js +5 -0
  30. package/dist/components/Dialog/Dialog.d.ts +0 -1
  31. package/dist/components/Dialog/Dialog.js +33 -26
  32. package/dist/components/Dialog/index.d.ts +0 -1
  33. package/dist/components/Dialog/index.js +6 -2
  34. package/dist/components/Divider/Divider.d.ts +22 -0
  35. package/dist/components/Divider/Divider.js +19 -0
  36. package/dist/components/Divider/index.d.ts +1 -0
  37. package/dist/components/Divider/index.js +5 -0
  38. package/dist/components/Icon/Icon.d.ts +26 -9
  39. package/dist/components/Icon/Icon.js +16 -6
  40. package/dist/components/Icon/index.d.ts +0 -1
  41. package/dist/components/Icon/index.js +5 -2
  42. package/dist/components/Input/Input.d.ts +62 -0
  43. package/dist/components/Input/Input.js +141 -0
  44. package/dist/components/Input/index.d.ts +1 -0
  45. package/dist/components/Input/index.js +5 -0
  46. package/dist/components/List/List.d.ts +58 -0
  47. package/dist/components/List/List.js +116 -0
  48. package/dist/components/List/index.d.ts +1 -0
  49. package/dist/components/List/index.js +8 -0
  50. package/dist/components/Popover/Popover.d.ts +34 -0
  51. package/dist/components/Popover/Popover.js +62 -0
  52. package/dist/components/Popover/index.d.ts +1 -0
  53. package/dist/components/Popover/index.js +5 -0
  54. package/dist/components/Radio/Radio.d.ts +52 -0
  55. package/dist/components/Radio/Radio.js +127 -0
  56. package/dist/components/Radio/index.d.ts +1 -0
  57. package/dist/components/Radio/index.js +6 -0
  58. package/dist/components/Select/Select.d.ts +0 -1
  59. package/dist/components/Select/Select.js +114 -96
  60. package/dist/components/Select/index.d.ts +0 -1
  61. package/dist/components/Select/index.js +10 -2
  62. package/dist/components/Skeleton/Skeleton.d.ts +33 -0
  63. package/dist/components/Skeleton/Skeleton.js +66 -0
  64. package/dist/components/Skeleton/index.d.ts +1 -0
  65. package/dist/components/Skeleton/index.js +5 -0
  66. package/dist/components/Toast/Toast.d.ts +35 -0
  67. package/dist/components/Toast/Toast.js +79 -0
  68. package/dist/components/Toast/index.d.ts +1 -0
  69. package/dist/components/Toast/index.js +5 -0
  70. package/dist/components/Toggle/Toggle.d.ts +31 -0
  71. package/dist/components/Toggle/Toggle.js +91 -0
  72. package/dist/components/Toggle/index.d.ts +1 -0
  73. package/dist/components/Toggle/index.js +5 -0
  74. package/dist/components/Tooltip/Tooltip.d.ts +34 -0
  75. package/dist/components/Tooltip/Tooltip.js +67 -0
  76. package/dist/components/Tooltip/index.d.ts +1 -0
  77. package/dist/components/Tooltip/index.js +5 -0
  78. package/dist/index.d.ts +17 -3
  79. package/dist/index.js +81 -7
  80. package/dist/theme/ThemeContext.d.ts +24 -8
  81. package/dist/theme/ThemeContext.js +41 -22
  82. package/dist/theme/index.d.ts +1 -2
  83. package/dist/theme/index.js +8 -3
  84. package/dist/theme/themes.d.ts +0 -1
  85. package/dist/theme/themes.js +214 -2
  86. package/dist/theme/types.d.ts +183 -1
  87. package/dist/theme/types.js +2 -2
  88. package/dist/tokens/colors.d.ts +294 -26
  89. package/dist/tokens/colors.js +324 -99
  90. package/dist/tokens/index.d.ts +1 -2
  91. package/dist/tokens/index.js +29 -3
  92. package/dist/tokens/typography.d.ts +0 -1
  93. package/dist/tokens/typography.js +13 -11
  94. package/package.json +13 -2
  95. package/dist/components/Button/Button.d.ts.map +0 -1
  96. package/dist/components/Button/Button.js.map +0 -1
  97. package/dist/components/Button/index.d.ts.map +0 -1
  98. package/dist/components/Button/index.js.map +0 -1
  99. package/dist/components/Dialog/Dialog.d.ts.map +0 -1
  100. package/dist/components/Dialog/Dialog.js.map +0 -1
  101. package/dist/components/Dialog/index.d.ts.map +0 -1
  102. package/dist/components/Dialog/index.js.map +0 -1
  103. package/dist/components/Icon/Icon.d.ts.map +0 -1
  104. package/dist/components/Icon/Icon.js.map +0 -1
  105. package/dist/components/Icon/index.d.ts.map +0 -1
  106. package/dist/components/Icon/index.js.map +0 -1
  107. package/dist/components/Select/Select.d.ts.map +0 -1
  108. package/dist/components/Select/Select.js.map +0 -1
  109. package/dist/components/Select/index.d.ts.map +0 -1
  110. package/dist/components/Select/index.js.map +0 -1
  111. package/dist/index.d.ts.map +0 -1
  112. package/dist/index.js.map +0 -1
  113. package/dist/theme/ThemeContext.d.ts.map +0 -1
  114. package/dist/theme/ThemeContext.js.map +0 -1
  115. package/dist/theme/index.d.ts.map +0 -1
  116. package/dist/theme/index.js.map +0 -1
  117. package/dist/theme/themes.d.ts.map +0 -1
  118. package/dist/theme/themes.js.map +0 -1
  119. package/dist/theme/types.d.ts.map +0 -1
  120. package/dist/theme/types.js.map +0 -1
  121. package/dist/tokens/colors.d.ts.map +0 -1
  122. package/dist/tokens/colors.js.map +0 -1
  123. package/dist/tokens/index.d.ts.map +0 -1
  124. package/dist/tokens/index.js.map +0 -1
  125. package/dist/tokens/typography.d.ts.map +0 -1
  126. package/dist/tokens/typography.js.map +0 -1
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Card — surface container for grouped content with optional media, header,
3
+ * body, and actions.
4
+ *
5
+ * Maps to the Figma <Card> component (node 307:3346):
6
+ * size → small | default | large (drives padding, gap, type scale)
7
+ * variant → outline (1px border) | elevated (border + drop shadow)
8
+ *
9
+ * Each content slot mirrors a Figma boolean (hasImage / hasIcon / hasSubtitle
10
+ * / hasBody / hasActions): the slot renders only when its prop is provided.
11
+ * Padding + gap come from the density theme's `card` tokens (size × density).
12
+ */
13
+ import React from 'react';
14
+ import { type ViewStyle, type StyleProp } from 'react-native';
15
+ export type CardSize = 'small' | 'default' | 'large';
16
+ export type CardVariant = 'outline' | 'elevated';
17
+ export type CardProps = {
18
+ /** Size variant — controls padding, gap, and typography scale. */
19
+ size?: CardSize;
20
+ /** Visual style — outline (border) or elevated (border + shadow). */
21
+ variant?: CardVariant;
22
+ /** Media area rendered at the top (e.g. an <Image>). */
23
+ image?: React.ReactNode;
24
+ /** Header leading icon — Material Symbols name string or a ReactNode. */
25
+ icon?: string | React.ReactNode;
26
+ /** Card title. */
27
+ title?: string;
28
+ /** Supporting subtitle below the title. */
29
+ subtitle?: string;
30
+ /** Body description text. */
31
+ body?: string;
32
+ /** Action row content (e.g. Buttons), right-aligned at the bottom. */
33
+ actions?: React.ReactNode;
34
+ /** Additional custom content rendered in the body, after `body`. */
35
+ children?: React.ReactNode;
36
+ /** Style override for the outer container. */
37
+ style?: StyleProp<ViewStyle>;
38
+ /** Accessibility label for the card. */
39
+ accessibilityLabel?: string;
40
+ };
41
+ export declare function Card({ size, variant, image, icon, title: titleText, subtitle, body: bodyText, actions, children, style, accessibilityLabel, }: CardProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,91 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Card = Card;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_native_1 = require("react-native");
6
+ const theme_1 = require("../../theme");
7
+ const Icon_1 = require("../Icon");
8
+ const tokens_1 = require("../../tokens");
9
+ /** Maps card size → title typography scale */
10
+ const TITLE_SCALE = {
11
+ small: 'sm',
12
+ default: 'md',
13
+ large: 'lg',
14
+ };
15
+ /** Maps card size → body/subtitle typography scale */
16
+ const BODY_SCALE = {
17
+ small: 'sm',
18
+ default: 'md',
19
+ large: 'lg',
20
+ };
21
+ /** shadow/lg — elevated card drop shadow */
22
+ const SHADOW_WEB = {
23
+ boxShadow: '0px 10px 15px -3px rgba(0,0,0,0.08), 0px 4px 6px -4px rgba(0,0,0,0.04)',
24
+ };
25
+ const SHADOW_NATIVE = {
26
+ shadowColor: '#000000',
27
+ shadowOffset: { width: 0, height: 10 },
28
+ shadowOpacity: 0.08,
29
+ shadowRadius: 15,
30
+ elevation: 8,
31
+ };
32
+ function Card({ size = 'default', variant = 'outline', image, icon, title: titleText, subtitle, body: bodyText, actions, children, style, accessibilityLabel, }) {
33
+ const { components, scheme } = (0, theme_1.useTheme)();
34
+ const surfaceTokens = scheme.surface;
35
+ const textTokens = scheme.text;
36
+ const TITLE_FG = scheme.intents.neutral.default.default.fg;
37
+ const tokens = components.card;
38
+ const sizeTokens = tokens[size];
39
+ const titleTokens = tokens_1.title[TITLE_SCALE[size]];
40
+ const bodyTokens = tokens_1.body[BODY_SCALE[size]];
41
+ const resolvedIcon = typeof icon === 'string' ? ((0, jsx_runtime_1.jsx)(Icon_1.Icon, { name: icon, size: sizeTokens.iconSize, color: TITLE_FG })) : (icon);
42
+ const hasHeader = !!(resolvedIcon || titleText || subtitle);
43
+ return ((0, jsx_runtime_1.jsxs)(react_native_1.View, { accessibilityLabel: accessibilityLabel, style: [
44
+ {
45
+ backgroundColor: surfaceTokens.overlay.bg,
46
+ borderRadius: tokens.borderRadius,
47
+ borderWidth: 1,
48
+ borderColor: surfaceTokens.overlay.border,
49
+ overflow: 'hidden',
50
+ ...(variant === 'elevated'
51
+ ? react_native_1.Platform.OS === 'web'
52
+ ? SHADOW_WEB
53
+ : SHADOW_NATIVE
54
+ : {}),
55
+ },
56
+ style,
57
+ ], children: [image ? ((0, jsx_runtime_1.jsx)(react_native_1.View, { style: { height: sizeTokens.imageHeight, width: '100%' }, children: image })) : null, (0, jsx_runtime_1.jsxs)(react_native_1.View, { style: { padding: sizeTokens.padding, gap: sizeTokens.gap }, children: [hasHeader ? ((0, jsx_runtime_1.jsxs)(react_native_1.View, { style: {
58
+ flexDirection: 'row',
59
+ alignItems: 'flex-start',
60
+ gap: sizeTokens.gap,
61
+ }, children: [resolvedIcon ? ((0, jsx_runtime_1.jsx)(react_native_1.View, { accessibilityElementsHidden: true, importantForAccessibility: "no", style: {
62
+ width: sizeTokens.iconSize,
63
+ height: sizeTokens.iconSize,
64
+ }, children: resolvedIcon })) : null, titleText || subtitle ? ((0, jsx_runtime_1.jsxs)(react_native_1.View, { style: { flex: 1 }, children: [titleText ? ((0, jsx_runtime_1.jsx)(react_native_1.Text, { style: {
65
+ fontFamily: tokens_1.fontFamily.sans,
66
+ fontWeight: tokens_1.fontWeight.medium,
67
+ fontSize: titleTokens.fontSize,
68
+ lineHeight: titleTokens.lineHeight,
69
+ letterSpacing: titleTokens.letterSpacing,
70
+ color: TITLE_FG,
71
+ }, selectable: false, children: titleText })) : null, subtitle ? ((0, jsx_runtime_1.jsx)(react_native_1.Text, { style: {
72
+ fontFamily: tokens_1.fontFamily.sans,
73
+ fontWeight: tokens_1.fontWeight.regular,
74
+ fontSize: bodyTokens.fontSize,
75
+ lineHeight: bodyTokens.lineHeight,
76
+ letterSpacing: bodyTokens.letterSpacing,
77
+ color: textTokens.description,
78
+ }, selectable: false, children: subtitle })) : null] })) : null] })) : null, bodyText ? ((0, jsx_runtime_1.jsx)(react_native_1.Text, { style: {
79
+ fontFamily: tokens_1.fontFamily.sans,
80
+ fontWeight: tokens_1.fontWeight.regular,
81
+ fontSize: bodyTokens.fontSize,
82
+ lineHeight: bodyTokens.lineHeight,
83
+ letterSpacing: bodyTokens.letterSpacing,
84
+ color: textTokens.description,
85
+ }, selectable: false, children: bodyText })) : null, children, actions ? ((0, jsx_runtime_1.jsx)(react_native_1.View, { style: {
86
+ flexDirection: 'row',
87
+ justifyContent: 'flex-end',
88
+ alignItems: 'center',
89
+ gap: sizeTokens.gap,
90
+ }, children: actions })) : null] })] }));
91
+ }
@@ -0,0 +1 @@
1
+ export { Card, type CardProps, type CardSize, type CardVariant } from './Card';
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Card = void 0;
4
+ var Card_1 = require("./Card");
5
+ Object.defineProperty(exports, "Card", { enumerable: true, get: function () { return Card_1.Card; } });
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Checkbox — binary (or tri-state) choice control.
3
+ *
4
+ * Maps to the Figma <Checkbox> component (node 275:5919):
5
+ * checked → false | true | indeterminate
6
+ * size → small | default | large
7
+ * state → default | hover | focus | disabled (interaction-driven)
8
+ *
9
+ * Indicator and icon sizes come from the density theme's `checkbox` tokens
10
+ * (sizes track the `size` prop; gap tracks density). Colours come from the
11
+ * active theme scheme's `checkbox` set + the focus-ring colour.
12
+ */
13
+ import { type ViewStyle, type StyleProp } from 'react-native';
14
+ export type CheckboxSize = 'small' | 'default' | 'large';
15
+ export type CheckboxChecked = boolean | 'indeterminate';
16
+ export type CheckboxProps = {
17
+ /** Checked state — true, false, or 'indeterminate'. */
18
+ checked?: CheckboxChecked;
19
+ /** Change handler — receives the next boolean checked value. */
20
+ onChange?: (checked: boolean) => void;
21
+ /** Optional label rendered beside the indicator. */
22
+ children?: string;
23
+ /** Size variant — controls indicator + icon size. */
24
+ size?: CheckboxSize;
25
+ /** Disables interaction and applies muted styling. */
26
+ disabled?: boolean;
27
+ /** Style override for the outer row. */
28
+ style?: StyleProp<ViewStyle>;
29
+ /** Accessibility label — falls back to the label text. */
30
+ accessibilityLabel?: string;
31
+ };
32
+ export declare function Checkbox({ checked, onChange, children, size, disabled, style, accessibilityLabel, }: CheckboxProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,107 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Checkbox = Checkbox;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ /**
6
+ * Checkbox — binary (or tri-state) choice control.
7
+ *
8
+ * Maps to the Figma <Checkbox> component (node 275:5919):
9
+ * checked → false | true | indeterminate
10
+ * size → small | default | large
11
+ * state → default | hover | focus | disabled (interaction-driven)
12
+ *
13
+ * Indicator and icon sizes come from the density theme's `checkbox` tokens
14
+ * (sizes track the `size` prop; gap tracks density). Colours come from the
15
+ * active theme scheme's `checkbox` set + the focus-ring colour.
16
+ */
17
+ const react_1 = require("react");
18
+ const react_native_1 = require("react-native");
19
+ const theme_1 = require("../../theme");
20
+ const Icon_1 = require("../Icon");
21
+ const tokens_1 = require("../../tokens");
22
+ /** Maps checkbox size → label typography scale */
23
+ const LABEL_SCALE = {
24
+ small: 'sm',
25
+ default: 'md',
26
+ large: 'lg',
27
+ };
28
+ function Checkbox({ checked = false, onChange, children, size = 'default', disabled = false, style, accessibilityLabel, }) {
29
+ const { components, scheme } = (0, theme_1.useTheme)();
30
+ const checkboxColors = scheme.checkbox;
31
+ const tokens = components.checkbox;
32
+ const sizeTokens = tokens[size];
33
+ const labelTokens = tokens_1.label[LABEL_SCALE[size]];
34
+ const [isHovered, setIsHovered] = (0, react_1.useState)(false);
35
+ const [isFocused, setIsFocused] = (0, react_1.useState)(false);
36
+ const isIndeterminate = checked === 'indeterminate';
37
+ const isChecked = checked === true;
38
+ const isOn = isChecked || isIndeterminate;
39
+ const handlePress = (0, react_1.useCallback)(() => {
40
+ if (!disabled)
41
+ onChange?.(!isChecked);
42
+ }, [disabled, onChange, isChecked]);
43
+ // Resolve indicator fill + border based on state.
44
+ // Priority: disabled > focus > (checked) > hover > default
45
+ let boxBg;
46
+ let boxBorderColor;
47
+ let boxBorderWidth;
48
+ if (disabled) {
49
+ boxBg = checkboxColors.box.disabled.bg;
50
+ boxBorderColor = checkboxColors.box.disabled.border;
51
+ boxBorderWidth = tokens_1.controlTokens.borderWidth;
52
+ }
53
+ else if (isOn) {
54
+ boxBg = checkboxColors.box.checked.bg;
55
+ boxBorderColor = isFocused
56
+ ? scheme.focusRing.color
57
+ : checkboxColors.box.checked.border;
58
+ boxBorderWidth = isFocused ? tokens.focusRingWidth : 0;
59
+ }
60
+ else {
61
+ boxBg = checkboxColors.box.uncheckedDefault.bg;
62
+ if (isFocused) {
63
+ boxBorderColor = scheme.focusRing.color;
64
+ boxBorderWidth = tokens.focusRingWidth;
65
+ }
66
+ else if (isHovered) {
67
+ boxBorderColor = checkboxColors.box.uncheckedHover.border;
68
+ boxBorderWidth = tokens_1.controlTokens.borderWidth;
69
+ }
70
+ else {
71
+ boxBorderColor = checkboxColors.box.uncheckedDefault.border;
72
+ boxBorderWidth = tokens_1.controlTokens.borderWidth;
73
+ }
74
+ }
75
+ const glyphColor = disabled
76
+ ? checkboxColors.icon.disabled
77
+ : checkboxColors.icon.default;
78
+ return ((0, jsx_runtime_1.jsxs)(react_native_1.Pressable, { onPress: handlePress, disabled: disabled, onHoverIn: () => setIsHovered(true), onHoverOut: () => setIsHovered(false), onFocus: () => setIsFocused(true), onBlur: () => setIsFocused(false), accessibilityRole: "checkbox", accessibilityLabel: accessibilityLabel || children, accessibilityState: {
79
+ checked: isIndeterminate ? 'mixed' : isChecked,
80
+ disabled,
81
+ }, style: [
82
+ {
83
+ flexDirection: 'row',
84
+ alignItems: 'flex-start',
85
+ gap: tokens.gap,
86
+ },
87
+ style,
88
+ ], children: [(0, jsx_runtime_1.jsx)(react_native_1.View, { style: {
89
+ width: sizeTokens.indicatorSize,
90
+ height: sizeTokens.indicatorSize,
91
+ borderRadius: tokens.borderRadius,
92
+ backgroundColor: boxBg,
93
+ borderWidth: boxBorderWidth,
94
+ borderColor: boxBorderColor,
95
+ alignItems: 'center',
96
+ justifyContent: 'center',
97
+ }, children: isChecked ? ((0, jsx_runtime_1.jsx)(Icon_1.Icon, { name: "check", size: sizeTokens.iconSize, color: glyphColor })) : isIndeterminate ? ((0, jsx_runtime_1.jsx)(Icon_1.Icon, { name: "remove", size: sizeTokens.iconSize, color: glyphColor })) : null }), children ? ((0, jsx_runtime_1.jsx)(react_native_1.Text, { style: {
98
+ fontFamily: tokens_1.fontFamily.sans,
99
+ fontWeight: tokens_1.fontWeight.medium,
100
+ fontSize: labelTokens.fontSize,
101
+ lineHeight: labelTokens.lineHeight,
102
+ letterSpacing: labelTokens.letterSpacing,
103
+ color: disabled
104
+ ? checkboxColors.label.disabled
105
+ : checkboxColors.label.default,
106
+ }, selectable: false, children: children })) : null] }));
107
+ }
@@ -0,0 +1 @@
1
+ export { Checkbox, type CheckboxProps, type CheckboxSize, type CheckboxChecked, } from './Checkbox';
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Checkbox = void 0;
4
+ var Checkbox_1 = require("./Checkbox");
5
+ Object.defineProperty(exports, "Checkbox", { enumerable: true, get: function () { return Checkbox_1.Checkbox; } });
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Chip — compact, interactive pill for filters, selections, and tokens.
3
+ *
4
+ * Maps to the Figma <Chip> component (node 307:3479):
5
+ * intent → neutral | brand | danger
6
+ * variant → outline (bordered) | subtle (tinted)
7
+ * size → small | default | large
8
+ * state → default | hover | active | disabled (interaction-driven)
9
+ *
10
+ * Spacing/icon sizes come from the density theme's `chip` tokens (padding/gap
11
+ * vary by size AND density; icon size tracks the `size` prop). Colours map
12
+ * directly onto the semantic intent system:
13
+ * outline → intent default (white/tinted bg + border)
14
+ * subtle → intent subtle (transparent bg/border)
15
+ * The `selected` state renders the intent's active colours.
16
+ */
17
+ import React from 'react';
18
+ import { type ViewStyle, type StyleProp, type GestureResponderEvent } from 'react-native';
19
+ import type { IntentName } from '../../tokens';
20
+ export type ChipSize = 'small' | 'default' | 'large';
21
+ export type ChipVariant = 'outline' | 'subtle';
22
+ export type ChipProps = {
23
+ /** The chip label text. */
24
+ children: string;
25
+ /** Semantic intent — drives the colour scheme. */
26
+ intent?: IntentName;
27
+ /** Surface treatment — outline (bordered) or subtle (tinted). */
28
+ variant?: ChipVariant;
29
+ /** Size variant — controls padding, gap, and typography scale. */
30
+ size?: ChipSize;
31
+ /** Selected state — renders the intent's active colours. */
32
+ selected?: boolean;
33
+ /** Disables interaction and applies muted styling. */
34
+ disabled?: boolean;
35
+ /** Leading icon — Material Symbols name string or a ReactNode. */
36
+ leadingIcon?: string | React.ReactNode;
37
+ /** Press handler — makes the chip selectable. */
38
+ onPress?: (e: GestureResponderEvent) => void;
39
+ /** Remove handler — renders a trailing close button when provided. */
40
+ onRemove?: () => void;
41
+ /** Outer style — use for positioning (margin, flex, alignSelf). */
42
+ style?: StyleProp<ViewStyle>;
43
+ /** Accessibility label — falls back to the label text. */
44
+ accessibilityLabel?: string;
45
+ };
46
+ export declare function Chip({ children, intent, variant, size, selected, disabled, leadingIcon, onPress, onRemove, style, accessibilityLabel, }: ChipProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,82 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Chip = Chip;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ /**
6
+ * Chip — compact, interactive pill for filters, selections, and tokens.
7
+ *
8
+ * Maps to the Figma <Chip> component (node 307:3479):
9
+ * intent → neutral | brand | danger
10
+ * variant → outline (bordered) | subtle (tinted)
11
+ * size → small | default | large
12
+ * state → default | hover | active | disabled (interaction-driven)
13
+ *
14
+ * Spacing/icon sizes come from the density theme's `chip` tokens (padding/gap
15
+ * vary by size AND density; icon size tracks the `size` prop). Colours map
16
+ * directly onto the semantic intent system:
17
+ * outline → intent default (white/tinted bg + border)
18
+ * subtle → intent subtle (transparent bg/border)
19
+ * The `selected` state renders the intent's active colours.
20
+ */
21
+ const react_1 = require("react");
22
+ const react_native_1 = require("react-native");
23
+ const theme_1 = require("../../theme");
24
+ const tokens_1 = require("../../tokens");
25
+ const Icon_1 = require("../Icon");
26
+ // ---------------------------------------------------------------------------
27
+ // Constants
28
+ // ---------------------------------------------------------------------------
29
+ /** Maps chip size → label typography scale */
30
+ const LABEL_SCALE = {
31
+ small: 'sm',
32
+ default: 'md',
33
+ large: 'lg',
34
+ };
35
+ // ---------------------------------------------------------------------------
36
+ // Component
37
+ // ---------------------------------------------------------------------------
38
+ function Chip({ children, intent = 'neutral', variant = 'outline', size = 'default', selected = false, disabled = false, leadingIcon, onPress, onRemove, style, accessibilityLabel, }) {
39
+ const { components, scheme } = (0, theme_1.useTheme)();
40
+ const intentColors = scheme.intents;
41
+ const disabledColors = scheme.disabled;
42
+ const sizeTokens = components.chip[size];
43
+ const labelTokens = tokens_1.label[LABEL_SCALE[size]];
44
+ const [isHovered, setIsHovered] = (0, react_1.useState)(false);
45
+ const prominence = variant === 'outline' ? 'default' : 'subtle';
46
+ // Resolve colours. Priority: disabled > selected/pressed > hover > default
47
+ const resolveColors = (0, react_1.useCallback)((pressed) => {
48
+ if (disabled)
49
+ return disabledColors;
50
+ const states = intentColors[intent][prominence];
51
+ if (selected || pressed)
52
+ return states.active;
53
+ if (isHovered)
54
+ return states.hover;
55
+ return states.default;
56
+ }, [disabled, intent, prominence, selected, isHovered, intentColors, disabledColors]);
57
+ const isInteractive = !disabled && (onPress != null || onRemove != null);
58
+ return ((0, jsx_runtime_1.jsx)(react_native_1.Pressable, { onPress: onPress, disabled: disabled || onPress == null, onHoverIn: () => setIsHovered(true), onHoverOut: () => setIsHovered(false), accessibilityRole: onPress ? 'button' : 'text', accessibilityLabel: accessibilityLabel || children, accessibilityState: { disabled, selected }, style: style, children: ({ pressed }) => {
59
+ const colors = resolveColors(pressed && isInteractive);
60
+ const resolvedLeading = typeof leadingIcon === 'string' ? ((0, jsx_runtime_1.jsx)(Icon_1.Icon, { name: leadingIcon, size: sizeTokens.iconSize, color: colors.fg })) : (leadingIcon);
61
+ return ((0, jsx_runtime_1.jsxs)(react_native_1.View, { style: {
62
+ flexDirection: 'row',
63
+ alignItems: 'center',
64
+ justifyContent: 'center',
65
+ alignSelf: 'flex-start',
66
+ gap: sizeTokens.gap,
67
+ paddingHorizontal: sizeTokens.paddingX,
68
+ paddingVertical: sizeTokens.paddingY,
69
+ borderRadius: components.chip.borderRadius,
70
+ borderWidth: tokens_1.controlTokens.borderWidth,
71
+ borderColor: colors.border,
72
+ backgroundColor: colors.bg,
73
+ }, children: [resolvedLeading ? ((0, jsx_runtime_1.jsx)(react_native_1.View, { accessibilityElementsHidden: true, importantForAccessibility: "no", style: { width: sizeTokens.iconSize, height: sizeTokens.iconSize }, children: resolvedLeading })) : null, (0, jsx_runtime_1.jsx)(react_native_1.Text, { style: {
74
+ fontFamily: tokens_1.fontFamily.sans,
75
+ fontWeight: tokens_1.fontWeight.medium,
76
+ fontSize: labelTokens.fontSize,
77
+ lineHeight: labelTokens.lineHeight,
78
+ letterSpacing: labelTokens.letterSpacing,
79
+ color: colors.fg,
80
+ }, selectable: false, children: children }), onRemove ? ((0, jsx_runtime_1.jsx)(react_native_1.Pressable, { onPress: disabled ? undefined : onRemove, disabled: disabled, hitSlop: 6, accessibilityRole: "button", accessibilityLabel: `Remove ${children}`, style: { width: sizeTokens.iconSize, height: sizeTokens.iconSize }, children: (0, jsx_runtime_1.jsx)(Icon_1.Icon, { name: "close", size: sizeTokens.iconSize, color: colors.fg }) })) : null] }));
81
+ } }));
82
+ }
@@ -0,0 +1 @@
1
+ export { Chip, type ChipProps, type ChipSize, type ChipVariant } from './Chip';
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Chip = void 0;
4
+ var Chip_1 = require("./Chip");
5
+ Object.defineProperty(exports, "Chip", { enumerable: true, get: function () { return Chip_1.Chip; } });
@@ -54,4 +54,3 @@ export type DialogProps = DialogContentProps & {
54
54
  */
55
55
  export declare function DialogContent({ title: titleText, description, icon, size, children, primaryAction, secondaryAction, style, accessibilityLabel, }: DialogContentProps): import("react/jsx-runtime").JSX.Element;
56
56
  export declare function Dialog({ open, onClose, ...contentProps }: DialogProps): import("react/jsx-runtime").JSX.Element;
57
- //# sourceMappingURL=Dialog.d.ts.map
@@ -1,9 +1,13 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Modal, Pressable, View, Text, Platform, } from 'react-native';
3
- import { useTheme } from '../../theme';
4
- import { Button } from '../Button';
5
- import { Icon } from '../Icon';
6
- import { fontFamily, fontWeight, title, body, surfaceTokens, textTokens, overlayTokens, controlTokens, } from '../../tokens';
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DialogContent = DialogContent;
4
+ exports.Dialog = Dialog;
5
+ const jsx_runtime_1 = require("react/jsx-runtime");
6
+ const react_native_1 = require("react-native");
7
+ const theme_1 = require("../../theme");
8
+ const Button_1 = require("../Button");
9
+ const Icon_1 = require("../Icon");
10
+ const tokens_1 = require("../../tokens");
7
11
  // ---------------------------------------------------------------------------
8
12
  // Constants
9
13
  // ---------------------------------------------------------------------------
@@ -48,57 +52,60 @@ const SHADOW_NATIVE = {
48
52
  * Use this for static display (e.g., Storybook visual stories)
49
53
  * or when building custom overlay implementations.
50
54
  */
51
- export function DialogContent({ title: titleText, description, icon, size = 'default', children, primaryAction, secondaryAction, style, accessibilityLabel, }) {
52
- const { components, colors } = useTheme();
55
+ function DialogContent({ title: titleText, description, icon, size = 'default', children, primaryAction, secondaryAction, style, accessibilityLabel, }) {
56
+ const { components, colors, scheme } = (0, theme_1.useTheme)();
57
+ const surfaceTokens = scheme.surface;
58
+ const textTokens = scheme.text;
53
59
  const sizeTokens = components.dialog[size];
54
- const titleTokens = title[TYPO_SCALE[size]];
55
- const bodyTokens = body[TYPO_SCALE[size]];
60
+ const titleTokens = tokens_1.title[TYPO_SCALE[size]];
61
+ const bodyTokens = tokens_1.body[TYPO_SCALE[size]];
56
62
  const buttonSize = BUTTON_SIZE[size];
57
63
  const fgColor = colors.neutral.default.default.fg;
58
- const resolvedIcon = typeof icon === 'string' ? (_jsx(Icon, { name: icon, size: sizeTokens.iconSize, color: fgColor })) : (icon);
64
+ const resolvedIcon = typeof icon === 'string' ? ((0, jsx_runtime_1.jsx)(Icon_1.Icon, { name: icon, size: sizeTokens.iconSize, color: fgColor })) : (icon);
59
65
  const hasActions = primaryAction || secondaryAction;
60
- return (_jsxs(View, { accessibilityRole: "alert", accessibilityLabel: accessibilityLabel || titleText, style: [
66
+ return ((0, jsx_runtime_1.jsxs)(react_native_1.View, { accessibilityRole: "alert", accessibilityLabel: accessibilityLabel || titleText, style: [
61
67
  {
62
68
  width: DIALOG_WIDTH[size],
63
69
  maxWidth: '100%',
64
70
  backgroundColor: surfaceTokens.overlay.bg,
65
- borderWidth: controlTokens.borderWidth,
71
+ borderWidth: tokens_1.controlTokens.borderWidth,
66
72
  borderColor: surfaceTokens.overlay.border,
67
73
  borderRadius: surfaceTokens.overlay.borderRadius,
68
74
  padding: sizeTokens.padding,
69
75
  gap: sizeTokens.gap,
70
- ...(Platform.OS === 'web' ? SHADOW_WEB : SHADOW_NATIVE),
76
+ ...(react_native_1.Platform.OS === 'web' ? SHADOW_WEB : SHADOW_NATIVE),
71
77
  },
72
78
  style,
73
- ], children: [_jsxs(View, { style: { gap: TITLE_DESC_GAP }, children: [_jsxs(View, { style: { gap: HEADER_ICON_GAP }, children: [resolvedIcon, _jsx(Text, { accessibilityRole: "header", style: {
74
- fontFamily: fontFamily.sans,
75
- fontWeight: fontWeight.medium,
79
+ ], children: [(0, jsx_runtime_1.jsxs)(react_native_1.View, { style: { gap: TITLE_DESC_GAP }, children: [(0, jsx_runtime_1.jsxs)(react_native_1.View, { style: { gap: HEADER_ICON_GAP }, children: [resolvedIcon, (0, jsx_runtime_1.jsx)(react_native_1.Text, { accessibilityRole: "header", style: {
80
+ fontFamily: tokens_1.fontFamily.sans,
81
+ fontWeight: tokens_1.fontWeight.medium,
76
82
  fontSize: titleTokens.fontSize,
77
83
  lineHeight: titleTokens.lineHeight,
78
84
  letterSpacing: titleTokens.letterSpacing,
79
85
  color: fgColor,
80
- }, children: titleText })] }), description ? (_jsx(Text, { style: {
81
- fontFamily: fontFamily.sans,
82
- fontWeight: fontWeight.regular,
86
+ }, children: titleText })] }), description ? ((0, jsx_runtime_1.jsx)(react_native_1.Text, { style: {
87
+ fontFamily: tokens_1.fontFamily.sans,
88
+ fontWeight: tokens_1.fontWeight.regular,
83
89
  fontSize: bodyTokens.fontSize,
84
90
  lineHeight: bodyTokens.lineHeight,
85
91
  letterSpacing: bodyTokens.letterSpacing,
86
92
  color: textTokens.description,
87
- }, children: description })) : null] }), children, hasActions ? (_jsxs(View, { style: {
93
+ }, children: description })) : null] }), children, hasActions ? ((0, jsx_runtime_1.jsxs)(react_native_1.View, { style: {
88
94
  flexDirection: 'row',
89
95
  justifyContent: 'flex-end',
90
96
  gap: sizeTokens.gap,
91
- }, children: [secondaryAction ? (_jsx(Button, { intent: "neutral", prominence: "default", size: buttonSize, onPress: secondaryAction.onPress, children: secondaryAction.label })) : null, primaryAction ? (_jsx(Button, { intent: "brand", prominence: "bold", size: buttonSize, onPress: primaryAction.onPress, children: primaryAction.label })) : null] })) : null] }));
97
+ }, children: [secondaryAction ? ((0, jsx_runtime_1.jsx)(Button_1.Button, { intent: "neutral", prominence: "default", size: buttonSize, onPress: secondaryAction.onPress, children: secondaryAction.label })) : null, primaryAction ? ((0, jsx_runtime_1.jsx)(Button_1.Button, { intent: "brand", prominence: "bold", size: buttonSize, onPress: primaryAction.onPress, children: primaryAction.label })) : null] })) : null] }));
92
98
  }
93
99
  // ---------------------------------------------------------------------------
94
100
  // Dialog — full modal with backdrop
95
101
  // ---------------------------------------------------------------------------
96
- export function Dialog({ open, onClose, ...contentProps }) {
97
- return (_jsx(Modal, { visible: open, transparent: true, animationType: "fade", onRequestClose: onClose, children: _jsx(Pressable, { onPress: onClose, accessibilityRole: "button", accessibilityLabel: "Close dialog", style: {
102
+ function Dialog({ open, onClose, ...contentProps }) {
103
+ const { scheme } = (0, theme_1.useTheme)();
104
+ const overlayTokens = scheme.overlay;
105
+ return ((0, jsx_runtime_1.jsx)(react_native_1.Modal, { visible: open, transparent: true, animationType: "fade", onRequestClose: onClose, children: (0, jsx_runtime_1.jsx)(react_native_1.Pressable, { onPress: onClose, accessibilityRole: "button", accessibilityLabel: "Close dialog", style: {
98
106
  flex: 1,
99
107
  backgroundColor: `rgba(0, 0, 0, ${overlayTokens.scrimOpacity})`,
100
108
  justifyContent: 'center',
101
109
  alignItems: 'center',
102
- }, children: _jsx(Pressable, { onPress: (e) => e.stopPropagation(), accessibilityRole: "none", style: { maxWidth: '90%' }, children: _jsx(DialogContent, { ...contentProps }) }) }) }));
110
+ }, children: (0, jsx_runtime_1.jsx)(react_native_1.Pressable, { onPress: (e) => e.stopPropagation(), accessibilityRole: "none", style: { maxWidth: '90%' }, children: (0, jsx_runtime_1.jsx)(DialogContent, { ...contentProps }) }) }) }));
103
111
  }
104
- //# sourceMappingURL=Dialog.js.map
@@ -1,2 +1 @@
1
1
  export { Dialog, DialogContent, type DialogProps, type DialogContentProps, type DialogAction, type DialogSize, } from './Dialog';
2
- //# sourceMappingURL=index.d.ts.map
@@ -1,2 +1,6 @@
1
- export { Dialog, DialogContent, } from './Dialog';
2
- //# sourceMappingURL=index.js.map
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DialogContent = exports.Dialog = void 0;
4
+ var Dialog_1 = require("./Dialog");
5
+ Object.defineProperty(exports, "Dialog", { enumerable: true, get: function () { return Dialog_1.Dialog; } });
6
+ Object.defineProperty(exports, "DialogContent", { enumerable: true, get: function () { return Dialog_1.DialogContent; } });
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Divider — a thin rule separating content, horizontally or vertically.
3
+ *
4
+ * Maps to the Figma <Divider> component (node 307:3571):
5
+ * orientation → horizontal | vertical
6
+ *
7
+ * The line uses the overlay border colour (surface/overlay/border) at the
8
+ * control border width (1px) — both constant across densities. A horizontal
9
+ * divider stretches to its container's width; a vertical divider stretches to
10
+ * its container's height (give the parent a defined cross-axis size).
11
+ */
12
+ import { type ViewStyle, type StyleProp } from 'react-native';
13
+ export type DividerOrientation = 'horizontal' | 'vertical';
14
+ export type DividerProps = {
15
+ /** Line direction. */
16
+ orientation?: DividerOrientation;
17
+ /** Line colour — defaults to the overlay border token. */
18
+ color?: string;
19
+ /** Style override — e.g. margins or an explicit length. */
20
+ style?: StyleProp<ViewStyle>;
21
+ };
22
+ export declare function Divider({ orientation, color, style, }: DividerProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Divider = Divider;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_native_1 = require("react-native");
6
+ const theme_1 = require("../../theme");
7
+ const tokens_1 = require("../../tokens");
8
+ function Divider({ orientation = 'horizontal', color, style, }) {
9
+ const { scheme } = (0, theme_1.useTheme)();
10
+ const resolvedColor = color ?? scheme.surface.overlay.border;
11
+ const isVertical = orientation === 'vertical';
12
+ return ((0, jsx_runtime_1.jsx)(react_native_1.View, { accessibilityElementsHidden: true, importantForAccessibility: "no-hide-descendants", style: [
13
+ isVertical
14
+ ? { alignSelf: 'stretch', width: tokens_1.controlTokens.borderWidth }
15
+ : { alignSelf: 'stretch', height: tokens_1.controlTokens.borderWidth },
16
+ { backgroundColor: resolvedColor },
17
+ style,
18
+ ] }));
19
+ }
@@ -0,0 +1 @@
1
+ export { Divider, type DividerProps, type DividerOrientation } from './Divider';
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Divider = void 0;
4
+ var Divider_1 = require("./Divider");
5
+ Object.defineProperty(exports, "Divider", { enumerable: true, get: function () { return Divider_1.Divider; } });