@ledgerhq/lumen-ui-rnative 0.1.21 → 0.1.23

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 (99) hide show
  1. package/dist/module/lib/Components/ListItem/ListItem.js +57 -27
  2. package/dist/module/lib/Components/ListItem/ListItem.js.map +1 -1
  3. package/dist/module/lib/Components/ListItem/ListItem.mdx +15 -7
  4. package/dist/module/lib/Components/ListItem/ListItem.stories.js +497 -283
  5. package/dist/module/lib/Components/ListItem/ListItem.stories.js.map +1 -1
  6. package/dist/module/lib/Components/ListItem/ListItem.test.js +153 -0
  7. package/dist/module/lib/Components/ListItem/ListItem.test.js.map +1 -0
  8. package/dist/module/lib/Components/{TriggerButton/TriggerButton.js → MediaButton/MediaButton.js} +13 -10
  9. package/dist/module/lib/Components/MediaButton/MediaButton.js.map +1 -0
  10. package/{src/lib/Components/TriggerButton/TriggerButton.mdx → dist/module/lib/Components/MediaButton/MediaButton.mdx} +10 -10
  11. package/dist/module/lib/Components/{TriggerButton/TriggerButton.stories.js → MediaButton/MediaButton.stories.js} +18 -18
  12. package/dist/module/lib/Components/MediaButton/MediaButton.stories.js.map +1 -0
  13. package/dist/module/lib/Components/{TriggerButton/TriggerButton.test.js → MediaButton/MediaButton.test.js} +14 -14
  14. package/dist/module/lib/Components/MediaButton/MediaButton.test.js.map +1 -0
  15. package/dist/module/lib/Components/MediaButton/index.js +5 -0
  16. package/dist/module/lib/Components/MediaButton/index.js.map +1 -0
  17. package/dist/module/lib/Components/MediaButton/types.js.map +1 -0
  18. package/dist/module/lib/Components/NavBar/NavBar.js +0 -2
  19. package/dist/module/lib/Components/NavBar/NavBar.js.map +1 -1
  20. package/dist/module/lib/Components/OptionList/OptionList.figma.js +28 -0
  21. package/dist/module/lib/Components/OptionList/OptionList.figma.js.map +1 -0
  22. package/dist/module/lib/Components/OptionList/OptionList.js +452 -0
  23. package/dist/module/lib/Components/OptionList/OptionList.js.map +1 -0
  24. package/dist/module/lib/Components/OptionList/OptionList.mdx +304 -0
  25. package/dist/module/lib/Components/OptionList/OptionList.stories.js +735 -0
  26. package/dist/module/lib/Components/OptionList/OptionList.stories.js.map +1 -0
  27. package/dist/module/lib/Components/OptionList/OptionList.test.js +443 -0
  28. package/dist/module/lib/Components/OptionList/OptionList.test.js.map +1 -0
  29. package/dist/module/lib/Components/OptionList/index.js +5 -0
  30. package/dist/module/lib/Components/OptionList/index.js.map +1 -0
  31. package/dist/module/lib/Components/OptionList/types.js +4 -0
  32. package/dist/module/lib/Components/OptionList/types.js.map +1 -0
  33. package/dist/module/lib/Components/OptionList/useOptionList/useOptionListItems.js +36 -0
  34. package/dist/module/lib/Components/OptionList/useOptionList/useOptionListItems.js.map +1 -0
  35. package/dist/module/lib/Components/OptionList/useOptionList/useOptionListItems.test.js +84 -0
  36. package/dist/module/lib/Components/OptionList/useOptionList/useOptionListItems.test.js.map +1 -0
  37. package/dist/module/lib/Components/index.js +2 -1
  38. package/dist/module/lib/Components/index.js.map +1 -1
  39. package/dist/typescript/src/lib/Components/ListItem/ListItem.d.ts +8 -8
  40. package/dist/typescript/src/lib/Components/ListItem/ListItem.d.ts.map +1 -1
  41. package/dist/typescript/src/lib/Components/ListItem/types.d.ts +11 -7
  42. package/dist/typescript/src/lib/Components/ListItem/types.d.ts.map +1 -1
  43. package/dist/typescript/src/lib/Components/MediaButton/MediaButton.d.ts +23 -0
  44. package/dist/typescript/src/lib/Components/MediaButton/MediaButton.d.ts.map +1 -0
  45. package/dist/typescript/src/lib/Components/MediaButton/index.d.ts +3 -0
  46. package/dist/typescript/src/lib/Components/MediaButton/index.d.ts.map +1 -0
  47. package/dist/typescript/src/lib/Components/{TriggerButton → MediaButton}/types.d.ts +10 -5
  48. package/dist/typescript/src/lib/Components/MediaButton/types.d.ts.map +1 -0
  49. package/dist/typescript/src/lib/Components/OptionList/OptionList.d.ts +12 -0
  50. package/dist/typescript/src/lib/Components/OptionList/OptionList.d.ts.map +1 -0
  51. package/dist/typescript/src/lib/Components/OptionList/OptionList.figma.d.ts +2 -0
  52. package/dist/typescript/src/lib/Components/OptionList/OptionList.figma.d.ts.map +1 -0
  53. package/dist/typescript/src/lib/Components/OptionList/index.d.ts +3 -0
  54. package/dist/typescript/src/lib/Components/OptionList/index.d.ts.map +1 -0
  55. package/dist/typescript/src/lib/Components/OptionList/types.d.ts +97 -0
  56. package/dist/typescript/src/lib/Components/OptionList/types.d.ts.map +1 -0
  57. package/dist/typescript/src/lib/Components/OptionList/useOptionList/useOptionListItems.d.ts +12 -0
  58. package/dist/typescript/src/lib/Components/OptionList/useOptionList/useOptionListItems.d.ts.map +1 -0
  59. package/dist/typescript/src/lib/Components/index.d.ts +2 -1
  60. package/dist/typescript/src/lib/Components/index.d.ts.map +1 -1
  61. package/dist/typescript/src/styles/types/theme.types.d.ts +7 -6
  62. package/dist/typescript/src/styles/types/theme.types.d.ts.map +1 -1
  63. package/package.json +1 -1
  64. package/src/lib/Components/ListItem/ListItem.mdx +15 -7
  65. package/src/lib/Components/ListItem/ListItem.stories.tsx +354 -220
  66. package/src/lib/Components/ListItem/ListItem.test.tsx +152 -0
  67. package/src/lib/Components/ListItem/ListItem.tsx +63 -28
  68. package/src/lib/Components/ListItem/types.ts +11 -8
  69. package/{dist/module/lib/Components/TriggerButton/TriggerButton.mdx → src/lib/Components/MediaButton/MediaButton.mdx} +10 -10
  70. package/src/lib/Components/{TriggerButton/TriggerButton.stories.tsx → MediaButton/MediaButton.stories.tsx} +28 -28
  71. package/src/lib/Components/{TriggerButton/TriggerButton.test.tsx → MediaButton/MediaButton.test.tsx} +22 -22
  72. package/src/lib/Components/{TriggerButton/TriggerButton.tsx → MediaButton/MediaButton.tsx} +27 -21
  73. package/src/lib/Components/MediaButton/index.ts +2 -0
  74. package/src/lib/Components/{TriggerButton → MediaButton}/types.ts +10 -5
  75. package/src/lib/Components/NavBar/NavBar.tsx +0 -3
  76. package/src/lib/Components/OptionList/OptionList.figma.tsx +37 -0
  77. package/src/lib/Components/OptionList/OptionList.mdx +304 -0
  78. package/src/lib/Components/OptionList/OptionList.stories.tsx +755 -0
  79. package/src/lib/Components/OptionList/OptionList.test.tsx +412 -0
  80. package/src/lib/Components/OptionList/OptionList.tsx +532 -0
  81. package/src/lib/Components/OptionList/index.ts +2 -0
  82. package/src/lib/Components/OptionList/types.ts +115 -0
  83. package/src/lib/Components/OptionList/useOptionList/useOptionListItems.test.ts +73 -0
  84. package/src/lib/Components/OptionList/useOptionList/useOptionListItems.ts +49 -0
  85. package/src/lib/Components/index.ts +2 -1
  86. package/src/styles/types/theme.types.ts +8 -6
  87. package/dist/module/lib/Components/TriggerButton/TriggerButton.js.map +0 -1
  88. package/dist/module/lib/Components/TriggerButton/TriggerButton.stories.js.map +0 -1
  89. package/dist/module/lib/Components/TriggerButton/TriggerButton.test.js.map +0 -1
  90. package/dist/module/lib/Components/TriggerButton/index.js +0 -5
  91. package/dist/module/lib/Components/TriggerButton/index.js.map +0 -1
  92. package/dist/module/lib/Components/TriggerButton/types.js.map +0 -1
  93. package/dist/typescript/src/lib/Components/TriggerButton/TriggerButton.d.ts +0 -23
  94. package/dist/typescript/src/lib/Components/TriggerButton/TriggerButton.d.ts.map +0 -1
  95. package/dist/typescript/src/lib/Components/TriggerButton/index.d.ts +0 -3
  96. package/dist/typescript/src/lib/Components/TriggerButton/index.d.ts.map +0 -1
  97. package/dist/typescript/src/lib/Components/TriggerButton/types.d.ts.map +0 -1
  98. package/src/lib/Components/TriggerButton/index.ts +0 -2
  99. /package/dist/module/lib/Components/{TriggerButton → MediaButton}/types.js +0 -0
