@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
@@ -1,14 +1,24 @@
1
1
  /**
2
2
  * Icon — renders a Material Symbols Outlined icon by name.
3
3
  *
4
- * Uses the Material Symbols font with ligature rendering.
5
- * The `name` prop matches Material Symbols names exactly
6
- * (e.g., "star", "close", "chevron_right", "add").
4
+ * Why Material Symbols Outlined?
5
+ * - It's the icon set the Cast UI Figma uses (star, check, close,
6
+ * keyboard_arrow_down, …), so names map 1:1 to the design with zero drift.
7
+ * - Apache-2.0 licensed and free for commercial use.
8
+ * - It's a single *variable* font, so one asset covers every icon plus the
9
+ * fill / weight / grade / optical-size axes — keeping Cast UI's zero
10
+ * runtime dependencies (no per-icon SVG packages, no vector-icons dep).
7
11
  *
8
- * Requires the MaterialSymbolsOutlined font to be loaded:
9
- * - Web: Google Fonts CSS import
10
- * - Expo: expo-font
11
- * - Bare RN: font asset linking
12
+ * Rendering uses font ligatures: the `name` text (e.g. "chevron_right") is
13
+ * shaped into the glyph by the font. Requires the font to be loaded:
14
+ * - Web: Google Fonts CSS import (see .storybook/preview-head.html), or
15
+ * self-host the same `Material Symbols Outlined` family.
16
+ * - Expo: load `MaterialSymbolsOutlined` via expo-font / useFonts.
17
+ * - Bare RN: link the .ttf as a font asset (react-native.config.js / Xcode).
18
+ *
19
+ * The fill / weight / grade / opticalSize axes are applied via CSS
20
+ * `fontVariationSettings` and therefore take effect on web (where the variable
21
+ * font is loaded). On native they require a matching static/variable font cut.
12
22
  */
13
23
  import { type TextStyle, type StyleProp } from 'react-native';
