@castui/cast-ui 4.1.1 → 4.2.0

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 (155) hide show
  1. package/README.md +129 -19
  2. package/dist/components/Alert/Alert.d.ts +41 -0
  3. package/dist/components/Alert/Alert.d.ts.map +1 -0
  4. package/dist/components/Alert/Alert.js +69 -0
  5. package/dist/components/Alert/Alert.js.map +1 -0
  6. package/dist/components/Alert/index.d.ts +2 -0
  7. package/dist/components/Alert/index.d.ts.map +1 -0
  8. package/dist/components/Alert/index.js +2 -0
  9. package/dist/components/Alert/index.js.map +1 -0
  10. package/dist/components/Avatar/Avatar.d.ts +32 -0
  11. package/dist/components/Avatar/Avatar.d.ts.map +1 -0
  12. package/dist/components/Avatar/Avatar.js +53 -0
  13. package/dist/components/Avatar/Avatar.js.map +1 -0
  14. package/dist/components/Avatar/index.d.ts +2 -0
  15. package/dist/components/Avatar/index.d.ts.map +1 -0
  16. package/dist/components/Avatar/index.js +2 -0
  17. package/dist/components/Avatar/index.js.map +1 -0
  18. package/dist/components/Badge/Badge.d.ts +42 -0
  19. package/dist/components/Badge/Badge.d.ts.map +1 -0
  20. package/dist/components/Badge/Badge.js +69 -0
  21. package/dist/components/Badge/Badge.js.map +1 -0
  22. package/dist/components/Badge/index.d.ts +2 -0
  23. package/dist/components/Badge/index.d.ts.map +1 -0
  24. package/dist/components/Badge/index.js +2 -0
  25. package/dist/components/Badge/index.js.map +1 -0
  26. package/dist/components/Card/Card.d.ts +42 -0
  27. package/dist/components/Card/Card.d.ts.map +1 -0
  28. package/dist/components/Card/Card.js +89 -0
  29. package/dist/components/Card/Card.js.map +1 -0
  30. package/dist/components/Card/index.d.ts +2 -0
  31. package/dist/components/Card/index.d.ts.map +1 -0
  32. package/dist/components/Card/index.js +2 -0
  33. package/dist/components/Card/index.js.map +1 -0
  34. package/dist/components/Checkbox/Checkbox.d.ts +33 -0
  35. package/dist/components/Checkbox/Checkbox.d.ts.map +1 -0
  36. package/dist/components/Checkbox/Checkbox.js +105 -0
  37. package/dist/components/Checkbox/Checkbox.js.map +1 -0
  38. package/dist/components/Checkbox/index.d.ts +2 -0
  39. package/dist/components/Checkbox/index.d.ts.map +1 -0
  40. package/dist/components/Checkbox/index.js +2 -0
  41. package/dist/components/Checkbox/index.js.map +1 -0
  42. package/dist/components/Chip/Chip.d.ts +47 -0
  43. package/dist/components/Chip/Chip.d.ts.map +1 -0
  44. package/dist/components/Chip/Chip.js +80 -0
  45. package/dist/components/Chip/Chip.js.map +1 -0
  46. package/dist/components/Chip/index.d.ts +2 -0
  47. package/dist/components/Chip/index.d.ts.map +1 -0
  48. package/dist/components/Chip/index.js +2 -0
  49. package/dist/components/Chip/index.js.map +1 -0
  50. package/dist/components/Dialog/Dialog.d.ts.map +1 -1
  51. package/dist/components/Dialog/Dialog.js +6 -2
  52. package/dist/components/Dialog/Dialog.js.map +1 -1
  53. package/dist/components/Divider/Divider.d.ts +23 -0
  54. package/dist/components/Divider/Divider.d.ts.map +1 -0
  55. package/dist/components/Divider/Divider.js +17 -0
  56. package/dist/components/Divider/Divider.js.map +1 -0
  57. package/dist/components/Divider/index.d.ts +2 -0
  58. package/dist/components/Divider/index.d.ts.map +1 -0
  59. package/dist/components/Divider/index.js +2 -0
  60. package/dist/components/Divider/index.js.map +1 -0
  61. package/dist/components/Icon/Icon.d.ts +26 -8
  62. package/dist/components/Icon/Icon.d.ts.map +1 -1
  63. package/dist/components/Icon/Icon.js +9 -1
  64. package/dist/components/Icon/Icon.js.map +1 -1
  65. package/dist/components/Input/Input.d.ts +63 -0
  66. package/dist/components/Input/Input.d.ts.map +1 -0
  67. package/dist/components/Input/Input.js +139 -0
  68. package/dist/components/Input/Input.js.map +1 -0
  69. package/dist/components/Input/index.d.ts +2 -0
  70. package/dist/components/Input/index.d.ts.map +1 -0
  71. package/dist/components/Input/index.js +2 -0
  72. package/dist/components/Input/index.js.map +1 -0
  73. package/dist/components/List/List.d.ts +59 -0
  74. package/dist/components/List/List.d.ts.map +1 -0
  75. package/dist/components/List/List.js +111 -0
  76. package/dist/components/List/List.js.map +1 -0
  77. package/dist/components/List/index.d.ts +2 -0
  78. package/dist/components/List/index.d.ts.map +1 -0
  79. package/dist/components/List/index.js +2 -0
  80. package/dist/components/List/index.js.map +1 -0
  81. package/dist/components/Popover/Popover.d.ts +35 -0
  82. package/dist/components/Popover/Popover.d.ts.map +1 -0
  83. package/dist/components/Popover/Popover.js +60 -0
  84. package/dist/components/Popover/Popover.js.map +1 -0
  85. package/dist/components/Popover/index.d.ts +2 -0
  86. package/dist/components/Popover/index.d.ts.map +1 -0
  87. package/dist/components/Popover/index.js +2 -0
  88. package/dist/components/Popover/index.js.map +1 -0
  89. package/dist/components/Radio/Radio.d.ts +53 -0
  90. package/dist/components/Radio/Radio.d.ts.map +1 -0
  91. package/dist/components/Radio/Radio.js +124 -0
  92. package/dist/components/Radio/Radio.js.map +1 -0
  93. package/dist/components/Radio/index.d.ts +2 -0
  94. package/dist/components/Radio/index.d.ts.map +1 -0
  95. package/dist/components/Radio/index.js +2 -0
  96. package/dist/components/Radio/index.js.map +1 -0
  97. package/dist/components/Select/Select.d.ts.map +1 -1
  98. package/dist/components/Select/Select.js +20 -9
  99. package/dist/components/Select/Select.js.map +1 -1
  100. package/dist/components/Skeleton/Skeleton.d.ts +34 -0
  101. package/dist/components/Skeleton/Skeleton.d.ts.map +1 -0
  102. package/dist/components/Skeleton/Skeleton.js +64 -0
  103. package/dist/components/Skeleton/Skeleton.js.map +1 -0
  104. package/dist/components/Skeleton/index.d.ts +2 -0
  105. package/dist/components/Skeleton/index.d.ts.map +1 -0
  106. package/dist/components/Skeleton/index.js +2 -0
  107. package/dist/components/Skeleton/index.js.map +1 -0
  108. package/dist/components/Toast/Toast.d.ts +36 -0
  109. package/dist/components/Toast/Toast.d.ts.map +1 -0
  110. package/dist/components/Toast/Toast.js +77 -0
  111. package/dist/components/Toast/Toast.js.map +1 -0
  112. package/dist/components/Toast/index.d.ts +2 -0
  113. package/dist/components/Toast/index.d.ts.map +1 -0
  114. package/dist/components/Toast/index.js +2 -0
  115. package/dist/components/Toast/index.js.map +1 -0
  116. package/dist/components/Toggle/Toggle.d.ts +32 -0
  117. package/dist/components/Toggle/Toggle.d.ts.map +1 -0
  118. package/dist/components/Toggle/Toggle.js +89 -0
  119. package/dist/components/Toggle/Toggle.js.map +1 -0
  120. package/dist/components/Toggle/index.d.ts +2 -0
  121. package/dist/components/Toggle/index.d.ts.map +1 -0
  122. package/dist/components/Toggle/index.js +2 -0
  123. package/dist/components/Toggle/index.js.map +1 -0
  124. package/dist/components/Tooltip/Tooltip.d.ts +35 -0
  125. package/dist/components/Tooltip/Tooltip.d.ts.map +1 -0
  126. package/dist/components/Tooltip/Tooltip.js +65 -0
  127. package/dist/components/Tooltip/Tooltip.js.map +1 -0
  128. package/dist/components/Tooltip/index.d.ts +2 -0
  129. package/dist/components/Tooltip/index.d.ts.map +1 -0
  130. package/dist/components/Tooltip/index.js +2 -0
  131. package/dist/components/Tooltip/index.js.map +1 -0
  132. package/dist/index.d.ts +17 -2
  133. package/dist/index.d.ts.map +1 -1
  134. package/dist/index.js +16 -1
  135. package/dist/index.js.map +1 -1
  136. package/dist/theme/ThemeContext.d.ts +24 -7
  137. package/dist/theme/ThemeContext.d.ts.map +1 -1
  138. package/dist/theme/ThemeContext.js +27 -11
  139. package/dist/theme/ThemeContext.js.map +1 -1
  140. package/dist/theme/index.d.ts +1 -1
  141. package/dist/theme/index.d.ts.map +1 -1
  142. package/dist/theme/themes.d.ts.map +1 -1
  143. package/dist/theme/themes.js +210 -0
  144. package/dist/theme/themes.js.map +1 -1
  145. package/dist/theme/types.d.ts +183 -0
  146. package/dist/theme/types.d.ts.map +1 -1
  147. package/dist/tokens/colors.d.ts +294 -25
  148. package/dist/tokens/colors.d.ts.map +1 -1
  149. package/dist/tokens/colors.js +319 -96
  150. package/dist/tokens/colors.js.map +1 -1
  151. package/dist/tokens/index.d.ts +1 -1
  152. package/dist/tokens/index.d.ts.map +1 -1
  153. package/dist/tokens/index.js +1 -1
  154. package/dist/tokens/index.js.map +1 -1
  155. package/package.json +1 -1