@@ -0,0 +1,304 @@
1
+ import { Meta, Canvas } from '@storybook/addon-docs/blocks';
2
+ import * as OptionListStories from './OptionList.stories';
3
+ import {
4
+ CustomTabs,
5
+ Tab,
6
+ DoVsDontRow,
7
+ DoBlockItem,
8
+ DontBlockItem,
9
+ } from '../../../../.storybook/components';
10
+
11
+ <Meta title='Selection/OptionList' of={OptionListStories} />
12
+
13
+ # OptionList
14
+
15
+ <CustomTabs>
16
+ <Tab label="Overview">
17
+
18
+ ## Introduction
19
+
20
+ OptionList is a data-driven, composable selection list designed to be embedded inside a `BottomSheet`, a new screen, or any container. Unlike `Select`, it does not manage its own trigger or modal — consumers compose it within their own layout.
21
+
22
+ It handles **selection state**, **automatic grouping** (via a `group` field on items), and exposes a `renderItem` callback for full control over item rendering.
23
+
24
+ > View in [Figma](https://www.figma.com/design/JxaLVMTWirCpU0rsbZ30k7/2.-Components-Library?node-id=15941-6709&m=dev).
25
+
26
+ ## Anatomy
27
+
28
+ <Canvas of={OptionListStories.Base} />
29
+
30
+ - **OptionList**: Root component managing selection state and item processing
31
+ - **OptionListTrigger**: Input-style trigger with floating label and chevron — displays the selected value and opens a BottomSheet on press
32
+ - **OptionListContent**: Iterates items, renders group labels and separators automatically, calls `renderItem`
33
+ - **OptionListItem**: Pressable item with selection check mark
34
+ - **OptionListItemLeading**: Slot for leading visuals (icons, avatars)
35
+ - **OptionListItemContent**: Flex column for title + description
36
+ - **OptionListItemContentRow**: Horizontal row for placing elements side-by-side (e.g. title + tag)
37
+ - **OptionListItemText**: Styled title text
38
+ - **OptionListItemDescription**: Styled description text
39
+
40
+ ## Properties
41
+
42
+ ### Grouped items
43
+
44
+ Items with a `group` field are automatically grouped with labels and separators:
45
+
46
+ <Canvas of={OptionListStories.WithGroups} />
47
+
48
+ ### Complex item layout
49
+
50
+ Use `OptionListItemContentRow` to place a `Tag` next to the title:
51
+
52
+ <Canvas of={OptionListStories.WithContentRow} />
53
+
54
+ ### Disabled items
55
+
56
+ Individual items can be disabled:
57
+
58
+ <Canvas of={OptionListStories.WithDisabledItems} />
59
+
60
+ ### Groups + complex layout
61
+
62
+ Combining grouping with rich item content:
63
+
64
+ <Canvas of={OptionListStories.GroupedWithContentRow} />
65
+
66
+ ### Trigger showcase
67
+
68
+ OptionList can be opened from any trigger. `MediaButton` supports multiple appearances (`gray`, `transparent`, `no-background`), optional icons (`flat` / `rounded`), and disabled state:
69
+
70
+ <Canvas of={OptionListStories.TriggerShowcase} />
71
+
72
+ </Tab>
73
+ <Tab label="Implementation">
74
+
75
+ ## Setup
76
+
77
+ Install and set up the library with our [Setup Guide →](?path=/docs/getting-started-setup--docs).
78
+
79
+ ## Basic usage
80
+
81
+ ```tsx
82
+ import {
83
+ OptionList,
84
+ OptionListContent,
85
+ OptionListItem,
86
+ OptionListItemContent,
87
+ OptionListItemText,
88
+ } from '@ledgerhq/lumen-ui-rnative';
89
+
90
+ const items = [
91
+ { value: 'a', label: 'Option A' },
92
+ { value: 'b', label: 'Option B' },
93
+ ];
94
+
95
+ function MyList() {
96
+ const [value, setValue] = useState<string | null>(null);
97
+
98
+ return (
99
+ <OptionList items={items} value={value} onValueChange={setValue}>
100
+ <OptionListContent
101
+ renderItem={(item) => (
102
+ <OptionListItem value={item.value}>
103
+ <OptionListItemContent>
104
+ <OptionListItemText>{item.label}</OptionListItemText>
105
+ </OptionListItemContent>
106
+ </OptionListItem>
107
+ )}
108
+ />
109
+ </OptionList>
110
+ );
111
+ }
112
+ ```
113
+
114
+ ## Inside a BottomSheet
115
+
116
+ Use `OptionListTrigger` as the input-style trigger — it provides a floating label that animates up when a value is selected, and a chevron indicator. Pass children only when a value is selected so the label stays centered when empty.
117
+
118
+ ```tsx
119
+ import {
120
+ OptionList, OptionListContent, OptionListItem,
121
+ OptionListItemContent, OptionListItemText, OptionListTrigger,
122
+ BottomSheet, BottomSheetHeader, BottomSheetView,
123
+ useBottomSheetRef, Text,
124
+ } from '@ledgerhq/lumen-ui-rnative';
125
+
126
+ function CurrencyPicker() {
127
+ const [value, setValue] = useState<string | null>(null);
128
+ const ref = useBottomSheetRef();
129
+ const selected = items.find((i) => i.value === value);
130
+
131
+ return (
132
+ <>
133
+ <OptionListTrigger
134
+ label='Currency'
135
+ onPress={() => ref.current?.present()}
136
+ >
137
+ {selected && <Text lx={{ color: 'base' }}>{selected.label}</Text>}
138
+ </OptionListTrigger>
139
+ <BottomSheet
140
+ ref={ref}
141
+ enableDynamicSizing
142
+ snapPoints={null}
143
+ onClose={() => ref.current?.dismiss()}
144
+ >
145
+ <BottomSheetView>
146
+ <BottomSheetHeader title='Pick a currency' />
147
+ <OptionList
148
+ items={items}
149
+ value={value}
150
+ onValueChange={(v) => { setValue(v); ref.current?.dismiss(); }}
151
+ >
152
+ <OptionListContent
153
+ renderItem={(item) => (
154
+ <OptionListItem value={item.value}>
155
+ <OptionListItemContent>
156
+ <OptionListItemText>{item.label}</OptionListItemText>
157
+ </OptionListItemContent>
158
+ </OptionListItem>
159
+ )}
160
+ />
161
+ </OptionList>
162
+ </BottomSheetView>
163
+ </BottomSheet>
164
+ </>
165
+ );
166
+ }
167
+ ```
168
+
169
+ ## Grouping
170
+
171
+ Add a `group` field to items — labels and separators are rendered automatically:
172
+
173
+ ```tsx
174
+ const items = [
175
+ { value: 'btc', label: 'Bitcoin', group: 'Crypto' },
176
+ { value: 'eth', label: 'Ethereum', group: 'Crypto' },
177
+ { value: 'usd', label: 'US Dollar', group: 'Fiat' },
178
+ ];
179
+ ```
180
+
181
+ ## Controlled vs uncontrolled
182
+
183
+ Use `value` + `onValueChange` (controlled) when OptionList is inside a BottomSheet — the sheet unmounts children on dismiss, so internal state is lost. Use `defaultValue` (uncontrolled) only when the component stays mounted (e.g. inline in a screen).
184
+
185
+ ## Custom item layout with meta
186
+
187
+ Use `meta` for arbitrary data, and sub-components for layout:
188
+
189
+ ```tsx
190
+ const items = [
191
+ { value: 'eth', label: 'Ethereum', meta: { ticker: 'ETH', tag: 'ERC-20' } },
192
+ ];
193
+
194
+ <OptionListContent
195
+ renderItem={(item) => {
196
+ const meta = item.meta as { ticker: string; tag: string };
197
+ return (
198
+ <OptionListItem value={item.value}>
199
+ <OptionListItemLeading>
200
+ <Spot appearance='icon' icon={Wallet} />
201
+ </OptionListItemLeading>
202
+ <OptionListItemContent>
203
+ <OptionListItemContentRow>
204
+ <OptionListItemText>{item.label}</OptionListItemText>
205
+ <Tag label={meta.tag} appearance='gray' size='sm' />
206
+ </OptionListItemContentRow>
207
+ <OptionListItemDescription>{meta.ticker}</OptionListItemDescription>
208
+ </OptionListItemContent>
209
+ </OptionListItem>
210
+ );
211
+ }}
212
+ />
213
+ ```
214
+
215
+ ## Do's and Don'ts
216
+
217
+ <div className='flex flex-col gap-24'>
218
+
219
+ <DoVsDontRow>
220
+ <DoBlockItem
221
+ title='Pass items as a flat array'
222
+ description='Use the group field for grouping — the component handles labels and separators automatically.'
223
+ >
224
+
225
+ {/* prettier-ignore */}
226
+ ```tsx
227
+ <OptionList
228
+ items={[
229
+ { value: 'a', label: 'A', group: 'Group 1' },
230
+ { value: 'b', label: 'B', group: 'Group 2' },
231
+ ]}
232
+ value={value}
233
+ onValueChange={setValue}
234
+ >
235
+ <OptionListContent renderItem={...} />
236
+ </OptionList>
237
+ ```
238
+
239
+ </DoBlockItem>
240
+ <DontBlockItem
241
+ title="Don't manually render group labels or separators"
242
+ description='OptionListContent handles group rendering internally based on item data.'
243
+ >
244
+
245
+ {/* prettier-ignore */}
246
+ ```tsx
247
+ <OptionList
248
+ items={items}
249
+ value={value}
250
+ onValueChange={setValue}
251
+ >
252
+ <Text>Group 1</Text>
253
+ <OptionListContent renderItem={...} />
254
+ <Divider />
255
+ <Text>Group 2</Text>
256
+ <OptionListContent renderItem={...} />
257
+ </OptionList>
258
+ ```
259
+
260
+ </DontBlockItem>
261
+ </DoVsDontRow>
262
+
263
+ <DoVsDontRow>
264
+ <DoBlockItem
265
+ title='Compose OptionList inside your own container'
266
+ description='OptionList is display-only — wrap it in a BottomSheet, screen, or any layout.'
267
+ >
268
+
269
+ {/* prettier-ignore */}
270
+ ```tsx
271
+ <BottomSheet ref={ref}>
272
+ <BottomSheetView>
273
+ <OptionList items={items} value={value} onValueChange={setValue}>
274
+ <OptionListContent renderItem={...} />
275
+ </OptionList>
276
+ </BottomSheetView>
277
+ </BottomSheet>
278
+ ```
279
+
280
+ </DoBlockItem>
281
+ <DontBlockItem
282
+ title="Don't expect OptionList to manage the BottomSheet"
283
+ description='Use OptionListTrigger to open the sheet yourself — OptionList only handles selection state, not the container.'
284
+ >
285
+
286
+ {/* prettier-ignore */}
287
+ ```tsx
288
+ <OptionList
289
+ items={items}
290
+ value={value}
291
+ onValueChange={setValue}
292
+ trigger={<Button>Open</Button>}
293
+ >
294
+ <OptionListContent renderItem={...} />
295
+ </OptionList>
296
+ ```
297
+
298
+ </DontBlockItem>
299
+ </DoVsDontRow>
300
+
301
+ </div>
302
+
303
+ </Tab>
304
+ </CustomTabs>