@cdx-ui/components 0.3.7 → 0.3.9

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 (66) hide show
  1. package/docs/components/content.md +2 -1
  2. package/docs/components/country-flag/content.md +3 -3
  3. package/docs/components/currency-flag/content.md +202 -0
  4. package/docs/components/currency-input/content.md +175 -56
  5. package/docs/components/data-grid/content.md +47 -0
  6. package/docs/components/date-range-picker/content.md +62 -1
  7. package/docs/foundations/expressions/icons/content.md +1 -1
  8. package/docs/getting-started/developers/styling/content.md +2 -2
  9. package/docs/llms.txt +6 -3
  10. package/docs/resources/release-notes/0.2.5/content.md +6 -8
  11. package/docs/resources/release-notes/0.3.0/content.md +2 -2
  12. package/docs/resources/release-notes/0.3.1/content.md +3 -3
  13. package/docs/resources/release-notes/0.3.2/content.md +1 -1
  14. package/docs/resources/release-notes/0.3.3/content.md +6 -6
  15. package/docs/resources/release-notes/0.3.4/content.md +5 -5
  16. package/docs/resources/release-notes/0.3.6/content.md +3 -3
  17. package/docs/resources/release-notes/0.3.7/content.md +23 -0
  18. package/docs/resources/release-notes/0.3.8/content.md +21 -0
  19. package/docs/resources/release-notes/content.md +4 -2
  20. package/lib/commonjs/components/CountryFlag/index.js +2 -2
  21. package/lib/commonjs/components/CountryFlag/index.js.map +1 -1
  22. package/lib/commonjs/components/CurrencyFlag/index.js +77 -0
  23. package/lib/commonjs/components/CurrencyFlag/index.js.map +1 -0
  24. package/lib/commonjs/components/CurrencyInput/index.js +3 -1
  25. package/lib/commonjs/components/CurrencyInput/index.js.map +1 -1
  26. package/lib/commonjs/components/CurrencyInput/styles.js +23 -7
  27. package/lib/commonjs/components/CurrencyInput/styles.js.map +1 -1
  28. package/lib/commonjs/components/DateRangePicker/index.js +3 -1
  29. package/lib/commonjs/components/DateRangePicker/index.js.map +1 -1
  30. package/lib/commonjs/components/index.js +12 -0
  31. package/lib/commonjs/components/index.js.map +1 -1
  32. package/lib/commonjs/components/picker/surfaces.js.map +1 -1
  33. package/lib/module/components/CountryFlag/index.js +2 -2
  34. package/lib/module/components/CountryFlag/index.js.map +1 -1
  35. package/lib/module/components/CurrencyFlag/index.js +72 -0
  36. package/lib/module/components/CurrencyFlag/index.js.map +1 -0
  37. package/lib/module/components/CurrencyInput/index.js +3 -1
  38. package/lib/module/components/CurrencyInput/index.js.map +1 -1
  39. package/lib/module/components/CurrencyInput/styles.js +23 -7
  40. package/lib/module/components/CurrencyInput/styles.js.map +1 -1
  41. package/lib/module/components/DateRangePicker/index.js +3 -1
  42. package/lib/module/components/DateRangePicker/index.js.map +1 -1
  43. package/lib/module/components/index.js +1 -0
  44. package/lib/module/components/index.js.map +1 -1
  45. package/lib/module/components/picker/surfaces.js.map +1 -1
  46. package/lib/typescript/components/CountryFlag/index.d.ts +8 -3
  47. package/lib/typescript/components/CountryFlag/index.d.ts.map +1 -1
  48. package/lib/typescript/components/CurrencyFlag/index.d.ts +47 -0
  49. package/lib/typescript/components/CurrencyFlag/index.d.ts.map +1 -0
  50. package/lib/typescript/components/CurrencyInput/index.d.ts.map +1 -1
  51. package/lib/typescript/components/CurrencyInput/styles.d.ts +6 -1
  52. package/lib/typescript/components/CurrencyInput/styles.d.ts.map +1 -1
  53. package/lib/typescript/components/DateRangePicker/index.d.ts +26 -2
  54. package/lib/typescript/components/DateRangePicker/index.d.ts.map +1 -1
  55. package/lib/typescript/components/index.d.ts +1 -0
  56. package/lib/typescript/components/index.d.ts.map +1 -1
  57. package/lib/typescript/components/picker/surfaces.d.ts +1 -1
  58. package/lib/typescript/components/picker/surfaces.d.ts.map +1 -1
  59. package/package.json +5 -5
  60. package/src/components/CountryFlag/index.tsx +8 -3
  61. package/src/components/CurrencyFlag/index.tsx +71 -0
  62. package/src/components/CurrencyInput/index.tsx +2 -1
  63. package/src/components/CurrencyInput/styles.ts +29 -3
  64. package/src/components/DateRangePicker/index.tsx +29 -1
  65. package/src/components/index.ts +1 -0
  66. package/src/components/picker/surfaces.tsx +6 -1