14
24
  export type IconProps = {
@@ -18,8 +28,15 @@ export type IconProps = {
18
28
  size?: number;
19
29
  /** Icon colour. Defaults to "#374151" (neutral fg). */
20
30
  color?: string;
31
+ /** Filled vs outlined glyph (FILL axis, 0–1). Defaults to false (outlined). */
32
+ fill?: boolean;
33
+ /** Stroke weight (wght axis, 100–700). Defaults to 400. */
34
+ weight?: 100 | 200 | 300 | 400 | 500 | 600 | 700;
35
+ /** Emphasis grade (GRAD axis, -25–200). Defaults to 0. */
36
+ grade?: number;
37
+ /** Optical size (opsz axis, 20–48). Defaults to the icon `size`. */
38
+ opticalSize?: number;
21
39
  /** Additional style overrides. */
22
40
  style?: StyleProp<TextStyle>;
23
41
  };
24
- export declare function Icon({ name, size, color, style }: IconProps): import("react/jsx-runtime").JSX.Element;
25
- //# sourceMappingURL=Icon.d.ts.map
42
+ export declare function Icon({ name, size, color, fill, weight, grade, opticalSize, style, }: IconProps): import("react/jsx-runtime").JSX.Element;
@@ -1,11 +1,21 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { Text, Platform } from 'react-native';
3
- const FONT_FAMILY = Platform.select({
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Icon = Icon;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_native_1 = require("react-native");
6
+ const FONT_FAMILY = react_native_1.Platform.select({
4
7
  web: '"Material Symbols Outlined", sans-serif',
5
8
  default: 'MaterialSymbolsOutlined',
6
9
  });
7
- export function Icon({ name, size = 20, color = '#374151', style }) {
8
- return (_jsx(Text, { selectable: false, accessibilityElementsHidden: true, importantForAccessibility: "no", style: [
10
+ function Icon({ name, size = 20, color = '#374151', fill = false, weight = 400, grade = 0, opticalSize, style, }) {
11
+ // Material Symbols variable-font axes applied on web via fontVariationSettings.
12
+ const opsz = Math.min(48, Math.max(20, opticalSize ?? size));
13
+ const variationStyle = react_native_1.Platform.OS === 'web'
14
+ ? {
15
+ fontVariationSettings: `'FILL' ${fill ? 1 : 0}, 'wght' ${weight}, 'GRAD' ${grade}, 'opsz' ${opsz}`,
16
+ }
17
+ : null;
18
+ return ((0, jsx_runtime_1.jsx)(react_native_1.Text, { selectable: false, accessibilityElementsHidden: true, importantForAccessibility: "no", style: [
9
19
  {
10
20
  fontFamily: FONT_FAMILY,
11
21
  fontSize: size,
@@ -22,7 +32,7 @@ export function Icon({ name, size = 20, color = '#374151', style }) {
22
32
  textTransform: 'none',
23
33
  textDecorationLine: 'none',
24
34
  },
35
+ variationStyle,
25
36
  style,
26
37
  ], children: name }));
27
38
  }
28
- //# sourceMappingURL=Icon.js.map
@@ -1,2 +1 @@
1
1
  export { Icon, type IconProps } from './Icon';
2
- //# sourceMappingURL=index.d.ts.map
@@ -1,2 +1,5 @@
1
- export { Icon } from './Icon';
2
- //# sourceMappingURL=index.js.map
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Icon = void 0;
4
+ var Icon_1 = require("./Icon");
5
+ Object.defineProperty(exports, "Icon", { enumerable: true, get: function () { return Icon_1.Icon; } });
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Input — single-line text field with label and helper/error text.
3
+ *
4
+ * Maps to the Figma <Input> component (node 307:3476):
5
+ * size → small | default | large
6
+ * state → default | hover | focus | error | disabled
7
+ *
8
+ * `error` and `disabled` are props; `hover` and `focus` are interaction-driven.
9
+ * Field spacing comes from the density theme's `input` tokens (shared with the
10
+ * Select trigger). Colours come from the semantic intent system (neutral):
11
+ * default → neutral/default/default hover → neutral/default/hover
12
+ * focus → focus-ring border (2px) error → danger border + red helper
13
+ * disabled→ shared disabled colours
14
+ * Label uses the label scale, the value/placeholder the body scale (both
15
+ * matched to size); helper text uses the caption scale.
16
+ */
17
+ import React from 'react';
18
+ import { type ViewStyle, type StyleProp, type KeyboardTypeOptions, type ReturnKeyTypeOptions } from 'react-native';
19
+ export type InputSize = 'small' | 'default' | 'large';
20
+ export type InputProps = {
21
+ /** Form label above the field. */
22
+ label?: string;
23
+ /** Helper text below the field — turns red when `error` is set. */
24
+ helperText?: string;
25
+ /** Placeholder shown when the field is empty. */
26
+ placeholder?: string;
27
+ /** Controlled value. */
28
+ value?: string;
29
+ /** Uncontrolled initial value. */
30
+ defaultValue?: string;
31
+ /** Change handler — receives the new text. */
32
+ onChangeText?: (text: string) => void;
33
+ /** Size variant — controls padding, gap, and typography scale. */
34
+ size?: InputSize;
35
+ /** Error state — danger border and red helper text. */
36
+ error?: boolean;
37
+ /** Disables interaction and applies muted styling. */
38
+ disabled?: boolean;
39
+ /** Leading icon — Material Symbols name string or a ReactNode. */
40
+ leadingIcon?: string | React.ReactNode;
41
+ /** Trailing icon — Material Symbols name string or a ReactNode. */
42
+ trailingIcon?: string | React.ReactNode;
43
+ /** Masks the text (passwords). */
44
+ secureTextEntry?: boolean;
45
+ /** Keyboard type for native platforms. */
46
+ keyboardType?: KeyboardTypeOptions;
47
+ /** Auto-capitalisation behaviour. */
48
+ autoCapitalize?: 'none' | 'sentences' | 'words' | 'characters';
49
+ /** Return key label for native platforms. */
50
+ returnKeyType?: ReturnKeyTypeOptions;
51
+ /** Submit (return key) handler. */
52
+ onSubmitEditing?: () => void;
53
+ /** Focus handler. */
54
+ onFocus?: () => void;
55
+ /** Blur handler. */
56
+ onBlur?: () => void;
57
+ /** Style override for the outer container. */
58
+ style?: StyleProp<ViewStyle>;
59
+ /** Accessibility label — falls back to the label prop. */
60
+ accessibilityLabel?: string;
61
+ };
62
+ export declare function Input({ label: formLabel, helperText, placeholder, value, defaultValue, onChangeText, size, error, disabled, leadingIcon, trailingIcon, secureTextEntry, keyboardType, autoCapitalize, returnKeyType, onSubmitEditing, onFocus, onBlur, style, accessibilityLabel, }: InputProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,141 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Input = Input;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ /**
6
+ * Input — single-line text field with label and helper/error text.
7
+ *
8
+ * Maps to the Figma <Input> component (node 307:3476):
9
+ * size → small | default | large
10
+ * state → default | hover | focus | error | disabled
11
+ *
12
+ * `error` and `disabled` are props; `hover` and `focus` are interaction-driven.
13
+ * Field spacing comes from the density theme's `input` tokens (shared with the
14
+ * Select trigger). Colours come from the semantic intent system (neutral):
15
+ * default → neutral/default/default hover → neutral/default/hover
16
+ * focus → focus-ring border (2px) error → danger border + red helper
17
+ * disabled→ shared disabled colours
18
+ * Label uses the label scale, the value/placeholder the body scale (both
19
+ * matched to size); helper text uses the caption scale.
20
+ */
21
+ const react_1 = require("react");
22
+ const react_native_1 = require("react-native");
23
+ const theme_1 = require("../../theme");
24
+ const Icon_1 = require("../Icon");
25
+ const tokens_1 = require("../../tokens");
26
+ // ---------------------------------------------------------------------------
27
+ // Constants
28
+ // ---------------------------------------------------------------------------
29
+ const ICON_SIZE = 16;
30
+ /** Maps input size → label typography scale (form label text) */
31
+ const LABEL_SCALE = {
32
+ small: 'sm',
33
+ default: 'md',
34
+ large: 'lg',
35
+ };
36
+ /** Maps input size → body typography scale (value + placeholder text) */
37
+ const BODY_SCALE = {
38
+ small: 'sm',
39
+ default: 'md',
40
+ large: 'lg',
41
+ };
42
+ // ---------------------------------------------------------------------------
43
+ // Component
44
+ // ---------------------------------------------------------------------------
45
+ function Input({ label: formLabel, helperText, placeholder, value, defaultValue, onChangeText, size = 'default', error = false, disabled = false, leadingIcon, trailingIcon, secureTextEntry, keyboardType, autoCapitalize, returnKeyType, onSubmitEditing, onFocus, onBlur, style, accessibilityLabel, }) {
46
+ const { components, scheme } = (0, theme_1.useTheme)();
47
+ const sizeTokens = components.input[size];
48
+ const labelTypo = tokens_1.label[LABEL_SCALE[size]];
49
+ const bodyTypo = tokens_1.body[BODY_SCALE[size]];
50
+ const [isHovered, setIsHovered] = (0, react_1.useState)(false);
51
+ const [isFocused, setIsFocused] = (0, react_1.useState)(false);
52
+ const disabledColors = scheme.disabled;
53
+ const errorTokens = scheme.error;
54
+ const textTokens = scheme.text;
55
+ const neutral = scheme.intents.neutral.default;
56
+ // Resolve field colours — state priority: disabled > error > focus > hover > default
57
+ let bg;
58
+ let borderColor;
59
+ let borderWidth;
60
+ if (disabled) {
61
+ bg = disabledColors.bg;
62
+ borderColor = disabledColors.border;
63
+ borderWidth = tokens_1.controlTokens.borderWidth;
64
+ }
65
+ else if (isFocused) {
66
+ bg = neutral.default.bg;
67
+ borderColor = scheme.focusRing.color;
68
+ borderWidth = tokens_1.controlTokens.focusRingWidth;
69
+ }
70
+ else if (error) {
71
+ bg = neutral.default.bg;
72
+ borderColor = errorTokens.border;
73
+ borderWidth = tokens_1.controlTokens.borderWidth;
74
+ }
75
+ else if (isHovered) {
76
+ bg = neutral.hover.bg;
77
+ borderColor = neutral.hover.border;
78
+ borderWidth = tokens_1.controlTokens.borderWidth;
79
+ }
80
+ else {
81
+ bg = neutral.default.bg;
82
+ borderColor = neutral.default.border;
83
+ borderWidth = tokens_1.controlTokens.borderWidth;
84
+ }
85
+ const textColor = disabled ? disabledColors.fg : neutral.default.fg;
86
+ const labelColor = disabled ? disabledColors.fg : neutral.default.fg;
87
+ const helperColor = disabled
88
+ ? disabledColors.fg
89
+ : error
90
+ ? errorTokens.fg
91
+ : textTokens.description;
92
+ const iconColor = disabled ? disabledColors.fg : neutral.default.fg;
93
+ const resolvedLeading = typeof leadingIcon === 'string' ? ((0, jsx_runtime_1.jsx)(Icon_1.Icon, { name: leadingIcon, size: ICON_SIZE, color: iconColor })) : (leadingIcon);
94
+ const resolvedTrailing = typeof trailingIcon === 'string' ? ((0, jsx_runtime_1.jsx)(Icon_1.Icon, { name: trailingIcon, size: ICON_SIZE, color: iconColor })) : (trailingIcon);
95
+ return ((0, jsx_runtime_1.jsxs)(react_native_1.View, { style: [
96
+ { alignSelf: 'stretch', gap: components.input.fieldGap },
97
+ style,
98
+ ], children: [formLabel ? ((0, jsx_runtime_1.jsx)(react_native_1.Text, { style: {
99
+ fontFamily: tokens_1.fontFamily.sans,
100
+ fontWeight: tokens_1.fontWeight.medium,
101
+ fontSize: labelTypo.fontSize,
102
+ lineHeight: labelTypo.lineHeight,
103
+ letterSpacing: labelTypo.letterSpacing,
104
+ color: labelColor,
105
+ }, selectable: false, children: formLabel })) : null, (0, jsx_runtime_1.jsxs)(react_native_1.View, { onPointerEnter: disabled ? undefined : () => setIsHovered(true), onPointerLeave: disabled ? undefined : () => setIsHovered(false), style: {
106
+ flexDirection: 'row',
107
+ alignItems: 'center',
108
+ gap: sizeTokens.gap,
109
+ paddingHorizontal: sizeTokens.paddingX,
110
+ paddingVertical: sizeTokens.paddingY,
111
+ borderRadius: sizeTokens.borderRadius,
112
+ borderWidth,
113
+ borderColor,
114
+ backgroundColor: bg,
115
+ }, children: [resolvedLeading ? ((0, jsx_runtime_1.jsx)(react_native_1.View, { accessibilityElementsHidden: true, importantForAccessibility: "no", style: { width: ICON_SIZE, height: ICON_SIZE }, children: resolvedLeading })) : null, (0, jsx_runtime_1.jsx)(react_native_1.TextInput, { value: value, defaultValue: defaultValue, onChangeText: onChangeText, placeholder: placeholder, placeholderTextColor: textTokens.placeholder, editable: !disabled, secureTextEntry: secureTextEntry, keyboardType: keyboardType, autoCapitalize: autoCapitalize, returnKeyType: returnKeyType, onSubmitEditing: onSubmitEditing, onFocus: () => {
116
+ setIsFocused(true);
117
+ onFocus?.();
118
+ }, onBlur: () => {
119
+ setIsFocused(false);
120
+ onBlur?.();
121
+ }, accessibilityLabel: accessibilityLabel || formLabel, style: {
122
+ flex: 1,
123
+ fontFamily: tokens_1.fontFamily.sans,
124
+ fontWeight: tokens_1.fontWeight.regular,
125
+ fontSize: bodyTypo.fontSize,
126
+ lineHeight: bodyTypo.lineHeight,
127
+ letterSpacing: bodyTypo.letterSpacing,
128
+ color: textColor,
129
+ padding: 0,
130
+ ...(react_native_1.Platform.OS === 'web'
131
+ ? { outlineWidth: 0 }
132
+ : {}),
133
+ } }), resolvedTrailing ? ((0, jsx_runtime_1.jsx)(react_native_1.View, { accessibilityElementsHidden: true, importantForAccessibility: "no", style: { width: ICON_SIZE, height: ICON_SIZE }, children: resolvedTrailing })) : null] }), helperText ? ((0, jsx_runtime_1.jsx)(react_native_1.Text, { style: {
134
+ fontFamily: tokens_1.fontFamily.sans,
135
+ fontWeight: tokens_1.fontWeight.regular,
136
+ fontSize: tokens_1.caption.fontSize,
137
+ lineHeight: tokens_1.caption.lineHeight,
138
+ letterSpacing: tokens_1.caption.letterSpacing,
139
+ color: helperColor,
140
+ }, selectable: false, children: helperText })) : null] }));
141
+ }
@@ -0,0 +1 @@
1
+ export { Input, type InputProps, type InputSize } from './Input';
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Input = void 0;
4
+ var Input_1 = require("./Input");
5
+ Object.defineProperty(exports, "Input", { enumerable: true, get: function () { return Input_1.Input; } });
@@ -0,0 +1,58 @@
1
+ /**
2
+ * List — vertical collection of items with optional section subheaders.
3
+ *
4
+ * Maps to the Figma <List> component (node 452:3401):
5
+ * List — the container surface (white bg, 1px section gap)
6
+ * ListSubheader — muted caption label for a section ("Inbox", "Labels")
7
+ * ListItem — icon + label + optional description, with
8
+ * default / selected / disabled states
9
+ * ListDivider — horizontal rule between sections
10
+ *
11
+ * Density (compact/default/comfortable) drives item padding, gap, and
12
+ * icon size via the theme's `list` tokens. Colours come from the theme's
13
+ * colour scheme (`scheme.list`, constant across densities).
14
+ */
15
+ import React from 'react';
16
+ import { type ViewStyle, type StyleProp, type GestureResponderEvent } from 'react-native';
17
+ export type ListProps = {
18
+ /** ListItem / ListSubheader / ListDivider children. */
19
+ children: React.ReactNode;
20
+ /** Style override for the outer container. */
21
+ style?: StyleProp<ViewStyle>;
22
+ /** Accessibility label for the list region. */
23
+ accessibilityLabel?: string;
24
+ };
25
+ export declare function List({ children, style, accessibilityLabel }: ListProps): import("react/jsx-runtime").JSX.Element;
26
+ export type ListSubheaderProps = {
27
+ /** Subheader label text. */
28
+ children: string;
29
+ /** Style override. */
30
+ style?: StyleProp<ViewStyle>;
31
+ };
32
+ export declare function ListSubheader({ children, style }: ListSubheaderProps): import("react/jsx-runtime").JSX.Element;
33
+ export type ListDividerProps = {
34
+ /** Style override for the divider line. */
35
+ style?: StyleProp<ViewStyle>;
36
+ };
37
+ export declare function ListDivider({ style }: ListDividerProps): import("react/jsx-runtime").JSX.Element;
38
+ export type ListItemProps = {
39
+ /** Primary label text. */
40
+ children: string;
41
+ /** Supporting description text below the label. */
42
+ description?: string;
43
+ /** Leading icon — Material Symbols name string or a ReactNode. */
44
+ icon?: string | React.ReactNode;
45
+ /** Trailing icon — Material Symbols name string or a ReactNode. */
46
+ trailingIcon?: string | React.ReactNode;
47
+ /** Marks the item as selected (highlighted). */
48
+ selected?: boolean;
49
+ /** Disables interaction and applies muted styling. */
50
+ disabled?: boolean;
51
+ /** Press handler. */
52
+ onPress?: (e: GestureResponderEvent) => void;
53
+ /** Style override for the item row. */
54
+ style?: StyleProp<ViewStyle>;
55
+ /** Accessibility label — falls back to the label text. */
56
+ accessibilityLabel?: string;
57
+ };
58
+ export declare function ListItem({ children, description, icon, trailingIcon, selected, disabled, onPress, style, accessibilityLabel, }: ListItemProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,116 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.List = List;
4
+ exports.ListSubheader = ListSubheader;
5
+ exports.ListDivider = ListDivider;
6
+ exports.ListItem = ListItem;
7
+ const jsx_runtime_1 = require("react/jsx-runtime");
8
+ /**
9
+ * List — vertical collection of items with optional section subheaders.
10
+ *
11
+ * Maps to the Figma <List> component (node 452:3401):
12
+ * List — the container surface (white bg, 1px section gap)
13
+ * ListSubheader — muted caption label for a section ("Inbox", "Labels")
14
+ * ListItem — icon + label + optional description, with
15
+ * default / selected / disabled states
16
+ * ListDivider — horizontal rule between sections
17
+ *
18
+ * Density (compact/default/comfortable) drives item padding, gap, and
19
+ * icon size via the theme's `list` tokens. Colours come from the theme's
20
+ * colour scheme (`scheme.list`, constant across densities).
21
+ */
22
+ const react_1 = require("react");
23
+ const react_native_1 = require("react-native");
24
+ const theme_1 = require("../../theme");
25
+ const Icon_1 = require("../Icon");
26
+ const tokens_1 = require("../../tokens");
27
+ function List({ children, style, accessibilityLabel }) {
28
+ const { components, scheme } = (0, theme_1.useTheme)();
29
+ const listColors = scheme.list;
30
+ const tokens = components.list;
31
+ return ((0, jsx_runtime_1.jsx)(react_native_1.View, { accessibilityRole: "list", accessibilityLabel: accessibilityLabel, style: [
32
+ {
33
+ backgroundColor: listColors.containerBg,
34
+ gap: tokens.sectionGap,
35
+ alignSelf: 'stretch',
36
+ },
37
+ style,
38
+ ], children: children }));
39
+ }
40
+ function ListSubheader({ children, style }) {
41
+ const { components, scheme } = (0, theme_1.useTheme)();
42
+ const listColors = scheme.list;
43
+ const tokens = components.list.subheader;
44
+ return ((0, jsx_runtime_1.jsx)(react_native_1.View, { style: [
45
+ {
46
+ paddingHorizontal: tokens.paddingX,
47
+ paddingVertical: tokens.paddingY,
48
+ },
49
+ style,
50
+ ], children: (0, jsx_runtime_1.jsx)(react_native_1.Text, { style: {
51
+ fontFamily: tokens_1.fontFamily.sans,
52
+ fontWeight: tokens_1.fontWeight.regular,
53
+ fontSize: tokens_1.caption.fontSize,
54
+ lineHeight: tokens_1.caption.lineHeight,
55
+ letterSpacing: tokens_1.caption.letterSpacing,
56
+ color: listColors.subheaderFg,
57
+ }, selectable: false, children: children }) }));
58
+ }
59
+ function ListDivider({ style }) {
60
+ const { scheme } = (0, theme_1.useTheme)();
61
+ const listColors = scheme.list;
62
+ return ((0, jsx_runtime_1.jsx)(react_native_1.View, { accessibilityRole: "none", style: [
63
+ {
64
+ height: 1,
65
+ backgroundColor: listColors.separator,
66
+ },
67
+ style,
68
+ ] }));
69
+ }
70
+ function ListItem({ children, description, icon, trailingIcon, selected = false, disabled = false, onPress, style, accessibilityLabel, }) {
71
+ const { components, scheme } = (0, theme_1.useTheme)();
72
+ const listColors = scheme.list;
73
+ const tokens = components.list.item;
74
+ const [isHovered, setIsHovered] = (0, react_1.useState)(false);
75
+ // State priority: disabled > selected+hover > selected > hover > default
76
+ const colors = disabled
77
+ ? listColors.item.disabled
78
+ : selected && isHovered
79
+ ? listColors.item.selectedHover
80
+ : selected
81
+ ? listColors.item.selected
82
+ : isHovered
83
+ ? listColors.item.hover
84
+ : listColors.item.default;
85
+ const resolvedIcon = typeof icon === 'string' ? ((0, jsx_runtime_1.jsx)(Icon_1.Icon, { name: icon, size: tokens.iconSize, color: colors.fg })) : (icon);
86
+ const resolvedTrailing = typeof trailingIcon === 'string' ? ((0, jsx_runtime_1.jsx)(Icon_1.Icon, { name: trailingIcon, size: tokens.iconSize, color: colors.fg })) : (trailingIcon);
87
+ return ((0, jsx_runtime_1.jsxs)(react_native_1.Pressable, { onPress: (e) => {
88
+ if (!disabled)
89
+ onPress?.(e);
90
+ }, onHoverIn: () => setIsHovered(true), onHoverOut: () => setIsHovered(false), disabled: disabled || !onPress, accessibilityRole: "menuitem", accessibilityLabel: accessibilityLabel || children, accessibilityState: { selected, disabled }, style: [
91
+ {
92
+ flexDirection: 'row',
93
+ alignItems: 'flex-start',
94
+ gap: tokens.gap,
95
+ paddingHorizontal: tokens.paddingX,
96
+ paddingVertical: tokens.paddingY,
97
+ borderRadius: tokens.borderRadius,
98
+ backgroundColor: colors.bg,
99
+ },
100
+ style,
101
+ ], children: [resolvedIcon ? ((0, jsx_runtime_1.jsx)(react_native_1.View, { accessibilityElementsHidden: true, importantForAccessibility: "no", style: { width: tokens.iconSize, height: tokens.iconSize }, children: resolvedIcon })) : null, (0, jsx_runtime_1.jsxs)(react_native_1.View, { style: { flex: 1, justifyContent: 'center' }, children: [(0, jsx_runtime_1.jsx)(react_native_1.Text, { style: {
102
+ fontFamily: tokens_1.fontFamily.sans,
103
+ fontWeight: tokens_1.fontWeight.medium,
104
+ fontSize: tokens_1.label.md.fontSize,
105
+ lineHeight: tokens_1.label.md.lineHeight,
106
+ letterSpacing: tokens_1.label.md.letterSpacing,
107
+ color: colors.fg,
108
+ }, selectable: false, children: children }), description ? ((0, jsx_runtime_1.jsx)(react_native_1.Text, { style: {
109
+ fontFamily: tokens_1.fontFamily.sans,
110
+ fontWeight: tokens_1.fontWeight.regular,
111
+ fontSize: tokens_1.body.md.fontSize,
112
+ lineHeight: tokens_1.body.md.lineHeight,
113
+ letterSpacing: tokens_1.body.md.letterSpacing,
114
+ color: disabled ? colors.fg : listColors.descriptionFg,
115
+ }, selectable: false, children: description })) : null] }), resolvedTrailing ? ((0, jsx_runtime_1.jsx)(react_native_1.View, { accessibilityElementsHidden: true, importantForAccessibility: "no", style: { width: tokens.iconSize, height: tokens.iconSize }, children: resolvedTrailing })) : null] }));
116
+ }
@@ -0,0 +1 @@
1
+ export { List, ListItem, ListSubheader, ListDivider, type ListProps, type ListItemProps, type ListSubheaderProps, type ListDividerProps, } from './List';
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ListDivider = exports.ListSubheader = exports.ListItem = exports.List = void 0;
4
+ var List_1 = require("./List");
5
+ Object.defineProperty(exports, "List", { enumerable: true, get: function () { return List_1.List; } });
6
+ Object.defineProperty(exports, "ListItem", { enumerable: true, get: function () { return List_1.ListItem; } });
7
+ Object.defineProperty(exports, "ListSubheader", { enumerable: true, get: function () { return List_1.ListSubheader; } });
8
+ Object.defineProperty(exports, "ListDivider", { enumerable: true, get: function () { return List_1.ListDivider; } });
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Popover — a floating surface that points at an anchor with an arrow.
3
+ *
4
+ * Maps to the Figma <Popover> component (node 307:4149):
5
+ * direction → top | bottom | left | right (the edge the arrow sits on)
6
+ * size → small | default | large (drives content padding)
7
+ *
8
+ * This is the presentational bubble only: it renders the overlay surface
9
+ * (white background, 8px radius, shadow/md) with a directional arrow and your
10
+ * `children` inside. Positioning relative to a trigger is the caller's job —
11
+ * wrap it in a positioned container or pass a `style` with absolute coords.
12
+ *
13
+ * Padding comes from the `popover` density theme (size × density); the radius
14
+ * and arrow size are constant across densities.
15
+ */
16
+ import React from 'react';
17
+ import { type ViewStyle, type StyleProp } from 'react-native';
18
+ export type PopoverSize = 'small' | 'default' | 'large';
19
+ export type PopoverDirection = 'top' | 'bottom' | 'left' | 'right';
20
+ export type PopoverProps = {
21
+ /** Content rendered inside the bubble. */
22
+ children: React.ReactNode;
23
+ /** The edge the arrow sits on (points away from the bubble). */
24
+ direction?: PopoverDirection;
25
+ /** Size variant — controls content padding. */
26
+ size?: PopoverSize;
27
+ /** Hide the directional arrow. */
28
+ hideArrow?: boolean;
29
+ /** Outer style — use for positioning (absolute coords, margin, width). */
30
+ style?: StyleProp<ViewStyle>;
31
+ /** Accessibility label for the popover surface. */
32
+ accessibilityLabel?: string;
33
+ };
34
+ export declare function Popover({ children, direction, size, hideArrow, style, accessibilityLabel, }: PopoverProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Popover = Popover;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_native_1 = require("react-native");
6
+ const theme_1 = require("../../theme");
7
+ // ---------------------------------------------------------------------------
8
+ // Constants
9
+ // ---------------------------------------------------------------------------
10
+ /** shadow/md — overlay drop shadow (two stacked layers). */
11
+ const SHADOW_WEB = {
12
+ boxShadow: '0px 4px 6px -1px rgba(0,0,0,0.07), 0px 2px 4px -2px rgba(0,0,0,0.05)',
13
+ };
14
+ const SHADOW_NATIVE = {
15
+ shadowColor: '#000000',
16
+ shadowOffset: { width: 0, height: 4 },
17
+ shadowOpacity: 0.07,
18
+ shadowRadius: 6,
19
+ elevation: 4,
20
+ };
21
+ const SHADOW = react_native_1.Platform.OS === 'web' ? SHADOW_WEB : SHADOW_NATIVE;
22
+ // ---------------------------------------------------------------------------
23
+ // Component
24
+ // ---------------------------------------------------------------------------
25
+ /** Positions the rotated-square arrow on the requested edge, centred. */
26
+ function arrowStyle(direction, arrowSize, backgroundColor) {
27
+ const half = arrowSize / 2;
28
+ const base = {
29
+ position: 'absolute',
30
+ width: arrowSize,
31
+ height: arrowSize,
32
+ backgroundColor,
33
+ transform: [{ rotate: '45deg' }],
34
+ };
35
+ switch (direction) {
36
+ case 'top':
37
+ return { ...base, top: -half, left: '50%', marginLeft: -half };
38
+ case 'left':
39
+ return { ...base, left: -half, top: '50%', marginTop: -half };
40
+ case 'right':
41
+ return { ...base, right: -half, top: '50%', marginTop: -half };
42
+ case 'bottom':
43
+ default:
44
+ return { ...base, bottom: -half, left: '50%', marginLeft: -half };
45
+ }
46
+ }
47
+ function Popover({ children, direction = 'bottom', size = 'default', hideArrow = false, style, accessibilityLabel, }) {
48
+ const { components, scheme } = (0, theme_1.useTheme)();
49
+ const surfaceTokens = scheme.surface;
50
+ const tokens = components.popover;
51
+ const sizeTokens = tokens[size];
52
+ return ((0, jsx_runtime_1.jsxs)(react_native_1.View, { accessibilityLabel: accessibilityLabel, style: [
53
+ {
54
+ alignSelf: 'flex-start',
55
+ backgroundColor: surfaceTokens.overlay.bg,
56
+ borderRadius: tokens.borderRadius,
57
+ padding: sizeTokens.padding,
58
+ ...SHADOW,
59
+ },
60
+ style,
61
+ ], children: [!hideArrow ? ((0, jsx_runtime_1.jsx)(react_native_1.View, { accessibilityElementsHidden: true, importantForAccessibility: "no", style: arrowStyle(direction, tokens.arrowSize, surfaceTokens.overlay.bg) })) : null, children] }));
62
+ }
@@ -0,0 +1 @@
1
+ export { Popover, type PopoverProps, type PopoverSize, type PopoverDirection, } from './Popover';
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Popover = void 0;
4
+ var Popover_1 = require("./Popover");
5
+ Object.defineProperty(exports, "Popover", { enumerable: true, get: function () { return Popover_1.Popover; } });