package/README.md CHANGED
@@ -1,8 +1,14 @@
1
1
  # Cast UI
2
2
 
3
- A cross-platform component library for React Native (iOS, Android, Web).
3
+ A cross-platform component library for React Native. One set of components
4
+ that works on iOS, Android, and the web.
4
5
 
5
- > Components are currently being built. Check back soon.
6
+ Every colour, size, and spacing value in Cast UI comes from design tokens
7
+ kept in sync with the
8
+ [cast-ui-kit Figma file](https://www.figma.com/design/JGtlpxLPJMZcwvQ3UZ9ZUl/cast-ui-kit),
9
+ so what designers see in Figma is what ships in the app. Every component
10
+ supports light and dark mode, three spacing densities, and your own brand
11
+ colours — all switchable while the app is running, with no rebuild.
6
12
 
7
13
  ## Installation
8
14
 
@@ -10,36 +16,140 @@ A cross-platform component library for React Native (iOS, Android, Web).
10
16
  npm install @castui/cast-ui
11
17
  ```
12
18
 
13
- **Peer dependencies:** `react` (>=18), `react-native` (>=0.72)
19
+ **Peer dependencies:** `react` (>=18) and `react-native` (>=0.72). Nothing
20
+ else is installed alongside the package.
21
+
22
+ ```tsx
23
+ import { ThemeProvider, Button } from '@castui/cast-ui';
24
+
25
+ export function App() {
26
+ return (
27
+ <ThemeProvider>
28
+ <Button intent="brand" prominence="bold" onPress={save}>
29
+ Save changes
30
+ </Button>
31
+ </ThemeProvider>
32
+ );
33
+ }
34
+ ```
14
35
 
15
- ## Development
36
+ ## Components
37
+
38
+ | Component | Description |
39
+ |-----------|-------------|
40
+ | **Alert** | Inline message with neutral, brand, and danger intents, an intent-matched icon, and optional close button |
41
+ | **Avatar** | User representation as an image, initials, or icon |
42
+ | **Badge** | Compact pill for labels, counts, and status, with optional status dot |
43
+ | **Button** | Action button with three intents, three prominences, and icon support |
44
+ | **Card** | Content container with optional image, icon, and actions |
45
+ | **Checkbox** | Form control with checked, unchecked, and indeterminate states |
46
+ | **Chip** | Compact element for filters, selections, and tags |
47
+ | **Dialog** | Modal overlay for confirmations, alerts, and focused tasks |
48
+ | **Divider** | Horizontal or vertical separator line |
49
+ | **Icon** | Material Symbols Outlined icon, rendered via font ligatures |
50
+ | **Input** | Single-line text field with label, helper text, and error state |
51
+ | **List** | Item list with selection, icons, subheaders, and dividers |
52
+ | **Popover** | Anchored floating panel for contextual content |
53
+ | **Radio** | Single-choice control, with `RadioGroup` for managing a set |
54
+ | **Select** | Dropdown with single, multi (tag pills), and combobox (search) modes |
55
+ | **Skeleton** | Loading placeholder in text, circle, and rectangle shapes |
56
+ | **Toast** | Brief notification with icon and optional close button |
57
+ | **Toggle** | On/off switch with label |
58
+ | **Tooltip** | Short hint shown on hover or focus |
59
+
60
+ Components share a common prop vocabulary, mirrored from the Figma kit:
61
+
62
+ - `intent` — what it means: `neutral`, `brand`, or `danger`
63
+ - `prominence` — how visually heavy it is: `default` (outlined), `bold`
64
+ (filled), or `subtle` (ghost)
65
+ - `size` — `small`, `default`, or `large`
66
+
67
+ ## Customising
68
+
69
+ Wrap your app in `ThemeProvider`. It controls three independent settings:
70
+
71
+ **Density** — how tight or roomy spacing feels: `compact`, `default`, or
72
+ `comfortable`. Changing it scales padding and spacing across every component
73
+ at once. Colours and typography never change with density, so your brand
74
+ looks the same at any setting.
75
+
76
+ ```tsx
77
+ <ThemeProvider density="compact">
78
+ ```
16
79
 
17
- ### Prerequisites
80
+ **Colour mode** — `light` or `dark`. Switches every colour in the library:
81
+ buttons, surfaces, text, and form controls.
18
82
 
19
- - Node.js >= 18
20
- - npm
83
+ ```tsx
84
+ import { useColorScheme } from 'react-native';
21
85
 
22
- ### Install Dependencies
86
+ const scheme = useColorScheme();
87
+ <ThemeProvider colorMode={scheme === 'dark' ? 'dark' : 'light'}>
88
+ ```
23
89
 
24
- ```bash
25
- npm install
90
+ **Colour overrides** — pass a `colors` prop to use your own brand colours.
91
+ You only write the colours you want to change; everything else keeps its
92
+ default:
93
+
94
+ ```tsx
95
+ <ThemeProvider
96
+ colors={{
97
+ brand: {
98
+ bold: {
99
+ default: { bg: '#7C3AED', fg: '#FFFFFF', border: '#7C3AED' },
100
+ },
101
+ },
102
+ }}
103
+ >
26
104
  ```
27
105
 
28
- ### Start Storybook
106
+ ThemeProviders can be nested — for example, a compact data table inside a
107
+ comfortable app. Your own components can read the active theme with the
108
+ `useTheme` hook, and all the underlying values (colours, typography scales,
109
+ density spacing) are exported for direct use.
29
110
 
30
- ```bash
31
- npm run storybook
111
+ The full guide lives in Storybook under **Guides → Customisation**.
112
+
113
+ ## Theming from Figma — the cast-sync plugin
114
+
115
+ [`cast-sync/`](./cast-sync) is a Figma plugin that turns the Figma file's
116
+ colour variables into a theme file for this package. Run it inside the Cast
117
+ Design System file and it shows a preview, then downloads a
118
+ `cast-theme.json` you pass straight to `ThemeProvider`:
119
+
120
+ ```tsx
121
+ import theme from './cast-theme.json';
122
+
123
+ <ThemeProvider colorMode="light" colors={theme.colors.light}>
32
124
  ```
33
125
 
34
- Opens at `http://localhost:6006`.
126
+ The workflow: recolour the variables in Figma → run the plugin → swap in the
127
+ new file. No code changes. Setup instructions are in
128
+ [cast-sync/README.md](./cast-sync/README.md).
35
129
 
36
- ### Build
130
+ ## How the tokens work
37
131
 
38
- ```bash
39
- npm run build
132
+ Cast UI's values come from three layers of design tokens:
133
+
134
+ ```
135
+ Component tokens button.default.paddingX = 14 → changes with density
136
+ Semantic tokens intent/brand/bold/default/bg → changes with colour mode
137
+ Primitive tokens blue/600 = #2563EB → the raw palette
40
138
  ```
41
139
 
42
- ## Scripts
140
+ The raw token JSON exported from Figma lives in
141
+ [`design-tokens/`](./design-tokens). The library ships a lean TypeScript
142
+ version of the same values, so nothing is parsed at runtime.
143
+
144
+ ## Development
145
+
146
+ Requires Node.js >= 18.
147
+
148
+ ```bash
149
+ npm install
150
+ npm run storybook # component workshop at http://localhost:6006
151
+ npm run build # compile to dist/
152
+ ```
43
153
 
44
154
  | Script | Description |
45
155
  |--------|-------------|
@@ -53,7 +163,7 @@ npm run build
53
163
  |----------|---------|---------|
54
164
  | Chromatic | Every push | Visual regression testing via Storybook snapshots |
55
165
  | Adoption Tracking | Push to `main` | Registers package version with Zeroheight |
56
- | Publish to npm | Push to `main` | Builds and publishes package to npm (only if version changed) |
166
+ | Publish to npm | Push to `main` | Builds and publishes to npm (only when the version changes) |
57
167
 
58
168
  ## License
59
169
 
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Alert — inline message banner for notes, info, and errors.
3
+ *
4
+ * Maps to the Figma <Alert> component (node 307:3283):
5
+ * intent → neutral | brand | danger (drives colour)
6
+ * size → small | default | large (drives padding, gap, type scale)
7
+ * variant → subtle (no fill/border) | outline (white fill + intent border)
8
+ *
9
+ * Padding + gap come from the density theme's `alert` tokens (size × density).
10
+ * Icon/close sizes track the `size` prop. Colours reuse the intent system.
11
+ */
12
+ import React from 'react';
13
+ import { type ViewStyle, type StyleProp } from 'react-native';
14
+ import type { IntentName } from '../../tokens';
15
+ export type AlertSize = 'small' | 'default' | 'large';
16
+ export type AlertVariant = 'subtle' | 'outline';
17
+ export type AlertProps = {
18
+ /** Semantic intent — drives colour scheme. */
19
+ intent?: IntentName;
20
+ /** Size variant — controls padding, gap, and typography scale. */
21
+ size?: AlertSize;
22
+ /** Visual style — subtle (no fill) or outline (white fill + border). */
23
+ variant?: AlertVariant;
24
+ /** Bold title line. */
25
+ title?: string;
26
+ /** Supporting description text. */
27
+ description?: string;
28
+ /**
29
+ * Leading icon — Material Symbols name string or a ReactNode.
30
+ * Pass `null` to hide. Defaults to an intent-appropriate symbol.
31
+ */
32
+ icon?: string | React.ReactNode | null;
33
+ /** When provided, renders a close button that calls this handler. */
34
+ onClose?: () => void;
35
+ /** Style override for the outer container. */
36
+ style?: StyleProp<ViewStyle>;
37
+ /** Accessibility label — falls back to the title text. */
38
+ accessibilityLabel?: string;
39
+ };
40
+ export declare function Alert({ intent, size, variant, title: titleText, description, icon, onClose, style, accessibilityLabel, }: AlertProps): import("react/jsx-runtime").JSX.Element;
41
+ //# sourceMappingURL=Alert.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Alert.d.ts","sourceRoot":"","sources":["../../../src/components/Alert/Alert.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAIL,KAAK,SAAS,EACd,KAAK,SAAS,EACf,MAAM,cAAc,CAAC;AAUtB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE/C,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,OAAO,CAAC;AACtD,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,SAAS,CAAC;AAEhD,MAAM,MAAM,UAAU,GAAG;IACvB,8CAA8C;IAC9C,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,kEAAkE;IAClE,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,wEAAwE;IACxE,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,uBAAuB;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,mCAAmC;IACnC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC;IACvC,qEAAqE;IACrE,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,8CAA8C;IAC9C,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B,0DAA0D;IAC1D,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B,CAAC;AAuBF,wBAAgB,KAAK,CAAC,EACpB,MAAkB,EAClB,IAAgB,EAChB,OAAkB,EAClB,KAAK,EAAE,SAAS,EAChB,WAAW,EACX,IAAI,EACJ,OAAO,EACP,KAAK,EACL,kBAAkB,GACnB,EAAE,UAAU,2CAqGZ"}
@@ -0,0 +1,69 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Pressable, View, Text, } from 'react-native';
3
+ import { useTheme } from '../../theme';
4
+ import { Icon } from '../Icon';
5
+ import { fontFamily, fontWeight, title, body, controlTokens, } from '../../tokens';
6
+ /** Maps alert size → title typography scale */
7
+ const TITLE_SCALE = {
8
+ small: 'sm',
9
+ default: 'md',
10
+ large: 'lg',
11
+ };
12
+ /** Maps alert size → body (description) typography scale */
13
+ const BODY_SCALE = {
14
+ small: 'sm',
15
+ default: 'md',
16
+ large: 'lg',
17
+ };
18
+ /** Default leading icon per intent */
19
+ const DEFAULT_ICON = {
20
+ neutral: 'info',
21
+ brand: 'info',
22
+ danger: 'error',
23
+ };
24
+ export function Alert({ intent = 'neutral', size = 'default', variant = 'subtle', title: titleText, description, icon, onClose, style, accessibilityLabel, }) {
25
+ const { components, scheme } = useTheme();
26
+ const intentColors = scheme.intents;
27
+ const tokens = components.alert;
28
+ const sizeTokens = tokens[size];
29
+ const titleTokens = title[TITLE_SCALE[size]];
30
+ const bodyTokens = body[BODY_SCALE[size]];
31
+ // Colours derive from the intent system. Outline uses the white fill +
32
+ // intent border; subtle is transparent. Foreground is the intent fg.
33
+ const intentClr = intentColors[intent].default.default;
34
+ const bg = variant === 'outline' ? intentClr.bg : 'transparent';
35
+ const borderColor = variant === 'outline' ? intentClr.border : 'transparent';
36
+ const fg = intentClr.fg;
37
+ // Resolve leading icon — undefined uses the intent default, null hides it.
38
+ const iconNode = icon === null
39
+ ? null
40
+ : icon === undefined ? (_jsx(Icon, { name: DEFAULT_ICON[intent], size: sizeTokens.iconSize, color: fg })) : typeof icon === 'string' ? (_jsx(Icon, { name: icon, size: sizeTokens.iconSize, color: fg })) : (icon);
41
+ return (_jsxs(View, { accessibilityRole: "alert", accessibilityLabel: accessibilityLabel || titleText, style: [
42
+ {
43
+ flexDirection: 'row',
44
+ alignItems: 'flex-start',
45
+ gap: sizeTokens.gap,
46
+ padding: sizeTokens.padding,
47
+ borderRadius: tokens.borderRadius,
48
+ borderWidth: controlTokens.borderWidth,
49
+ borderColor,
50
+ backgroundColor: bg,
51
+ },
52
+ style,
53
+ ], children: [iconNode ? (_jsx(View, { accessibilityElementsHidden: true, importantForAccessibility: "no", style: { width: sizeTokens.iconSize, height: sizeTokens.iconSize }, children: iconNode })) : null, _jsxs(View, { style: { flex: 1 }, children: [titleText ? (_jsx(Text, { style: {
54
+ fontFamily: fontFamily.sans,
55
+ fontWeight: fontWeight.medium,
56
+ fontSize: titleTokens.fontSize,
57
+ lineHeight: titleTokens.lineHeight,
58
+ letterSpacing: titleTokens.letterSpacing,
59
+ color: fg,
60
+ }, selectable: false, children: titleText })) : null, description ? (_jsx(Text, { style: {
61
+ fontFamily: fontFamily.sans,
62
+ fontWeight: fontWeight.regular,
63
+ fontSize: bodyTokens.fontSize,
64
+ lineHeight: bodyTokens.lineHeight,
65
+ letterSpacing: bodyTokens.letterSpacing,
66
+ color: fg,
67
+ }, selectable: false, children: description })) : null] }), onClose ? (_jsx(Pressable, { onPress: onClose, hitSlop: 8, accessibilityRole: "button", accessibilityLabel: "Dismiss", style: { width: sizeTokens.closeSize, height: sizeTokens.closeSize }, children: _jsx(Icon, { name: "close", size: sizeTokens.closeSize, color: fg }) })) : null] }));
68
+ }
69
+ //# sourceMappingURL=Alert.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Alert.js","sourceRoot":"","sources":["../../../src/components/Alert/Alert.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export { Alert, type AlertProps, type AlertSize, type AlertVariant, } from './Alert';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/Alert/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,EACL,KAAK,UAAU,EACf,KAAK,SAAS,EACd,KAAK,YAAY,GAClB,MAAM,SAAS,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { Alert, } from './Alert';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/Alert/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,GAIN,MAAM,SAAS,CAAC"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Avatar — a circular representation of a user or entity.
3
+ *
4
+ * Maps to the Figma <Avatar> component (node 307:4153):
5
+ * size → small | default | large (drives diameter, glyph + initials scale)
6
+ * type → image | initials | icon (inferred from the props you pass)
7
+ *
8
+ * The frame diameter comes from the `avatar` density theme (size × density);
9
+ * the circle radius is constant (full pill). Initials use the label scale
10
+ * matched to the size; the icon glyph and initials colour are the neutral
11
+ * foreground. Image avatars fill the frame and have no background.
12
+ */
13
+ import React from 'react';
14
+ import { type ImageSourcePropType, type ViewStyle, type StyleProp } from 'react-native';
15
+ export type AvatarSize = 'small' | 'default' | 'large';
16
+ export type AvatarType = 'image' | 'initials' | 'icon';
17
+ export type AvatarProps = {
18
+ /** Size variant — controls diameter, initials, and glyph scale. */
19
+ size?: AvatarSize;
20
+ /** Image source — when set, renders an image avatar filling the frame. */
21
+ source?: ImageSourcePropType;
22
+ /** Initials to display (e.g. "AB"). Used when no `source` is provided. */
23
+ initials?: string;
24
+ /** Fallback icon — Material Symbols name string or a ReactNode. */
25
+ icon?: string | React.ReactNode;
26
+ /** Outer style — use for positioning (margin, flex, alignSelf). */
27
+ style?: StyleProp<ViewStyle>;
28
+ /** Accessibility label — falls back to initials, else "Avatar". */
29
+ accessibilityLabel?: string;
30
+ };
31
+ export declare function Avatar({ size, source, initials, icon, style, accessibilityLabel, }: AvatarProps): import("react/jsx-runtime").JSX.Element;
32
+ //# sourceMappingURL=Avatar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Avatar.d.ts","sourceRoot":"","sources":["../../../src/components/Avatar/Avatar.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAIL,KAAK,mBAAmB,EACxB,KAAK,SAAS,EACd,KAAK,SAAS,EACf,MAAM,cAAc,CAAC;AAStB,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,SAAS,GAAG,OAAO,CAAC;AACvD,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,UAAU,GAAG,MAAM,CAAC;AAEvD,MAAM,MAAM,WAAW,GAAG;IACxB,mEAAmE;IACnE,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,0EAA0E;IAC1E,MAAM,CAAC,EAAE,mBAAmB,CAAC;IAC7B,0EAA0E;IAC1E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mEAAmE;IACnE,IAAI,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC,SAAS,CAAC;IAChC,mEAAmE;IACnE,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B,mEAAmE;IACnE,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B,CAAC;AA0BF,wBAAgB,MAAM,CAAC,EACrB,IAAgB,EAChB,MAAM,EACN,QAAQ,EACR,IAAI,EACJ,KAAK,EACL,kBAAkB,GACnB,EAAE,WAAW,2CA4Db"}
@@ -0,0 +1,53 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { View, Text, Image, } from 'react-native';
3
+ import { useTheme } from '../../theme';
4
+ import { fontFamily, fontWeight, label } from '../../tokens';
5
+ import { Icon } from '../Icon';
6
+ // ---------------------------------------------------------------------------
7
+ // Constants
8
+ // ---------------------------------------------------------------------------
9
+ /** Maps avatar size → initials typography scale */
10
+ const LABEL_SCALE = {
11
+ small: 'sm',
12
+ default: 'md',
13
+ large: 'lg',
14
+ };
15
+ /** Default fallback glyph when no source/initials/icon is supplied. */
16
+ const FALLBACK_ICON = 'person';
17
+ // ---------------------------------------------------------------------------
18
+ // Component
19
+ // ---------------------------------------------------------------------------
20
+ function resolveType(props) {
21
+ if (props.source)
22
+ return 'image';
23
+ if (props.initials)
24
+ return 'initials';
25
+ return 'icon';
26
+ }
27
+ export function Avatar({ size = 'default', source, initials, icon, style, accessibilityLabel, }) {
28
+ const { components, scheme } = useTheme();
29
+ const avatarColors = scheme.avatar;
30
+ const tokens = components.avatar;
31
+ const sizeTokens = tokens[size];
32
+ const labelTokens = label[LABEL_SCALE[size]];
33
+ const type = resolveType({ source, initials, icon });
34
+ const frameStyle = {
35
+ width: sizeTokens.size,
36
+ height: sizeTokens.size,
37
+ borderRadius: tokens.borderRadius,
38
+ alignItems: 'center',
39
+ justifyContent: 'center',
40
+ overflow: 'hidden',
41
+ backgroundColor: type === 'image' ? undefined : avatarColors.bg,
42
+ };
43
+ return (_jsx(View, { accessibilityRole: "image", accessibilityLabel: accessibilityLabel || initials || 'Avatar', style: [frameStyle, style], children: type === 'image' ? (_jsx(Image, { source: source, resizeMode: "cover", style: { width: '100%', height: '100%' } })) : type === 'initials' ? (_jsx(Text, { selectable: false, style: {
44
+ fontFamily: fontFamily.sans,
45
+ fontWeight: fontWeight.medium,
46
+ fontSize: labelTokens.fontSize,
47
+ lineHeight: labelTokens.lineHeight,
48
+ letterSpacing: labelTokens.letterSpacing,
49
+ color: avatarColors.fg,
50
+ textAlign: 'center',
51
+ }, children: initials })) : (_jsx(View, { accessibilityElementsHidden: true, importantForAccessibility: "no", children: typeof icon === 'string' || icon == null ? (_jsx(Icon, { name: typeof icon === 'string' ? icon : FALLBACK_ICON, size: sizeTokens.iconSize, color: avatarColors.fg })) : (icon) })) }));
52
+ }
53
+ //# sourceMappingURL=Avatar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Avatar.js","sourceRoot":"","sources":["../../../src/components/Avatar/Avatar.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export { Avatar, type AvatarProps, type AvatarSize, type AvatarType } from './Avatar';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/Avatar/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,KAAK,WAAW,EAAE,KAAK,UAAU,EAAE,KAAK,UAAU,EAAE,MAAM,UAAU,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { Avatar } from './Avatar';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/Avatar/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAsD,MAAM,UAAU,CAAC"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Badge — a compact pill for labels, counts, and status indicators.
3
+ *
4
+ * Maps to the Figma <Badge> component (node 307:3354):
5
+ * intent → neutral | brand | danger (Figma "default" === neutral)
6
+ * variant → solid | subtle | outline (Figma surface treatment)
7
+ * size → small | default | large (Figma "neutral" === default)
8
+ *
9
+ * Spacing/sizing comes from the `badge` theme tokens (keyed by size; constant
10
+ * across density). Colours map directly onto the semantic intent system:
11
+ * solid → intent bold (filled, white text)
12
+ * subtle → intent subtle (transparent fill, coloured text)
13
+ * outline → intent bold border + intent default text (transparent fill)
14
+ * Typography uses the label scale (sm/md/lg) matched to the badge size.
15
+ */
16
+ import React from 'react';
17
+ import { type ViewStyle, type StyleProp } from 'react-native';
18
+ import type { IntentName } from '../../tokens';
19
+ export type BadgeSize = 'small' | 'default' | 'large';
20
+ export type BadgeVariant = 'solid' | 'subtle' | 'outline';
21
+ export type BadgeProps = {
22
+ /** The badge label text. */
23
+ children: string;
24
+ /** Semantic intent — drives the colour scheme. */
25
+ intent?: IntentName;
26
+ /** Surface treatment — solid (filled), subtle (tinted), or outline (bordered). */
27
+ variant?: BadgeVariant;
28
+ /** Size variant — controls padding, gap, and typography scale. */
29
+ size?: BadgeSize;
30
+ /** Shows a leading status dot in the foreground colour. */
31
+ dot?: boolean;
32
+ /** Icon before the label — Material Symbols name string or a ReactNode. */
33
+ leadingIcon?: string | React.ReactNode;
34
+ /** Icon after the label — Material Symbols name string or a ReactNode. */
35
+ trailingIcon?: string | React.ReactNode;
36
+ /** Outer style — use for positioning (margin, flex, alignSelf). */
37
+ style?: StyleProp<ViewStyle>;
38
+ /** Accessibility label — falls back to children text if not provided. */
39
+ accessibilityLabel?: string;
40
+ };
41
+ export declare function Badge({ children, intent, variant, size, dot, leadingIcon, trailingIcon, style, accessibilityLabel, }: BadgeProps): import("react/jsx-runtime").JSX.Element;
42
+ //# sourceMappingURL=Badge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Badge.d.ts","sourceRoot":"","sources":["../../../src/components/Badge/Badge.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAGL,KAAK,SAAS,EACd,KAAK,SAAS,EACf,MAAM,cAAc,CAAC;AAItB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAO/C,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,OAAO,CAAC;AACtD,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,QAAQ,GAAG,SAAS,CAAC;AAE1D,MAAM,MAAM,UAAU,GAAG;IACvB,4BAA4B;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,kDAAkD;IAClD,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,kFAAkF;IAClF,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,kEAAkE;IAClE,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,2DAA2D;IAC3D,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,2EAA2E;IAC3E,WAAW,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC,SAAS,CAAC;IACvC,0EAA0E;IAC1E,YAAY,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC,SAAS,CAAC;IACxC,mEAAmE;IACnE,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B,yEAAyE;IACzE,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B,CAAC;AA2CF,wBAAgB,KAAK,CAAC,EACpB,QAAQ,EACR,MAAkB,EAClB,OAAiB,EACjB,IAAgB,EAChB,GAAW,EACX,WAAW,EACX,YAAY,EACZ,KAAK,EACL,kBAAkB,GACnB,EAAE,UAAU,2CAyFZ"}
@@ -0,0 +1,69 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { View, Text, } from 'react-native';
3
+ import { useTheme } from '../../theme';
4
+ import { fontFamily, fontWeight, label, controlTokens } from '../../tokens';
5
+ import { Icon } from '../Icon';
6
+ // ---------------------------------------------------------------------------
7
+ // Constants
8
+ // ---------------------------------------------------------------------------
9
+ /** Maps badge size → label typography scale */
10
+ const LABEL_SCALE = {
11
+ small: 'sm',
12
+ default: 'md',
13
+ large: 'lg',
14
+ };
15
+ /** Icon size — fixed at 16px, matched to the label baseline. */
16
+ const ICON_SIZE = 16;
17
+ function resolveColors(intent, variant, intentColors) {
18
+ const clrs = intentColors[intent];
19
+ switch (variant) {
20
+ case 'subtle':
21
+ return clrs.subtle.default;
22
+ case 'outline':
23
+ return {
24
+ bg: 'transparent',
25
+ fg: clrs.default.default.fg,
26
+ border: clrs.bold.default.border,
27
+ };
28
+ case 'solid':
29
+ default:
30
+ return clrs.bold.default;
31
+ }
32
+ }
33
+ export function Badge({ children, intent = 'neutral', variant = 'solid', size = 'default', dot = false, leadingIcon, trailingIcon, style, accessibilityLabel, }) {
34
+ const { components, scheme } = useTheme();
35
+ const sizeTokens = components.badge[size];
36
+ const labelTokens = label[LABEL_SCALE[size]];
37
+ const colors = resolveColors(intent, variant, scheme.intents);
38
+ const resolvedLeading = typeof leadingIcon === 'string' ? (_jsx(Icon, { name: leadingIcon, size: ICON_SIZE, color: colors.fg })) : (leadingIcon);
39
+ const resolvedTrailing = typeof trailingIcon === 'string' ? (_jsx(Icon, { name: trailingIcon, size: ICON_SIZE, color: colors.fg })) : (trailingIcon);
40
+ return (_jsxs(View, { accessibilityRole: "text", accessibilityLabel: accessibilityLabel || children, style: [
41
+ {
42
+ flexDirection: 'row',
43
+ alignItems: 'center',
44
+ justifyContent: 'center',
45
+ alignSelf: 'flex-start',
46
+ gap: sizeTokens.gap,
47
+ paddingHorizontal: sizeTokens.paddingX,
48
+ paddingVertical: sizeTokens.paddingY,
49
+ borderRadius: components.badge.borderRadius,
50
+ borderWidth: controlTokens.borderWidth,
51
+ borderColor: colors.border,
52
+ backgroundColor: colors.bg,
53
+ },
54
+ style,
55
+ ], children: [dot ? (_jsx(View, { accessibilityElementsHidden: true, importantForAccessibility: "no", style: {
56
+ width: sizeTokens.dotSize,
57
+ height: sizeTokens.dotSize,
58
+ borderRadius: sizeTokens.dotSize / 2,
59
+ backgroundColor: colors.fg,
60
+ } })) : null, resolvedLeading ? (_jsx(View, { accessibilityElementsHidden: true, importantForAccessibility: "no", style: { width: ICON_SIZE, height: ICON_SIZE }, children: resolvedLeading })) : null, _jsx(Text, { style: {
61
+ fontFamily: fontFamily.sans,
62
+ fontWeight: fontWeight.medium,
63
+ fontSize: labelTokens.fontSize,
64
+ lineHeight: labelTokens.lineHeight,
65
+ letterSpacing: labelTokens.letterSpacing,
66
+ color: colors.fg,
67
+ }, selectable: false, children: children }), resolvedTrailing ? (_jsx(View, { accessibilityElementsHidden: true, importantForAccessibility: "no", style: { width: ICON_SIZE, height: ICON_SIZE }, children: resolvedTrailing })) : null] }));
68
+ }
69
+ //# sourceMappingURL=Badge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Badge.js","sourceRoot":"","sources":["../../../src/components/Badge/Badge.tsx"],"names":[],"mappings":";AAiBA,OAAO,EACL,IAAI,EACJ,IAAI,GAGL,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAG5E,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AA8B/B,8EAA8E;AAC9E,YAAY;AACZ,8EAA8E;AAE9E,+CAA+C;AAC/C,MAAM,WAAW,GAA0C;IACzD,KAAK,EAAE,IAAI;IACX,OAAO,EAAE,IAAI;IACb,KAAK,EAAE,IAAI;CACZ,CAAC;AAEF,gEAAgE;AAChE,MAAM,SAAS,GAAG,EAAE,CAAC;AAQrB,SAAS,aAAa,CACpB,MAAkB,EAClB,OAAqB,EACrB,YAAoC;IAEpC,MAAM,IAAI,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;IAClC,QAAQ,OAAO,EAAE,CAAC;QAChB,KAAK,QAAQ;YACX,OAAO,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC;QAC7B,KAAK,SAAS;YACZ,OAAO;gBACL,EAAE,EAAE,aAAa;gBACjB,EAAE,EAAE,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE;gBAC3B,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM;aACjC,CAAC;QACJ,KAAK,OAAO,CAAC;QACb;YACE,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC;IAC7B,CAAC;AACH,CAAC;AAED,MAAM,UAAU,KAAK,CAAC,EACpB,QAAQ,EACR,MAAM,GAAG,SAAS,EAClB,OAAO,GAAG,OAAO,EACjB,IAAI,GAAG,SAAS,EAChB,GAAG,GAAG,KAAK,EACX,WAAW,EACX,YAAY,EACZ,KAAK,EACL,kBAAkB,GACP;IACX,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,QAAQ,EAAE,CAAC;IAE1C,MAAM,UAAU,GAAG,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC1C,MAAM,WAAW,GAAG,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC;IAC7C,MAAM,MAAM,GAAG,aAAa,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;IAE9D,MAAM,eAAe,GACnB,OAAO,WAAW,KAAK,QAAQ,CAAC,CAAC,CAAC,CAChC,KAAC,IAAI,IAAC,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,CAAC,EAAE,GAAI,CAC/D,CAAC,CAAC,CAAC,CACF,WAAW,CACZ,CAAC;IACJ,MAAM,gBAAgB,GACpB,OAAO,YAAY,KAAK,QAAQ,CAAC,CAAC,CAAC,CACjC,KAAC,IAAI,IAAC,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,CAAC,EAAE,GAAI,CAChE,CAAC,CAAC,CAAC,CACF,YAAY,CACb,CAAC;IAEJ,OAAO,CACL,MAAC,IAAI,IACH,iBAAiB,EAAC,MAAM,EACxB,kBAAkB,EAAE,kBAAkB,IAAI,QAAQ,EAClD,KAAK,EAAE;YACL;gBACE,aAAa,EAAE,KAAK;gBACpB,UAAU,EAAE,QAAQ;gBACpB,cAAc,EAAE,QAAQ;gBACxB,SAAS,EAAE,YAAY;gBACvB,GAAG,EAAE,UAAU,CAAC,GAAG;gBACnB,iBAAiB,EAAE,UAAU,CAAC,QAAQ;gBACtC,eAAe,EAAE,UAAU,CAAC,QAAQ;gBACpC,YAAY,EAAE,UAAU,CAAC,KAAK,CAAC,YAAY;gBAC3C,WAAW,EAAE,aAAa,CAAC,WAAW;gBACtC,WAAW,EAAE,MAAM,CAAC,MAAM;gBAC1B,eAAe,EAAE,MAAM,CAAC,EAAE;aAC3B;YACD,KAAK;SACN,aAEA,GAAG,CAAC,CAAC,CAAC,CACL,KAAC,IAAI,IACH,2BAA2B,QAC3B,yBAAyB,EAAC,IAAI,EAC9B,KAAK,EAAE;oBACL,KAAK,EAAE,UAAU,CAAC,OAAO;oBACzB,MAAM,EAAE,UAAU,CAAC,OAAO;oBAC1B,YAAY,EAAE,UAAU,CAAC,OAAO,GAAG,CAAC;oBACpC,eAAe,EAAE,MAAM,CAAC,EAAE;iBAC3B,GACD,CACH,CAAC,CAAC,CAAC,IAAI,EAEP,eAAe,CAAC,CAAC,CAAC,CACjB,KAAC,IAAI,IACH,2BAA2B,QAC3B,yBAAyB,EAAC,IAAI,EAC9B,KAAK,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,YAE7C,eAAe,GACX,CACR,CAAC,CAAC,CAAC,IAAI,EAER,KAAC,IAAI,IACH,KAAK,EAAE;oBACL,UAAU,EAAE,UAAU,CAAC,IAAI;oBAC3B,UAAU,EAAE,UAAU,CAAC,MAAM;oBAC7B,QAAQ,EAAE,WAAW,CAAC,QAAQ;oBAC9B,UAAU,EAAE,WAAW,CAAC,UAAU;oBAClC,aAAa,EAAE,WAAW,CAAC,aAAa;oBACxC,KAAK,EAAE,MAAM,CAAC,EAAE;iBACjB,EACD,UAAU,EAAE,KAAK,YAEhB,QAAQ,GACJ,EAEN,gBAAgB,CAAC,CAAC,CAAC,CAClB,KAAC,IAAI,IACH,2BAA2B,QAC3B,yBAAyB,EAAC,IAAI,EAC9B,KAAK,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,YAE7C,gBAAgB,GACZ,CACR,CAAC,CAAC,CAAC,IAAI,IACH,CACR,CAAC;AACJ,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { Badge, type BadgeProps, type BadgeSize, type BadgeVariant } from './Badge';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/Badge/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,KAAK,UAAU,EAAE,KAAK,SAAS,EAAE,KAAK,YAAY,EAAE,MAAM,SAAS,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { Badge } from './Badge';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/Badge/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAsD,MAAM,SAAS,CAAC"}
@@ -0,0 +1,42 @@
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;
42
+ //# sourceMappingURL=Card.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Card.d.ts","sourceRoot":"","sources":["../../../src/components/Card/Card.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAIL,KAAK,SAAS,EACd,KAAK,SAAS,EACf,MAAM,cAAc,CAAC;AAUtB,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,SAAS,GAAG,OAAO,CAAC;AACrD,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,UAAU,CAAC;AAEjD,MAAM,MAAM,SAAS,GAAG;IACtB,kEAAkE;IAClE,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,qEAAqE;IACrE,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,wDAAwD;IACxD,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACxB,yEAAyE;IACzE,IAAI,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC,SAAS,CAAC;IAChC,kBAAkB;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2CAA2C;IAC3C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,6BAA6B;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,sEAAsE;IACtE,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,oEAAoE;IACpE,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,8CAA8C;IAC9C,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B,wCAAwC;IACxC,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B,CAAC;AA6BF,wBAAgB,IAAI,CAAC,EACnB,IAAgB,EAChB,OAAmB,EACnB,KAAK,EACL,IAAI,EACJ,KAAK,EAAE,SAAS,EAChB,QAAQ,EACR,IAAI,EAAE,QAAQ,EACd,OAAO,EACP,QAAQ,EACR,KAAK,EACL,kBAAkB,GACnB,EAAE,SAAS,2CAwIX"}