@@ -61,7 +61,8 @@
61
61
  - [Divider](https://design.candescent.com/docs/components/divider/content.md) — A horizontal or vertical separator for grouping related content, with an optional inline label.
62
62
  - [Insurance Disclosure](https://design.candescent.com/docs/components/insurance-disclosure/content.md) — Domain-specific regulatory disclosure — official FDIC lockup with optional copy for account footers, deposit screens, and onboarding.
63
63
  - [Icon](https://design.candescent.com/docs/components/icon/content.md) — A cross-platform SVG icon wrapper with semantic color, sizing, filled variants, and accessibility support.
64
- - [Country Flag](https://design.candescent.com/docs/components/country-flag/content.md) — A country flag rendered from an officially assigned ISO 3166-1 alpha-2 code.
64
+ - [Country Flag](https://design.candescent.com/docs/components/country-flag/content.md) — A flag for a country-flag-icons code, including unofficial codes used by libphonenumber-js.
65
+ - [Currency Flag](https://design.candescent.com/docs/components/currency-flag/content.md) — The flag of the country or union that issues an ISO 4217 currency.
65
66
  - [Image](https://design.candescent.com/docs/components/image/content.md) — Displays local or remote images across native and web platforms.
66
67
  - [List Item](https://design.candescent.com/docs/components/list-item/content.md) — A composable row for display and navigation — accounts, transactions, alerts, settings, and nav rows.
67
68
  - [Reorderable List](https://design.candescent.com/docs/components/reorderable-list/content.md) — A short, mount-all list that lets members drag rows into a new order via an explicit handle.
@@ -2,7 +2,7 @@
2
2
 
3
3
  Resources: [Storybook](https://victorious-wave-0daadf00f.6.azurestaticapps.net/?path=/story/content-countryflag--default)
4
4
 
5
- `CountryFlag` renders a country's flag from an officially assigned ISO 3166-1 alpha-2 `code`.
5
+ `CountryFlag` renders a flag from a `FlagCode`. The codes match the `country-flag-icons` 3x2 set this package was built with: officially assigned ISO 3166-1 alpha-2 codes, the unofficial codes that package ships for `libphonenumber-js`, and its subdivision codes.
6
6
 
7
7
  ```tsx
8
8
  import { CountryFlag, Select } from '@cdx-ui/components';
@@ -208,9 +208,9 @@ Renders the flag for `code`. An unknown `code` renders nothing and logs a warnin
208
208
  | `children?` | `React.ReactNode` | — | — |
209
209
  | `size?` | `string \| number` | — | Width and height of the icon, in pixels or any SVG length. The bare icon renders at 24 when omitted. |
210
210
  | `data-testid?` | `string` | — | Test identifier forwarded to the rendered SVG. |
211
- | `code` | `'AD' \| 'AE' \| 'AF' \| 'AG' \| 'AI' \| 'AL' \| 'AM' \| 'AO' \| 'AQ' \| 'AR' \| 'AS' \| 'AT' \| 'AU' \| 'AW' \| 'AX' \| 'AZ' \| 'BA' \| 'BB' \| 'BD' \| 'BE' \| 'BF' \| 'BG' \| 'BH' \| 'BI' \| 'BJ' \| 'BL' \| 'BM' \| 'BN' \| 'BO' \| 'BQ' \| 'BR' \| 'BS' \| 'BT' \| 'BV' \| 'BW' \| 'BY' \| 'BZ' \| 'CA' \| 'CC' \| 'CD' \| 'CF' \| 'CG' \| 'CH' \| 'CI' \| 'CK' \| 'CL' \| 'CM' \| 'CN' \| 'CO' \| 'CR' \| 'CU' \| 'CV' \| 'CW' \| 'CX' \| 'CY' \| 'CZ' \| 'DE' \| 'DJ' \| 'DK' \| 'DM' \| 'DO' \| 'DZ' \| 'EC' \| 'EE' \| 'EG' \| 'EH' \| 'ER' \| 'ES' \| 'ET' \| 'FI' \| 'FJ' \| 'FK' \| 'FM' \| 'FO' \| 'FR' \| 'GA' \| 'GB' \| 'GD' \| 'GE' \| 'GF' \| 'GG' \| 'GH' \| 'GI' \| 'GL' \| 'GM' \| 'GN' \| 'GP' \| 'GQ' \| 'GR' \| 'GS' \| 'GT' \| 'GU' \| 'GW' \| 'GY' \| 'HK' \| 'HM' \| 'HN' \| 'HR' \| 'HT' \| 'HU' \| 'ID' \| 'IE' \| 'IL' \| 'IM' \| 'IN' \| 'IO' \| 'IQ' \| 'IR' \| 'IS' \| 'IT' \| 'JE' \| 'JM' \| 'JO' \| 'JP' \| 'KE' \| 'KG' \| 'KH' \| 'KI' \| 'KM' \| 'KN' \| 'KP' \| 'KR' \| 'KW' \| 'KY' \| 'KZ' \| 'LA' \| 'LB' \| 'LC' \| 'LI' \| 'LK' \| 'LR' \| 'LS' \| 'LT' \| 'LU' \| 'LV' \| 'LY' \| 'MA' \| 'MC' \| 'MD' \| 'ME' \| 'MF' \| 'MG' \| 'MH' \| 'MK' \| 'ML' \| 'MM' \| 'MN' \| 'MO' \| 'MP' \| 'MQ' \| 'MR' \| 'MS' \| 'MT' \| 'MU' \| 'MV' \| 'MW' \| 'MX' \| 'MY' \| 'MZ' \| 'NA' \| 'NC' \| 'NE' \| 'NF' \| 'NG' \| 'NI' \| 'NL' \| 'NO' \| 'NP' \| 'NR' \| 'NU' \| 'NZ' \| 'OM' \| 'PA' \| 'PE' \| 'PF' \| 'PG' \| 'PH' \| 'PK' \| 'PL' \| 'PM' \| 'PN' \| 'PR' \| 'PS' \| 'PT' \| 'PW' \| 'PY' \| 'QA' \| 'RE' \| 'RO' \| 'RS' \| 'RU' \| 'RW' \| 'SA' \| 'SB' \| 'SC' \| 'SD' \| 'SE' \| 'SG' \| 'SH' \| 'SI' \| 'SJ' \| 'SK' \| 'SL' \| 'SM' \| 'SN' \| 'SO' \| 'SR' \| 'SS' \| 'ST' \| 'SV' \| 'SX' \| 'SY' \| 'SZ' \| 'TC' \| 'TD' \| 'TF' \| 'TG' \| 'TH' \| 'TJ' \| 'TK' \| 'TL' \| 'TM' \| 'TN' \| 'TO' \| 'TR' \| 'TT' \| 'TV' \| 'TW' \| 'TZ' \| 'UA' \| 'UG' \| 'UM' \| 'US' \| 'UY' \| 'UZ' \| 'VA' \| 'VC' \| 'VE' \| 'VG' \| 'VI' \| 'VN' \| 'VU' \| 'WF' \| 'WS' \| 'YE' \| 'YT' \| 'ZA' \| 'ZM' \| 'ZW'` | — | ISO 3166-1 alpha-2 country code. |
211
+ | `code` | `'AC' \| 'AD' \| 'AE' \| 'AF' \| 'AG' \| 'AI' \| 'AL' \| 'AM' \| 'AO' \| 'AQ' \| 'AR' \| 'AS' \| 'AT' \| 'AU' \| 'AW' \| 'AX' \| 'AZ' \| 'BA' \| 'BB' \| 'BD' \| 'BE' \| 'BF' \| 'BG' \| 'BH' \| 'BI' \| 'BJ' \| 'BL' \| 'BM' \| 'BN' \| 'BO' \| 'BQ' \| 'BQ-BO' \| 'BQ-SA' \| 'BQ-SE' \| 'BR' \| 'BS' \| 'BT' \| 'BV' \| 'BW' \| 'BY' \| 'BZ' \| 'CA' \| 'CC' \| 'CD' \| 'CF' \| 'CG' \| 'CH' \| 'CI' \| 'CK' \| 'CL' \| 'CM' \| 'CN' \| 'CO' \| 'CR' \| 'CU' \| 'CV' \| 'CW' \| 'CX' \| 'CY' \| 'CZ' \| 'DE' \| 'DJ' \| 'DK' \| 'DM' \| 'DO' \| 'DZ' \| 'EC' \| 'EE' \| 'EG' \| 'EH' \| 'ER' \| 'ES' \| 'ES-CT' \| 'ET' \| 'EU' \| 'FI' \| 'FJ' \| 'FK' \| 'FM' \| 'FO' \| 'FR' \| 'GA' \| 'GB' \| 'GB-ENG' \| 'GB-NIR' \| 'GB-SCT' \| 'GB-WLS' \| 'GD' \| 'GE' \| 'GF' \| 'GG' \| 'GH' \| 'GI' \| 'GL' \| 'GM' \| 'GN' \| 'GP' \| 'GQ' \| 'GR' \| 'GS' \| 'GT' \| 'GU' \| 'GW' \| 'GY' \| 'HK' \| 'HM' \| 'HN' \| 'HR' \| 'HT' \| 'HU' \| 'IC' \| 'ID' \| 'IE' \| 'IL' \| 'IM' \| 'IN' \| 'IO' \| 'IQ' \| 'IR' \| 'IS' \| 'IT' \| 'JE' \| 'JM' \| 'JO' \| 'JP' \| 'KE' \| 'KG' \| 'KH' \| 'KI' \| 'KM' \| 'KN' \| 'KP' \| 'KR' \| 'KW' \| 'KY' \| 'KZ' \| 'LA' \| 'LB' \| 'LC' \| 'LI' \| 'LK' \| 'LR' \| 'LS' \| 'LT' \| 'LU' \| 'LV' \| 'LY' \| 'MA' \| 'MC' \| 'MD' \| 'ME' \| 'MF' \| 'MG' \| 'MH' \| 'MK' \| 'ML' \| 'MM' \| 'MN' \| 'MO' \| 'MP' \| 'MQ' \| 'MR' \| 'MS' \| 'MT' \| 'MU' \| 'MV' \| 'MW' \| 'MX' \| 'MY' \| 'MZ' \| 'NA' \| 'NC' \| 'NE' \| 'NF' \| 'NG' \| 'NI' \| 'NL' \| 'NO' \| 'NP' \| 'NR' \| 'NU' \| 'NZ' \| 'OM' \| 'PA' \| 'PE' \| 'PF' \| 'PG' \| 'PH' \| 'PK' \| 'PL' \| 'PM' \| 'PN' \| 'PR' \| 'PS' \| 'PT' \| 'PW' \| 'PY' \| 'QA' \| 'RE' \| 'RO' \| 'RS' \| 'RU' \| 'RW' \| 'SA' \| 'SB' \| 'SC' \| 'SD' \| 'SE' \| 'SG' \| 'SH' \| 'SI' \| 'SJ' \| 'SK' \| 'SL' \| 'SM' \| 'SN' \| 'SO' \| 'SR' \| 'SS' \| 'ST' \| 'SV' \| 'SX' \| 'SY' \| 'SZ' \| 'TA' \| 'TC' \| 'TD' \| 'TF' \| 'TG' \| 'TH' \| 'TJ' \| 'TK' \| 'TL' \| 'TM' \| 'TN' \| 'TO' \| 'TR' \| 'TT' \| 'TV' \| 'TW' \| 'TZ' \| 'UA' \| 'UG' \| 'UM' \| 'US' \| 'UY' \| 'UZ' \| 'VA' \| 'VC' \| 'VE' \| 'VG' \| 'VI' \| 'VN' \| 'VU' \| 'WF' \| 'WS' \| 'XA' \| 'XC' \| 'XK' \| 'XO' \| 'YE' \| 'YT' \| 'ZA' \| 'ZM' \| 'ZW'` | — | Code from the country-flag-icons 3x2 set. Includes officially assigned ISO 3166-1 alpha-2 codes, the unofficial codes that package ships for libphonenumber-js, and its subdivision codes. Subdivision codes keep their hyphen (`GB-ENG`). |
212
212
 
213
- Inherits [`SvgProps`](https://github.com/software-mansion/react-native-svg#common-props) except `color`, including `style` and `accessibilityLabel`. `as`, `filled`, and `color` are not accepted. `code` is the officially assigned ISO 3166-1 alpha-2 set, exported as `FlagCode` from `@cdx-ui/components` and `@cdx-ui/icons/flags`.
213
+ Inherits [`SvgProps`](https://github.com/software-mansion/react-native-svg#common-props) except `color`, including `style` and `accessibilityLabel`. `as`, `filled`, and `color` are not accepted. `code` is `FlagCode`, exported from `@cdx-ui/components` and `@cdx-ui/icons/flags`. Subdivision codes keep the hyphen (`GB-ENG`). The icon component replaces it with an underscore (`FlagGB_ENG`).
214
214
 
215
215
  ## Defaults and styling
216
216
 
@@ -0,0 +1,202 @@
1
+ # Currency Flag (https://design.candescent.com/docs/components/currency-flag)
2
+
3
+ Resources: [Storybook](https://victorious-wave-0daadf00f.6.azurestaticapps.net/?path=/story/content-currencyflag--default)
4
+
5
+ `CurrencyFlag` renders the flag of the country or union that issues an ISO 4217 currency `code`. `EUR` renders the European Union flag.
6
+
7
+ ```tsx
8
+ import { CurrencyFlag, CountryFlag, Select } from '@cdx-ui/components';
9
+ ```
10
+
11
+ Flags keep their source colors. Each path has an explicit fill, so text color classes and theme tokens do not recolor the artwork.
12
+
13
+ ## Basic
14
+
15
+ Pass a currency `code`. The default box is `size-5`, and a `size-*` class overrides it.
16
+
17
+ ```tsx
18
+ import { Box, CurrencyFlag, Text } from '@cdx-ui/components';
19
+
20
+ const examples = [
21
+ { code: 'USD', name: 'US Dollar' },
22
+ { code: 'EUR', name: 'Euro' },
23
+ { code: 'GBP', name: 'British Pound' },
24
+ { code: 'JPY', name: 'Japanese Yen' },
25
+ ];
26
+
27
+ export default function CurrencyFlagBasicDemo() {
28
+ return (
29
+ <Box className="flex-row items-end gap-5">
30
+ {examples.map((currency) => (
31
+ <Box key={currency.code} className="items-center gap-2">
32
+ <CurrencyFlag code={currency.code} accessibilityLabel={currency.name} />
33
+ <Text size="sm" color="secondary">
34
+ {currency.code}
35
+ </Text>
36
+ </Box>
37
+ ))}
38
+ </Box>
39
+ );
40
+ }
41
+ ```
42
+
43
+ ## Shared currencies
44
+
45
+ The flag shows the currency's issuer, not where the user is. `DKK` renders Denmark's flag for accounts in Greenland and the Faroe Islands, and `USD` renders the United States flag in Ecuador. When the flag should show the user's country, pass the account's country code to [`CountryFlag`](https://design.candescent.com/docs/components/country-flag/content.md) instead.
46
+
47
+ ```tsx
48
+ import { Box, CountryFlag, CurrencyFlag, Text } from '@cdx-ui/components';
49
+
50
+ export default function CurrencyFlagSharedCurrenciesDemo() {
51
+ return (
52
+ <Box className="gap-5">
53
+ <Box className="flex-row items-center gap-3">
54
+ <CurrencyFlag code="DKK" />
55
+ <Text>DKK in Greenland shows the issuer, Denmark</Text>
56
+ </Box>
57
+ <Box className="flex-row items-center gap-3">
58
+ <CountryFlag code="GL" />
59
+ <Text>Greenland, from the account country code</Text>
60
+ </Box>
61
+ </Box>
62
+ );
63
+ }
64
+ ```
65
+
66
+ ## With icons
67
+
68
+ Place the flag in the leading slot of a [`Select`](https://design.candescent.com/docs/components/select/content.md). `position="leading"` emits `data-icon="inline-start"`, and the slot's size class wins over `size-5`. A small select uses `size-4`.
69
+
70
+ ```tsx
71
+ import { useState } from 'react';
72
+ import { Box, CurrencyFlag, Select, Text, type SelectProps } from '@cdx-ui/components';
73
+
74
+ const currencies = [
75
+ { value: 'USD', label: 'US Dollar (USD)' },
76
+ { value: 'EUR', label: 'Euro (EUR)' },
77
+ { value: 'GBP', label: 'British Pound (GBP)' },
78
+ { value: 'CAD', label: 'Canadian Dollar (CAD)' },
79
+ ];
80
+
81
+ function CurrencySelect({
82
+ size,
83
+ defaultCode,
84
+ }: {
85
+ size: NonNullable<SelectProps['size']>;
86
+ defaultCode: string;
87
+ }) {
88
+ const [code, setCode] = useState(defaultCode);
89
+
90
+ return (
91
+ <Select
92
+ items={currencies}
93
+ size={size}
94
+ value={code}
95
+ onValueChange={setCode}
96
+ className="w-full"
97
+ accessibilityLabel="Currency"
98
+ >
99
+ <Select.Trigger>
100
+ <Select.Icon asChild position="leading">
101
+ <CurrencyFlag code={code} />
102
+ </Select.Icon>
103
+ <Select.Value />
104
+ </Select.Trigger>
105
+ <Select.Content>
106
+ {currencies.map((currency) => (
107
+ <Select.Item key={currency.value} value={currency.value}>
108
+ <CurrencyFlag code={currency.value} />
109
+ <Select.ItemLabel>{currency.label}</Select.ItemLabel>
110
+ </Select.Item>
111
+ ))}
112
+ </Select.Content>
113
+ </Select>
114
+ );
115
+ }
116
+
117
+ export default function CurrencyFlagWithIconsDemo() {
118
+ return (
119
+ <Box className="w-full gap-4">
120
+ <Box className="gap-2">
121
+ <Text size="sm" color="secondary">
122
+ default
123
+ </Text>
124
+ <CurrencySelect size="default" defaultCode="USD" />
125
+ </Box>
126
+ <Box className="gap-2">
127
+ <Text size="sm" color="secondary">
128
+ small
129
+ </Text>
130
+ <CurrencySelect size="small" defaultCode="EUR" />
131
+ </Box>
132
+ </Box>
133
+ );
134
+ }
135
+ ```
136
+
137
+ ## Accessibility
138
+
139
+ The flag is decorative unless `accessibilityLabel` is set. Omit the label when the currency name or code is already next to the flag.
140
+
141
+ ```tsx
142
+ import { Box, CurrencyFlag, Text } from '@cdx-ui/components';
143
+
144
+ export default function CurrencyFlagAccessibilityDemo() {
145
+ return (
146
+ <Box className="gap-5">
147
+ <Box className="flex-row items-center gap-3">
148
+ <CurrencyFlag code="EUR" accessibilityLabel="Euro" />
149
+ <Text>Informative flag with a screen reader label</Text>
150
+ </Box>
151
+ <Box className="flex-row items-center gap-3">
152
+ <CurrencyFlag code="USD" />
153
+ <Text>US Dollar</Text>
154
+ </Box>
155
+ </Box>
156
+ );
157
+ }
158
+ ```
159
+
160
+ ## API
161
+
162
+ ### CurrencyFlag
163
+
164
+ Renders the issuer flag for `code`. A code with no single issuer or no flag renders nothing and logs a warning in development only. It does not throw.
165
+
166
+ | Prop | Type | Default | Description |
167
+ | --- | --- | --- | --- |
168
+ | `className?` | `string` | — | Utility classes for size (`size-*`) and placement, merged after the defaults. |
169
+ | `children?` | `React.ReactNode` | — | — |
170
+ | `size?` | `string \| number` | — | Width and height of the icon, in pixels or any SVG length. The bare icon renders at 24 when omitted. |
171
+ | `data-testid?` | `string` | — | Test identifier forwarded to the rendered SVG. |
172
+ | `code` | `string` | — | ISO 4217 alphabetic currency code, such as `USD` or `EUR`. |
173
+
174
+ Inherits [`SvgProps`](https://github.com/software-mansion/react-native-svg#common-props) except `color`, including `style` and `accessibilityLabel`. `as`, `filled`, and `color` are not accepted.
175
+
176
+ ### currencyFlagCode
177
+
178
+ `currencyFlagCode(code)` returns the `FlagCode` that `CurrencyFlag` renders for `code`, or `undefined` when it renders nothing. Use it to decide whether to reserve space for a flag.
179
+
180
+ - A national code resolves to its first two letters, which ISO 4217 takes from the issuer's ISO 3166-1 alpha-2 code: `USD` resolves to `US`.
181
+ - `EUR` resolves to `EU`.
182
+ - Codes that start with `X` resolve to `undefined`. They name currencies shared by a region (`XOF`, `XAF`, `XCD`, `XPF`), precious metals (`XAU`), and fund or testing codes, none of which has a single issuing country.
183
+ - A code that is not three uppercase letters resolves to `undefined`.
184
+
185
+ ## Defaults and styling
186
+
187
+ - `className` defaults to a `size-5` box. Consumer classes are merged after that default, so a `size-*` utility overrides it.
188
+ - Flag artwork keeps its source colors. Text color classes and theme tokens do not recolor it, because each path has an explicit fill.
189
+ - Prefer a `size-*` class over the inherited numeric `size` prop. The numeric prop bypasses the spacing scale.
190
+
191
+ ## Anatomy
192
+
193
+ | `data-slot` | Element |
194
+ | --------------- | ------------- |
195
+ | `currency-flag` | Rendered flag |
196
+
197
+ When `CurrencyFlag` is the child of `Select.Icon` with `asChild`, the rendered node keeps `data-slot="currency-flag"`. `position="leading"` still sets `data-icon="inline-start"`, and `position="trailing"` sets `data-icon="inline-end"`.
198
+
199
+ ## Accessibility
200
+
201
+ - Without `accessibilityLabel`, the flag is decorative and hidden from assistive technology.
202
+ - With `accessibilityLabel`, the flag is exposed as an image and announced with that label. Use the currency name, such as `Euro`, not the issuer's country name.
@@ -129,32 +129,72 @@ export default function CurrencyInputCustomSymbolDemo() {
129
129
 
130
130
  ## States
131
131
 
132
- The root controls disabled, read-only, required, and invalid state for the field.
132
+ The root controls disabled, read-only, required, and invalid state for the field. Disabled, read-only, and invalid apply to both `ghost` and `outline`.
133
133
 
134
134
  ```tsx
135
- import { Box, CurrencyInput, Text } from '@cdx-ui/components';
135
+ import { Box, CurrencyInput, Text, type CurrencyInputProps } from '@cdx-ui/components';
136
+
137
+ const variants = ['ghost', 'outline'] as const satisfies readonly NonNullable<
138
+ CurrencyInputProps['variant']
139
+ >[];
140
+
141
+ const states = [
142
+ { label: 'Disabled', value: 1200, isDisabled: true },
143
+ { label: 'Read-only', value: 4890, isReadOnly: true },
144
+ { label: 'Invalid', value: 0, isInvalid: true },
145
+ ] as const satisfies readonly {
146
+ label: string;
147
+ value: number;
148
+ isDisabled?: boolean;
149
+ isReadOnly?: boolean;
150
+ isInvalid?: boolean;
151
+ }[];
152
+
153
+ function StateRow({
154
+ variant,
155
+ label,
156
+ value,
157
+ isDisabled,
158
+ isReadOnly,
159
+ isInvalid,
160
+ }: {
161
+ variant: NonNullable<CurrencyInputProps['variant']>;
162
+ label: string;
163
+ value: number;
164
+ isDisabled?: boolean;
165
+ isReadOnly?: boolean;
166
+ isInvalid?: boolean;
167
+ }) {
168
+ return (
169
+ <Box className="gap-2">
170
+ <Text size="sm" color="secondary">
171
+ {label}
172
+ </Text>
173
+ <CurrencyInput
174
+ accessibilityLabel={`${label} ${variant} transfer amount`}
175
+ isDisabled={isDisabled}
176
+ isInvalid={isInvalid}
177
+ isReadOnly={isReadOnly}
178
+ variant={variant}
179
+ value={value}
180
+ />
181
+ </Box>
182
+ );
183
+ }
136
184
 
137
185
  export default function CurrencyInputStatesDemo() {
138
186
  return (
139
- <Box className="w-full gap-4">
140
- <Box className="gap-2">
141
- <Text size="sm" color="secondary">
142
- Disabled
143
- </Text>
144
- <CurrencyInput accessibilityLabel="Disabled transfer amount" isDisabled value={1200} />
145
- </Box>
146
- <Box className="gap-2">
147
- <Text size="sm" color="secondary">
148
- Read-only
149
- </Text>
150
- <CurrencyInput accessibilityLabel="Read-only transfer amount" isReadOnly value={4890} />
151
- </Box>
152
- <Box className="gap-2">
153
- <Text size="sm" color="secondary">
154
- Invalid
155
- </Text>
156
- <CurrencyInput accessibilityLabel="Invalid transfer amount" isInvalid value={0} />
157
- </Box>
187
+ <Box className="w-full gap-6">
188
+ {variants.map((variant) => (
189
+ <Box key={variant} className="gap-4">
190
+ <Text size="sm" color="secondary">
191
+ {variant}
192
+ </Text>
193
+ {states.map((state) => (
194
+ <StateRow key={state.label} variant={variant} {...state} />
195
+ ))}
196
+ </Box>
197
+ ))}
158
198
  </Box>
159
199
  );
160
200
  }
@@ -200,60 +240,138 @@ export default function CurrencyInputWithFieldDemo() {
200
240
  }
201
241
  ```
202
242
 
203
- ## With field and validation
243
+ ## In card
204
244
 
205
- Set invalid state on both `Field` and `CurrencyInput` so the error message and amount styling stay in sync.
245
+ Stack the label above the amount. Align `Field.Label` to the start, and set `align="end"` on `CurrencyInput`.
206
246
 
207
247
  ```tsx
208
- import { useState } from 'react';
209
- import { CurrencyInput, Field } from '@cdx-ui/components';
210
-
211
- const DAILY_LIMIT = 1200;
212
-
213
- export default function CurrencyInputOutlineWithFieldInvalidDemo() {
214
- const [amount, setAmount] = useState(1500);
215
- const isInvalid = amount > DAILY_LIMIT;
248
+ import { Card, CurrencyInput, Field } from '@cdx-ui/components';
216
249
 
250
+ export default function CurrencyInputInCardDemo() {
217
251
  return (
218
- <Field className="w-full" isRequired isInvalid={isInvalid}>
219
- <Field.Label>Amount</Field.Label>
220
- <CurrencyInput
221
- isInvalid={isInvalid}
222
- isRequired
223
- variant="outline"
224
- value={amount}
225
- onChangeValue={setAmount}
226
- />
227
- <Field.Error>Amount exceeds your daily limit.</Field.Error>
228
- </Field>
252
+ <Card className="w-full max-w-md">
253
+ <Card.Content>
254
+ <Field className="w-full">
255
+ <Field.Label className="self-start">Available balance</Field.Label>
256
+ <CurrencyInput align="end" isReadOnly size="small" value={4250.18} />
257
+ </Field>
258
+ </Card.Content>
259
+ </Card>
229
260
  );
230
261
  }
231
262
  ```
232
263
 
233
- The same validation in the `ghost` pattern, with a centered label and error.
264
+ ## With field and validation
265
+
266
+ Set disabled, read-only, and invalid on both `Field` and `CurrencyInput` so the label, message, and amount styling stay in sync. Keep the `outline` label and error aligned to the start. For `ghost`, center the label and error and use `size="small"`.
234
267
 
235
268
  ```tsx
236
269
  import { useState } from 'react';
237
- import { CurrencyInput, Field } from '@cdx-ui/components';
270
+ import { Box, CurrencyInput, Field, Text } from '@cdx-ui/components';
238
271
 
239
272
  const DAILY_LIMIT = 1200;
240
273
 
241
- export default function CurrencyInputWithFieldInvalidDemo() {
274
+ function OutlineFields() {
242
275
  const [amount, setAmount] = useState(1500);
243
276
  const isInvalid = amount > DAILY_LIMIT;
244
277
 
245
278
  return (
246
- <Field className="w-full" isRequired isInvalid={isInvalid}>
247
- <Field.Label className="text-center">Amount</Field.Label>
248
- <CurrencyInput
249
- isInvalid={isInvalid}
250
- isRequired
251
- size="small"
252
- value={amount}
253
- onChangeValue={setAmount}
254
- />
255
- <Field.Error className="justify-center">Amount exceeds your daily limit.</Field.Error>
256
- </Field>
279
+ <Box className="w-full gap-4">
280
+ <Text size="sm" color="secondary">
281
+ outline
282
+ </Text>
283
+ <Box className="gap-2">
284
+ <Text size="sm" color="secondary">
285
+ Disabled
286
+ </Text>
287
+ <Field className="w-full" isDisabled>
288
+ <Field.Label>Amount</Field.Label>
289
+ <CurrencyInput isDisabled variant="outline" value={1200} />
290
+ </Field>
291
+ </Box>
292
+ <Box className="gap-2">
293
+ <Text size="sm" color="secondary">
294
+ Read-only
295
+ </Text>
296
+ <Field className="w-full" isReadOnly>
297
+ <Field.Label>Amount</Field.Label>
298
+ <CurrencyInput isReadOnly variant="outline" value={4890} />
299
+ </Field>
300
+ </Box>
301
+ <Box className="gap-2">
302
+ <Text size="sm" color="secondary">
303
+ Invalid
304
+ </Text>
305
+ <Field className="w-full" isRequired isInvalid={isInvalid}>
306
+ <Field.Label>Amount</Field.Label>
307
+ <CurrencyInput
308
+ isInvalid={isInvalid}
309
+ isRequired
310
+ variant="outline"
311
+ value={amount}
312
+ onChangeValue={setAmount}
313
+ />
314
+ <Field.Error>Amount exceeds your daily limit.</Field.Error>
315
+ </Field>
316
+ </Box>
317
+ </Box>
318
+ );
319
+ }
320
+
321
+ function GhostFields() {
322
+ const [amount, setAmount] = useState(1500);
323
+ const isInvalid = amount > DAILY_LIMIT;
324
+
325
+ return (
326
+ <Box className="w-full gap-4">
327
+ <Text size="sm" color="secondary">
328
+ ghost
329
+ </Text>
330
+ <Box className="gap-2">
331
+ <Text size="sm" color="secondary">
332
+ Disabled
333
+ </Text>
334
+ <Field className="w-full" isDisabled>
335
+ <Field.Label className="text-center">Amount</Field.Label>
336
+ <CurrencyInput isDisabled size="small" variant="ghost" value={1200} />
337
+ </Field>
338
+ </Box>
339
+ <Box className="gap-2">
340
+ <Text size="sm" color="secondary">
341
+ Read-only
342
+ </Text>
343
+ <Field className="w-full" isReadOnly>
344
+ <Field.Label className="text-center">Amount</Field.Label>
345
+ <CurrencyInput isReadOnly size="small" variant="ghost" value={4890} />
346
+ </Field>
347
+ </Box>
348
+ <Box className="gap-2">
349
+ <Text size="sm" color="secondary">
350
+ Invalid
351
+ </Text>
352
+ <Field className="w-full" isRequired isInvalid={isInvalid}>
353
+ <Field.Label className="text-center">Amount</Field.Label>
354
+ <CurrencyInput
355
+ isInvalid={isInvalid}
356
+ isRequired
357
+ size="small"
358
+ variant="ghost"
359
+ value={amount}
360
+ onChangeValue={setAmount}
361
+ />
362
+ <Field.Error className="justify-center">Amount exceeds your daily limit.</Field.Error>
363
+ </Field>
364
+ </Box>
365
+ </Box>
366
+ );
367
+ }
368
+
369
+ export default function CurrencyInputOutlineWithFieldInvalidDemo() {
370
+ return (
371
+ <Box className="w-full gap-6">
372
+ <OutlineFields />
373
+ <GhostFields />
374
+ </Box>
257
375
  );
258
376
  }
259
377
  ```
@@ -278,6 +396,7 @@ Controlled calculator-style monetary entry. The numeric `value` is expressed in
278
396
  | `isFullWidth?` | `boolean` | — | If true, the input element will span the full width of its parent. |
279
397
  | `variant?` | `'ghost' \| 'outline'` | `'ghost'` | Visual style. `ghost` is the large, centered, borderless amount entry; `outline` renders the bordered `Input` shell with a leading currency-symbol prefix, for amounts that sit alongside other form fields. |
280
398
  | `size?` | `'default' \| 'small'` | `'default'` | Height, padding, and text size. |
399
+ | `align?` | `'center' \| 'end'` | — | Horizontal alignment of the amount. Defaults to `center` on `ghost`. On `outline`, the amount stays at the start of the field until `align` is set. |
281
400
 
282
401
  Supports `accessibilityLabel`, `accessibilityHint`, `testID`, `onFocus`, `onBlur`, and `returnKeyType` from [`TextInputProps`](https://reactnative.dev/docs/textinput#props). `style` applies to the root container, and the forwarded ref targets the underlying `TextInput`.
283
402
 
@@ -215,6 +215,53 @@ export default function DataGridRichCellsDemo() {
215
215
  }
216
216
  ```
217
217
 
218
+ ## Numeric columns
219
+
220
+ Set `align: 'end'` on numeric columns so values line up by their last digit. The header label follows the column alignment, and the sort control moves to the label's leading side so the label ends at the same edge as the values. A header label that is wider than its column truncates with an ellipsis, and the full label is available as a tooltip. Give the column enough `width` for its label plus the sort control to keep the label readable.
221
+
222
+ ```tsx
223
+ import { DataGrid, type GridColDef } from '@cdx-ui/data-grid';
224
+ import { accounts, type Account } from './_data';
225
+
226
+ const currencyFormatter = new Intl.NumberFormat('en-US', {
227
+ style: 'currency',
228
+ currency: 'USD',
229
+ maximumFractionDigits: 0,
230
+ });
231
+
232
+ const columns: GridColDef<Account>[] = [
233
+ { field: 'name', headerName: 'Account', flex: 1, minWidth: 160 },
234
+ {
235
+ field: 'balance',
236
+ headerName: 'Available balance',
237
+ width: 200,
238
+ align: 'end',
239
+ valueFormatter: (_, row) => currencyFormatter.format(row.balance),
240
+ },
241
+ {
242
+ field: 'automation',
243
+ headerName: 'Automated payments share of all outgoing payments',
244
+ width: 160,
245
+ align: 'end',
246
+ valueFormatter: (_, row) => `${row.automation.toString()}%`,
247
+ },
248
+ ];
249
+
250
+ export default function DataGridNumericColumnsDemo() {
251
+ return (
252
+ <DataGrid
253
+ rows={accounts}
254
+ columns={columns}
255
+ aria-label="Account balances"
256
+ defaultSortModel={[{ field: 'balance', sort: 'desc' }]}
257
+ defaultPaginationModel={{ page: 0, pageSize: 5 }}
258
+ pageSizeOptions={[5, 10]}
259
+ autoHeight
260
+ />
261
+ );
262
+ }
263
+ ```
264
+
218
265
  ## Toolbar actions
219
266
 
220
267
  `toolbarActions` is an extension slot for your own toolbar controls beside search — export, density, view toggles, and so on. DataGrid does not ship toolbar buttons; you compose them and wire `onPress` to state that drives grid props.
@@ -128,6 +128,60 @@ export default function DateRangePickerBottomSheetDemo() {
128
128
  }
129
129
  ```
130
130
 
131
+ ## Snap points
132
+
133
+ The sheet snaps to 70% and 90% of the screen by default. Pass `snapPoints` for a different height, and set `stackBehavior="push"` when the picker opens over another sheet so that sheet stays presented underneath. With a short snap point, set `fill` and wrap the content in `BottomSheet.ScrollView` so the calendar scrolls under a fixed header instead of being cut off.
134
+
135
+ ```tsx
136
+ import { useState } from 'react';
137
+ import {
138
+ BottomSheet,
139
+ DateField,
140
+ DateRangePicker,
141
+ Field,
142
+ type DateRangeValue,
143
+ } from '@cdx-ui/components';
144
+ import { PickerBottomSheetFrame } from './_frame';
145
+
146
+ export default function DateRangePickerBottomSheetSnapPointsDemo() {
147
+ const [value, setValue] = useState<DateRangeValue | undefined>();
148
+ const [open, setOpen] = useState(false);
149
+
150
+ return (
151
+ <PickerBottomSheetFrame>
152
+ <Field className="w-full max-w-sm">
153
+ <DateRangePicker
154
+ value={value}
155
+ onValueChange={setValue}
156
+ isOpen={open}
157
+ onOpenChange={setOpen}
158
+ >
159
+ <Field.Label>Due dates</Field.Label>
160
+ <DateRangePicker.Trigger className="w-full">
161
+ <DateField.Group fullWidth>
162
+ <DateField.Input slot="start" />
163
+ <DateRangePicker.RangeSeparator />
164
+ <DateField.Input slot="end" />
165
+ <DateField.Suffix>
166
+ <DateRangePicker.TriggerIndicator />
167
+ </DateField.Suffix>
168
+ </DateField.Group>
169
+ </DateRangePicker.Trigger>
170
+ <DateRangePicker.BottomSheet snapPoints={['55%']} stackBehavior="push" fill>
171
+ <BottomSheet.Header title="Select dates" onClose={() => setOpen(false)} />
172
+ <BottomSheet.ScrollView>
173
+ <BottomSheet.Content>
174
+ <DateRangePicker.Calendar accessibilityLabel="Due dates" />
175
+ </BottomSheet.Content>
176
+ </BottomSheet.ScrollView>
177
+ </DateRangePicker.BottomSheet>
178
+ </DateRangePicker>
179
+ </Field>
180
+ </PickerBottomSheetFrame>
181
+ );
182
+ }
183
+ ```
184
+
131
185
  ## Standalone
132
186
 
133
187
  Render a `DateRangePicker.Calendar` inline instead of a presentation surface when the fields and calendar share the screen.
@@ -294,7 +348,14 @@ Presents the range calendar in a modal dialog. Wires the surface's open state an
294
348
 
295
349
  ### DateRangePicker.BottomSheet
296
350
 
297
- Presents the range calendar in a bottom sheet, the preferred surface on native. It wires open state only — compose `BottomSheet.Header` and `BottomSheet.Content` (or any sheet layout) as its children.
351
+ Presents the range calendar in a bottom sheet, the preferred surface on native. It wires open state only — compose `BottomSheet.Header` and `BottomSheet.Content` (or any sheet layout) as its children. `snapPoints`, `enableDynamicSizing`, and `stackBehavior` are forwarded to [`BottomSheet.Modal`](https://design.candescent.com/docs/components/bottom-sheet/content.md).
352
+
353
+ | Prop | Type | Default | Description |
354
+ | --- | --- | --- | --- |
355
+ | `snapPoints?` | `(string \| number)[] \| SharedValue<(string \| number)[]>` | `['70%', '90%']` | Heights the sheet snaps to, as percentages of the screen or pixel values. |
356
+ | `enableDynamicSizing?` | `boolean` | `false` | Sizes the sheet to its content and adds that height as a snap point. |
357
+ | `stackBehavior?` | `'replace' \| 'push' \| 'switch'` | `'switch'` | How the sheet opens over a sheet that is already presented: `push` keeps that sheet underneath, `switch` minimizes it until this sheet closes, and `replace` dismisses it. |
358
+ | `fill?` | `boolean` | `false` | Lays the children out in a container that fills the sheet, so a fixed header can sit above a `BottomSheet.ScrollView`. By default the children size a `BottomSheet.View`. |
298
359
 
299
360
  ## Accessibility
300
361