react-native-platform-components 0.8.10 → 1.0.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 (67) hide show
  1. package/README.md +68 -891
  2. package/android/src/main/java/com/platformcomponents/PCDatePickerView.kt +17 -3
  3. package/android/src/main/java/com/platformcomponents/PCImageLoader.kt +88 -0
  4. package/android/src/main/java/com/platformcomponents/PCSegmentedControlView.kt +292 -31
  5. package/android/src/main/java/com/platformcomponents/PCSegmentedControlViewManager.kt +74 -8
  6. package/android/src/main/java/com/platformcomponents/PCSelectionMenuView.kt +2 -1
  7. package/android/src/main/java/com/platformcomponents/PCThemeSupport.kt +94 -0
  8. package/android/src/main/res/values/styles.xml +40 -0
  9. package/ios/PCImageLoader.swift +58 -0
  10. package/ios/PCSegmentedControl.mm +85 -25
  11. package/ios/PCSegmentedControl.swift +231 -308
  12. package/lib/commonjs/DatePickerNativeComponent.ts +4 -2
  13. package/lib/commonjs/SegmentedControl.js +138 -6
  14. package/lib/commonjs/SegmentedControl.js.map +1 -1
  15. package/lib/commonjs/SegmentedControlNativeComponent.ts +62 -8
  16. package/lib/commonjs/SelectionMenuNativeComponent.ts +4 -2
  17. package/lib/commonjs/index.web.js.map +1 -1
  18. package/lib/module/DatePickerNativeComponent.ts +4 -2
  19. package/lib/module/SegmentedControl.js +138 -7
  20. package/lib/module/SegmentedControl.js.map +1 -1
  21. package/lib/module/SegmentedControlNativeComponent.ts +62 -8
  22. package/lib/module/SelectionMenuNativeComponent.ts +4 -2
  23. package/lib/module/index.web.js.map +1 -1
  24. package/lib/typescript/commonjs/docs/docusaurus.config.d.ts +4 -0
  25. package/lib/typescript/commonjs/docs/docusaurus.config.d.ts.map +1 -0
  26. package/lib/typescript/commonjs/docs/sidebars.d.ts +4 -0
  27. package/lib/typescript/commonjs/docs/sidebars.d.ts.map +1 -0
  28. package/lib/typescript/commonjs/src/DatePickerNativeComponent.d.ts +2 -2
  29. package/lib/typescript/commonjs/src/DatePickerNativeComponent.d.ts.map +1 -1
  30. package/lib/typescript/commonjs/src/SegmentedControl.d.ts +111 -6
  31. package/lib/typescript/commonjs/src/SegmentedControl.d.ts.map +1 -1
  32. package/lib/typescript/commonjs/src/SegmentedControlNativeComponent.d.ts +46 -7
  33. package/lib/typescript/commonjs/src/SegmentedControlNativeComponent.d.ts.map +1 -1
  34. package/lib/typescript/commonjs/src/SelectionMenuNativeComponent.d.ts +2 -2
  35. package/lib/typescript/commonjs/src/SelectionMenuNativeComponent.d.ts.map +1 -1
  36. package/lib/typescript/commonjs/src/index.web.d.ts +36 -1
  37. package/lib/typescript/commonjs/src/index.web.d.ts.map +1 -1
  38. package/lib/typescript/module/docs/docusaurus.config.d.ts +4 -0
  39. package/lib/typescript/module/docs/docusaurus.config.d.ts.map +1 -0
  40. package/lib/typescript/module/docs/sidebars.d.ts +4 -0
  41. package/lib/typescript/module/docs/sidebars.d.ts.map +1 -0
  42. package/lib/typescript/module/src/DatePicker.d.ts +1 -1
  43. package/lib/typescript/module/src/DatePicker.d.ts.map +1 -1
  44. package/lib/typescript/module/src/DatePickerNativeComponent.d.ts +2 -2
  45. package/lib/typescript/module/src/DatePickerNativeComponent.d.ts.map +1 -1
  46. package/lib/typescript/module/src/SegmentedControl.d.ts +111 -6
  47. package/lib/typescript/module/src/SegmentedControl.d.ts.map +1 -1
  48. package/lib/typescript/module/src/SegmentedControlNativeComponent.d.ts +46 -7
  49. package/lib/typescript/module/src/SegmentedControlNativeComponent.d.ts.map +1 -1
  50. package/lib/typescript/module/src/SelectionMenu.d.ts +1 -1
  51. package/lib/typescript/module/src/SelectionMenu.d.ts.map +1 -1
  52. package/lib/typescript/module/src/SelectionMenuNativeComponent.d.ts +2 -2
  53. package/lib/typescript/module/src/SelectionMenuNativeComponent.d.ts.map +1 -1
  54. package/lib/typescript/module/src/index.d.ts +6 -6
  55. package/lib/typescript/module/src/index.d.ts.map +1 -1
  56. package/lib/typescript/module/src/index.web.d.ts +36 -1
  57. package/lib/typescript/module/src/index.web.d.ts.map +1 -1
  58. package/package.json +62 -37
  59. package/plugin/build/index.cjs +58 -17
  60. package/plugin/build/index.d.ts +32 -15
  61. package/plugin/build/index.d.ts.map +1 -1
  62. package/plugin/tsconfig.json +9 -4
  63. package/src/DatePickerNativeComponent.ts +4 -2
  64. package/src/SegmentedControl.tsx +238 -11
  65. package/src/SegmentedControlNativeComponent.ts +62 -8
  66. package/src/SelectionMenuNativeComponent.ts +4 -2
  67. package/src/index.web.tsx +34 -1
package/README.md CHANGED
@@ -2,12 +2,50 @@
2
2
 
3
3
  [![npm version](https://img.shields.io/npm/v/react-native-platform-components.svg)](https://www.npmjs.com/package/react-native-platform-components)
4
4
  [![npm downloads](https://img.shields.io/npm/dm/react-native-platform-components.svg)](https://www.npmjs.com/package/react-native-platform-components)
5
+ [![CI](https://github.com/JarX-Concepts/react-native-platform-components/actions/workflows/ci.yml/badge.svg)](https://github.com/JarX-Concepts/react-native-platform-components/actions/workflows/ci.yml)
6
+ [![license](https://img.shields.io/npm/l/react-native-platform-components.svg)](./LICENSE)
5
7
 
6
- High-quality **native UI components for React Native**, implemented with platform-first APIs and exposed through clean, typed JavaScript interfaces.
8
+ Native **DatePicker**, **ContextMenu**, **SelectionMenu**, **SegmentedControl** and **LiquidGlass** for React Native. Every component is the real platform widget on both iOS and Android (UIKit and SwiftUI on iOS, Material 3 on Android), behind one typed, declarative API. No JavaScript re-implementations.
7
9
 
8
- This library focuses on **true native behavior**, not JavaScript re-implementations.
10
+ ```sh
11
+ npm install react-native-platform-components
12
+ ```
9
13
 
10
- **Have a component request?** If there's a native UI component you'd like to see added, [open an issue](https://github.com/JarX-Concepts/react-native-platform-components/issues/new) describing the component and its native APIs on iOS and Android.
14
+ ```tsx
15
+ import { SegmentedControl } from 'react-native-platform-components';
16
+
17
+ <SegmentedControl
18
+ segments={[
19
+ { label: 'Day', value: 'day' },
20
+ { label: 'Week', value: 'week' },
21
+ ]}
22
+ selectedValue={range}
23
+ onSelect={setRange}
24
+ />;
25
+ ```
26
+
27
+ That renders `UISegmentedControl` on iOS and Material 3 segmented buttons (`MaterialButtonToggleGroup`) on Android. The library needs the New Architecture: React Native 0.81+, or Expo SDK 54+ with a dev client (not Expo Go). See [Installation](#installation) and the [documentation site](https://jarx-concepts.github.io/react-native-platform-components).
28
+
29
+ ## Why this library
30
+
31
+ | You need | This library | Common alternative |
32
+ | --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
33
+ | Date and time pickers | `UIDatePicker` on iOS; `MaterialDatePicker` / `MaterialTimePicker` or the AppCompat dialogs on Android. Declarative `visible` prop, modal or embedded. | `@react-native-community/datetimepicker`: platform dialogs on Android; Material 3 pickers are an [open request](https://github.com/react-native-datetimepicker/datetimepicker/issues/790). |
34
+ | Segmented control | `UISegmentedControl` on iOS; Material 3 segmented buttons on Android. Icons and badges on both. | `@react-native-segmented-control/segmented-control`: native on iOS, drawn in JavaScript on Android. |
35
+ | Context menu | `UIContextMenuInteraction` on iOS; `PopupMenu` on Android. Long-press gesture or modal trigger, icons on both. | `zeego`: native on both platforms, through two additional native dependencies (`react-native-ios-context-menu`, `@react-native-menu/menu`). |
36
+ | Selection menu | System menus on iOS; Material exposed dropdown or `Spinner` on Android. Headless or inline. | `@react-native-picker/picker`: wheel picker on iOS, dialog or dropdown `Spinner` on Android; no menu-style presentation. |
37
+ | Liquid glass | `UIGlassEffect` on iOS 26+, a fallback `View` elsewhere, `isLiquidGlassSupported` flag. | `@callstack/liquid-glass`, `expo-glass-effect`: same idea on iOS; here it ships with the components above. |
38
+ | All of the above | One package, one API shape (platform-only props under `ios={{ }}` and `android={{ }}`), Fabric + Codegen typed bindings, Expo config plugin, TypeScript. | Four or five packages with different conventions, install steps and upgrade cadences. |
39
+
40
+ ## Components
41
+
42
+ | Component | iOS | Android | Docs |
43
+ | -------------------- | -------------------------- | ---------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
44
+ | **DatePicker** | `UIDatePicker` | `MaterialDatePicker` / `MaterialTimePicker` or AppCompat dialogs | [DatePicker](https://jarx-concepts.github.io/react-native-platform-components/components/datepicker) |
45
+ | **ContextMenu** | `UIContextMenuInteraction` | `PopupMenu` | [ContextMenu](https://jarx-concepts.github.io/react-native-platform-components/components/contextmenu) |
46
+ | **SelectionMenu** | System menus | Material exposed dropdown or `Spinner` | [SelectionMenu](https://jarx-concepts.github.io/react-native-platform-components/components/selectionmenu) |
47
+ | **SegmentedControl** | `UISegmentedControl` | `MaterialButtonToggleGroup` (Material 3 segmented buttons) | [SegmentedControl](https://jarx-concepts.github.io/react-native-platform-components/components/segmentedcontrol) |
48
+ | **LiquidGlass** | `UIGlassEffect` (iOS 26+) | Fallback `View` | [LiquidGlass](https://jarx-concepts.github.io/react-native-platform-components/components/liquidglass) |
11
49
 
12
50
  <table>
13
51
  <tr>
@@ -52,20 +90,9 @@ This library focuses on **true native behavior**, not JavaScript re-implementati
52
90
  </tr>
53
91
  </table>
54
92
 
55
- ### Components
56
-
57
- - **DatePicker** – native date & time pickers with modal and embedded presentations
58
- - **ContextMenu** – native context menus with long-press activation (UIContextMenuInteraction on iOS, PopupMenu on Android)
59
- - **SelectionMenu** – native selection menus (Material on Android, system menus on iOS)
60
- - **SegmentedControl** – native segmented controls (UISegmentedControl on iOS, MaterialButtonToggleGroup on Android)
61
- - **LiquidGlass** – iOS 26+ glass morphism effects (UIGlassEffect on iOS, fallback View on Android)
62
-
63
- ### Goals
93
+ **Have a component request?** If there's a native UI component you'd like to see added, [open an issue](https://github.com/JarX-Concepts/react-native-platform-components/issues/new) describing the component and its native APIs on iOS and Android.
64
94
 
65
- - Feel **100% native** on each platform
66
- - Support modern platform design systems (Material 3 on Android, system pickers on iOS)
67
- - Offer **headless** and **inline** modes for maximum layout control
68
- - Integrate cleanly with **React Native Codegen / Fabric**
95
+ **Using it in a shipped app?** Open a PR to list it here.
69
96
 
70
97
  ---
71
98
 
@@ -77,802 +104,11 @@ npm install react-native-platform-components
77
104
  yarn add react-native-platform-components
78
105
  ```
79
106
 
80
- ### iOS
107
+ **iOS:** `cd ios && pod install`. Nothing else to configure.
81
108
 
82
- ```sh
83
- cd ios
84
- pod install
85
- ```
86
-
87
- - Minimum iOS version: **iOS 13+**
88
- - Uses `UIDatePicker`, SwiftUI Menu, and `UIContextMenuInteraction`
89
-
90
- ### Android
91
-
92
- - Uses native Android Views with Material Design (including `PopupMenu` for context menus)
93
- - Supports **Material 3** styling
94
- - **⚠️ Your app may crash if theme is not configured** — See [Android Theme Configuration](#android-theme-configuration) below
95
-
96
- ### Expo (Managed Workflow)
97
-
98
- > **Note:** This library is **not supported in Expo Go**. It requires native code and must be used with [Expo Dev Client](https://docs.expo.dev/develop/development-builds/introduction/) or EAS Build.
99
-
100
- ```sh
101
- npx expo install react-native-platform-components
102
- npx expo prebuild
103
- npx expo run:ios
104
- # or
105
- npx expo run:android
106
- ```
107
-
108
- The library includes an Expo config plugin that handles all native configuration automatically. No manual native setup is required.
109
+ **Android:** nothing to configure. The components work with the default AppCompat app theme; give the app a Material 3 theme to have `SegmentedControl` and the Material pickers use your colors. See [Android Theme Configuration](https://jarx-concepts.github.io/react-native-platform-components/guides/android-theme).
109
110
 
110
- **EAS Build:**
111
-
112
- ```sh
113
- eas build --platform ios
114
- eas build --platform android
115
- ```
116
-
117
- **Config Plugin:**
118
-
119
- Add to your `app.json`:
120
-
121
- ```json
122
- {
123
- "expo": {
124
- "plugins": [["react-native-platform-components/app.plugin", {}]]
125
- }
126
- }
127
- ```
128
-
129
- For a complete working example, see the [`example-expo/`](./example-expo) directory.
130
-
131
- ---
132
-
133
- ## React Native New Architecture
134
-
135
- This library is built for the **React Native New Architecture** (Fabric + TurboModules).
136
-
137
- | Feature | Status |
138
- | --------------------- | ---------------------------------- |
139
- | Fabric (New Renderer) | Supported |
140
- | Codegen | Used for type-safe native bindings |
141
- | TurboModules | N/A (view components only) |
142
- | Old Architecture | Not supported |
143
-
144
- **Tested with:**
145
-
146
- - React Native 0.81+ (bare and Expo)
147
- - Expo SDK 54+
148
-
149
- **Requirements:**
150
-
151
- - New Architecture must be enabled in your app
152
- - For bare React Native: set `newArchEnabled=true` in `gradle.properties` (Android) and use the `RCT_NEW_ARCH_ENABLED` flag (iOS)
153
- - For Expo: set `"newArchEnabled": true` in `app.json`
154
-
155
- ---
156
-
157
- ## Quick Start
158
-
159
- ### DatePicker (Modal)
160
-
161
- ```tsx
162
- import { DatePicker } from 'react-native-platform-components';
163
-
164
- export function Example() {
165
- const [date, setDate] = React.useState<Date | null>(null);
166
- const [visible, setVisible] = React.useState(false);
167
-
168
- return (
169
- <>
170
- <Button title="Pick date" onPress={() => setVisible(true)} />
171
-
172
- <DatePicker
173
- date={date}
174
- visible={visible}
175
- presentation="modal"
176
- mode="date"
177
- onConfirm={(d, confirmed) => {
178
- setDate(d);
179
- if (confirmed) setVisible(false);
180
- }}
181
- onClosed={() => setVisible(false)}
182
- ios={{ preferredStyle: 'inline' }}
183
- android={{ material: 'system' }}
184
- />
185
- </>
186
- );
187
- }
188
- ```
189
-
190
- ### DatePicker (Embedded)
191
-
192
- ```tsx
193
- import { DatePicker } from 'react-native-platform-components';
194
-
195
- export function Example() {
196
- const [date, setDate] = React.useState<Date | null>(new Date());
197
-
198
- return (
199
- <DatePicker
200
- date={date}
201
- presentation="embedded"
202
- mode="date"
203
- onConfirm={(d, confirmed) => setDate(d)}
204
- ios={{ preferredStyle: 'inline' }}
205
- android={{ material: 'system' }}
206
- />
207
- );
208
- }
209
- ```
210
-
211
- ---
212
-
213
- ### ContextMenu (Gesture Mode)
214
-
215
- ```tsx
216
- import { ContextMenu } from 'react-native-platform-components';
217
- import { Platform, View, Text } from 'react-native';
218
-
219
- export function Example() {
220
- const [lastAction, setLastAction] = React.useState<string | null>(null);
221
-
222
- return (
223
- <ContextMenu
224
- title="Options"
225
- actions={[
226
- {
227
- id: 'copy',
228
- title: 'Copy',
229
- image: Platform.OS === 'ios' ? 'doc.on.doc' : 'content_copy',
230
- },
231
- {
232
- id: 'share',
233
- title: 'Share',
234
- image: Platform.OS === 'ios' ? 'square.and.arrow.up' : 'share',
235
- },
236
- {
237
- id: 'delete',
238
- title: 'Delete',
239
- image: Platform.OS === 'ios' ? 'trash' : 'delete',
240
- attributes: { destructive: true },
241
- },
242
- ]}
243
- onPressAction={(id, title) => setLastAction(title)}
244
- >
245
- <View
246
- style={{ padding: 20, backgroundColor: '#E8F4FD', borderRadius: 8 }}
247
- >
248
- <Text>Long-press me</Text>
249
- </View>
250
- </ContextMenu>
251
- );
252
- }
253
- ```
254
-
255
- ### ContextMenu (Modal Mode)
256
-
257
- ```tsx
258
- import { ContextMenu } from 'react-native-platform-components';
259
- import { View, Text } from 'react-native';
260
-
261
- export function Example() {
262
- return (
263
- <ContextMenu
264
- title="Actions"
265
- actions={[
266
- { id: 'edit', title: 'Edit' },
267
- { id: 'duplicate', title: 'Duplicate' },
268
- { id: 'delete', title: 'Delete', attributes: { destructive: true } },
269
- ]}
270
- trigger="tap" // or "longPress" (default)
271
- onPressAction={(id) => console.log('Selected:', id)}
272
- >
273
- <View style={{ padding: 16, backgroundColor: '#eee' }}>
274
- <Text>Tap or long-press me</Text>
275
- </View>
276
- </ContextMenu>
277
- );
278
- }
279
- ```
280
-
281
- ---
282
-
283
- ### SelectionMenu (Headless)
284
-
285
- ```tsx
286
- import { SelectionMenu } from 'react-native-platform-components';
287
-
288
- const options = [
289
- { label: 'Apple', data: 'apple' },
290
- { label: 'Banana', data: 'banana' },
291
- { label: 'Orange', data: 'orange' },
292
- ];
293
-
294
- export function Example() {
295
- const [visible, setVisible] = React.useState(false);
296
- const [value, setValue] = React.useState<string | null>(null);
297
-
298
- return (
299
- <>
300
- <Button title="Open menu" onPress={() => setVisible(true)} />
301
-
302
- <SelectionMenu
303
- options={options}
304
- selected={value}
305
- visible={visible}
306
- onSelect={(data) => {
307
- setValue(data);
308
- setVisible(false);
309
- }}
310
- onRequestClose={() => setVisible(false)}
311
- />
312
- </>
313
- );
314
- }
315
- ```
316
-
317
- ### SelectionMenu (Inline)
318
-
319
- ```tsx
320
- import { SelectionMenu } from 'react-native-platform-components';
321
-
322
- const options = [
323
- { label: 'Apple', data: 'apple' },
324
- { label: 'Banana', data: 'banana' },
325
- { label: 'Orange', data: 'orange' },
326
- ];
327
-
328
- export function Example() {
329
- const [value, setValue] = React.useState<string | null>(null);
330
-
331
- return (
332
- <SelectionMenu
333
- options={options}
334
- selected={value}
335
- presentation="embedded"
336
- placeholder="Select fruit"
337
- onSelect={(data) => setValue(data)}
338
- android={{ material: 'm3' }}
339
- />
340
- );
341
- }
342
- ```
343
-
344
- ---
345
-
346
- ### SegmentedControl
347
-
348
- ```tsx
349
- import { SegmentedControl } from 'react-native-platform-components';
350
-
351
- const segments = [
352
- { label: 'Day', value: 'day' },
353
- { label: 'Week', value: 'week' },
354
- { label: 'Month', value: 'month' },
355
- ];
356
-
357
- export function Example() {
358
- const [selected, setSelected] = React.useState('day');
359
-
360
- return (
361
- <SegmentedControl
362
- segments={segments}
363
- selectedValue={selected}
364
- onSelect={(value) => setSelected(value)}
365
- />
366
- );
367
- }
368
- ```
369
-
370
- ### SegmentedControl (With Icons)
371
-
372
- ```tsx
373
- import { SegmentedControl } from 'react-native-platform-components';
374
- import { Platform } from 'react-native';
375
-
376
- const segments = [
377
- {
378
- label: 'List',
379
- value: 'list',
380
- icon: Platform.OS === 'ios' ? 'list.bullet' : 'list_bullet',
381
- },
382
- {
383
- label: 'Grid',
384
- value: 'grid',
385
- icon: Platform.OS === 'ios' ? 'square.grid.2x2' : 'grid_view',
386
- },
387
- ];
388
-
389
- export function Example() {
390
- const [selected, setSelected] = React.useState('list');
391
-
392
- return (
393
- <SegmentedControl
394
- segments={segments}
395
- selectedValue={selected}
396
- onSelect={(value) => setSelected(value)}
397
- ios={{ apportionsSegmentWidthsByContent: true }}
398
- />
399
- );
400
- }
401
- ```
402
-
403
- ---
404
-
405
- ### LiquidGlass
406
-
407
- ```tsx
408
- import {
409
- LiquidGlass,
410
- isLiquidGlassSupported,
411
- } from 'react-native-platform-components';
412
- import { View, Text, Image } from 'react-native';
413
-
414
- export function Example() {
415
- return (
416
- <View style={{ flex: 1 }}>
417
- {/* Background content */}
418
- <Image
419
- source={{ uri: 'https://example.com/photo.jpg' }}
420
- style={{ flex: 1 }}
421
- />
422
-
423
- {/* Glass effect overlay */}
424
- <LiquidGlass
425
- style={{
426
- position: 'absolute',
427
- top: 50,
428
- left: 20,
429
- right: 20,
430
- padding: 20,
431
- }}
432
- cornerRadius={20}
433
- ios={{
434
- effect: 'regular',
435
- interactive: true,
436
- colorScheme: 'system',
437
- }}
438
- android={{
439
- fallbackBackgroundColor: '#FFFFFF80',
440
- }}
441
- >
442
- <Text style={{ fontSize: 18, fontWeight: '600' }}>
443
- {isLiquidGlassSupported ? 'Glass Effect!' : 'Fallback View'}
444
- </Text>
445
- </LiquidGlass>
446
- </View>
447
- );
448
- }
449
- ```
450
-
451
- ---
452
-
453
- ## Components
454
-
455
- ## DatePicker
456
-
457
- Native date & time picker using **platform system pickers**.
458
-
459
- ### Props
460
-
461
- | Prop | Type | Description |
462
- | -------------- | ------------------------------------------------------- | ---------------------------------------------------------------------------------- |
463
- | `date` | `Date \| null` | Controlled date value |
464
- | `minDate` | `Date \| null` | Minimum selectable date |
465
- | `maxDate` | `Date \| null` | Maximum selectable date |
466
- | `locale` | `string` | Locale identifier (e.g., `'en-US'`) |
467
- | `timeZoneName` | `string` | Time zone identifier |
468
- | `mode` | `'date' \| 'time' \| 'dateAndTime' \| 'countDownTimer'` | Picker mode |
469
- | `presentation` | `'modal' \| 'embedded'` | Presentation style |
470
- | `visible` | `boolean` | Controls modal visibility (modal mode only) |
471
- | `onConfirm` | `(date: Date, confirmed: boolean) => void` | Called on date change; `confirmed` is `true` for deliberate selections (see below) |
472
- | `onClosed` | `() => void` | Called when modal is dismissed |
473
-
474
- ### iOS Props (`ios`)
475
-
476
- | Prop | Type | Description |
477
- | -------------------------- | -------------------------------------------------- | ------------------------------------------------------------------------ |
478
- | `preferredStyle` | `'automatic' \| 'compact' \| 'inline' \| 'wheels'` | iOS date picker style |
479
- | `countDownDurationSeconds` | `number` | Duration for countdown timer mode |
480
- | `minuteInterval` | `number` | Minute interval (1-30) |
481
- | `roundsToMinuteInterval` | `'inherit' \| 'round' \| 'noRound'` | Rounding behavior |
482
- | `showConfirmToolbar` | `boolean` | Modal only. Show Cancel/Done toolbar below the picker. Defaults to `true`. See below. |
483
-
484
- ### Android Props (`android`)
485
-
486
- | Prop | Type | Description |
487
- | --------------------- | ------------------ | ---------------------------------------------------------------------- |
488
- | `firstDayOfWeek` | `number` | First day of week (1-7, Sunday=1) |
489
- | `material` | `'system' \| 'm3'` | Material Design style (modal only; embedded always uses system picker) |
490
- | `dialogTitle` | `string` | Custom dialog title |
491
- | `positiveButtonTitle` | `string` | Custom confirm button text |
492
- | `negativeButtonTitle` | `string` | Custom cancel button text |
493
-
494
- ### The `confirmed` Flag
495
-
496
- `onConfirm` fires on every date/time change, but the second argument (`confirmed`) lets you distinguish between browsing and deliberate selections:
497
-
498
- | Platform / Mode | Every change | Deliberate selection |
499
- | -------------------- | ----------------------------------------- | ------------------------------------- |
500
- | **iOS modal** | `confirmed: false` (user still adjusting) | `confirmed: true` (tapping **Done**) |
501
- | **iOS embedded** | `confirmed: true` | — |
502
- | **Android modal** | — | `confirmed: true` (pressing OK) |
503
- | **Android embedded** | `confirmed: true` | — |
504
-
505
- On iOS in modal presentation, the picker is shown in a popover with a Cancel/Done toolbar below it. Tapping **Done** emits `confirmed: true`; tapping **Cancel** or outside the popover calls `onClosed`. Set `ios.showConfirmToolbar: false` to hide the toolbar — in that mode `confirmed: true` never fires, and your app is expected to drive dismissal by flipping `visible` off (reading the current date from the stream of `confirmed: false` events). This only makes UX sense paired with `ios.preferredStyle: 'inline'`.
506
-
507
- A common pattern is to close the modal only on a confirmed selection:
508
-
509
- ```tsx
510
- <DatePicker
511
- date={date}
512
- visible={visible}
513
- presentation="modal"
514
- mode="time"
515
- onConfirm={(d, confirmed) => {
516
- setDate(d);
517
- if (confirmed) setVisible(false);
518
- }}
519
- onClosed={() => setVisible(false)}
520
- />
521
- ```
522
-
523
- ---
524
-
525
- ## ContextMenu
526
-
527
- Native context menu that wraps content and responds to **long-press** or **tap** gestures.
528
-
529
- ### Props
530
-
531
- | Prop | Type | Description |
532
- | --------------- | --------------------------------- | ------------------------------------------- |
533
- | `title` | `string` | Menu title (shown as header on iOS) |
534
- | `actions` | `ContextMenuAction[]` | Array of menu actions |
535
- | `disabled` | `boolean` | Disables the menu |
536
- | `trigger` | `'longPress' \| 'tap'` | How the menu opens (default: `'longPress'`) |
537
- | `onPressAction` | `(actionId, actionTitle) => void` | Called when user selects an action |
538
- | `onMenuOpen` | `() => void` | Called when menu opens |
539
- | `onMenuClose` | `() => void` | Called when menu closes |
540
- | `children` | `ReactNode` | Content to wrap (required) |
541
-
542
- ### ContextMenuAction
543
-
544
- | Property | Type | Description |
545
- | ------------ | -------------------------------------- | ------------------------------------------------- |
546
- | `id` | `string` | Unique identifier returned in callbacks |
547
- | `title` | `string` | Display text |
548
- | `subtitle` | `string` | Secondary text (iOS only) |
549
- | `image` | `string` | Icon name (SF Symbol on iOS, drawable on Android) |
550
- | `imageColor` | `string` | Tint color for the icon (hex string) |
551
- | `attributes` | `{ destructive?, disabled?, hidden? }` | Action attributes |
552
- | `state` | `'off' \| 'on' \| 'mixed'` | Checkmark state |
553
- | `subactions` | `ContextMenuAction[]` | Nested actions for submenu |
554
-
555
- ### iOS Props (`ios`)
556
-
557
- | Prop | Type | Description |
558
- | --------------- | --------- | --------------------------------- |
559
- | `enablePreview` | `boolean` | Enable preview when long-pressing |
560
-
561
- ### Android Props (`android`)
562
-
563
- | Prop | Type | Description |
564
- | ---------------- | ------------------- | ---------------------------------------------- |
565
- | `anchorPosition` | `'left' \| 'right'` | Anchor position for the popup menu |
566
- | `visible` | `boolean` | Programmatic visibility control (Android only) |
567
-
568
- ### Trigger Modes
569
-
570
- - **Long-Press** (default): Long-press on wrapped content triggers the menu.
571
- - **Tap** (`trigger="tap"`): Single tap on wrapped content triggers the menu.
572
- - **Programmatic** (Android only): Use `android.visible` to control menu visibility programmatically. iOS does not support programmatic menu opening due to platform limitations.
573
-
574
- ### Icon Support
575
-
576
- - **iOS**: Use SF Symbol names (e.g., `'trash'`, `'square.and.arrow.up'`, `'doc.on.doc'`)
577
- - **Android**: Use drawable resource names or Material icon names
578
-
579
- ---
580
-
581
- ## SelectionMenu
582
-
583
- Native selection menu with **modal** and **embedded** modes.
584
-
585
- ### Props
586
-
587
- | Prop | Type | Description |
588
- | ------------------ | ----------------------------------- | ----------------------------------------------- |
589
- | `options` | `{ label: string; data: string }[]` | Array of options to display |
590
- | `selected` | `string \| null` | Currently selected option's `data` value |
591
- | `disabled` | `boolean` | Disables the menu |
592
- | `placeholder` | `string` | Placeholder text when no selection |
593
- | `presentation` | `'modal' \| 'embedded'` | Presentation mode (default: `'modal'`) |
594
- | `visible` | `boolean` | Controls modal mode menu visibility |
595
- | `onSelect` | `(data, label, index) => void` | Called when user selects an option |
596
- | `onRequestClose` | `() => void` | Called when menu is dismissed without selection |
597
- | `android.material` | `'system' \| 'm3'` | Material Design style preference |
598
-
599
- ### Modes
600
-
601
- - **Modal mode** (default): Menu visibility controlled by `visible` prop. Use for custom trigger UI.
602
- - **Embedded mode** (`presentation="embedded"`): Native picker UI rendered inline. Menu managed internally.
603
-
604
- > **Note:** On iOS, modal mode uses a custom popover to enable programmatic presentation. For the full native menu experience (system animations, scroll physics), use embedded mode. This is an intentional trade-off: modal gives you control over the trigger UI, embedded gives you the complete system menu behavior.
605
-
606
- ---
607
-
608
- ## SegmentedControl
609
-
610
- Native segmented control using **UISegmentedControl** on iOS and **MaterialButtonToggleGroup** on Android.
611
-
612
- ### Props
613
-
614
- | Prop | Type | Description |
615
- | --------------- | ---------------------------------------- | ------------------------------------ |
616
- | `segments` | `SegmentedControlSegment[]` | Array of segments to display |
617
- | `selectedValue` | `string \| null` | Currently selected segment's `value` |
618
- | `disabled` | `boolean` | Disables the entire control |
619
- | `onSelect` | `(value: string, index: number) => void` | Called when user selects a segment |
620
-
621
- ### SegmentedControlSegment
622
-
623
- | Property | Type | Description |
624
- | ---------- | --------- | ------------------------------------------------- |
625
- | `label` | `string` | Display text for the segment |
626
- | `value` | `string` | Unique value returned in callbacks |
627
- | `disabled` | `boolean` | Disables this specific segment |
628
- | `icon` | `string` | Icon name (SF Symbol on iOS, drawable on Android) |
629
-
630
- ### iOS Props (`ios`)
631
-
632
- | Prop | Type | Description |
633
- | ---------------------------------- | --------- | --------------------------------------------------- |
634
- | `momentary` | `boolean` | If true, segments don't show selected state |
635
- | `apportionsSegmentWidthsByContent` | `boolean` | If true, segment widths are proportional to content |
636
- | `selectedSegmentTintColor` | `string` | Tint color for selected segment (hex string) |
637
-
638
- ### Android Props (`android`)
639
-
640
- | Prop | Type | Description |
641
- | ------------------- | --------- | -------------------------------------------- |
642
- | `selectionRequired` | `boolean` | If true, one segment must always be selected |
643
-
644
- ### Icon Support
645
-
646
- Icons work the same as ContextMenu:
647
-
648
- - **iOS**: Use SF Symbol names (e.g., `'list.bullet'`, `'square.grid.2x2'`)
649
- - **Android**: Use drawable resource names (e.g., `'list_bullet'`, `'grid_view'`)
650
-
651
- ---
652
-
653
- ## LiquidGlass
654
-
655
- Native glass morphism effect using **UIGlassEffect** on iOS 26+. On Android and older iOS versions, renders as a regular View with optional fallback styling.
656
-
657
- > **Note:** LiquidGlass requires **iOS 26+** (Xcode 16+). On older iOS versions and Android, the component renders children without the glass effect. Use `isLiquidGlassSupported` to check availability and provide fallback UI.
658
-
659
- ### Props
660
-
661
- | Prop | Type | Description |
662
- | -------------- | ----------- | ------------------------------------------------- |
663
- | `cornerRadius` | `number` | Corner radius for the glass effect (default: `0`) |
664
- | `children` | `ReactNode` | Content to render inside the glass container |
665
-
666
- ### iOS Props (`ios`)
667
-
668
- | Prop | Type | Description |
669
- | ------------- | -------------------------------- | ---------------------------------------------------- |
670
- | `effect` | `'clear' \| 'regular' \| 'none'` | Glass effect intensity (default: `'regular'`) |
671
- | `interactive` | `boolean` | Enable touch interaction feedback (default: `false`) |
672
- | `tintColor` | `string` | Overlay tint color (hex string) |
673
- | `colorScheme` | `'light' \| 'dark' \| 'system'` | Appearance mode (default: `'system'`) |
674
-
675
- ### Android Props (`android`)
676
-
677
- | Prop | Type | Description |
678
- | ------------------------- | -------- | ---------------------------------------------- |
679
- | `fallbackBackgroundColor` | `string` | Background color when glass effect unavailable |
680
-
681
- ### Constants
682
-
683
- | Export | Type | Description |
684
- | ------------------------ | --------- | ------------------------------------ |
685
- | `isLiquidGlassSupported` | `boolean` | `true` on iOS 26+, `false` otherwise |
686
-
687
- ### Effect Modes
688
-
689
- - **`'regular'`** (default): Standard glass blur intensity with full glass morphism effect
690
- - **`'clear'`**: More transparent, subtle glass effect
691
- - **`'none'`**: No glass effect (useful for animating materialization/dematerialization)
692
-
693
- ### Platform Behavior
694
-
695
- | Platform | iOS 26+ | iOS < 26 | Android |
696
- | ------------- | ------------------- | ----------- | ------------ |
697
- | Glass Effect | Full glass morphism | No effect | No effect |
698
- | Corner Radius | Applied | Applied | Applied |
699
- | Tint Color | Supported | Ignored | Ignored |
700
- | Interactive | Supported | Ignored | Ignored |
701
- | Fallback BG | N/A | Transparent | Configurable |
702
-
703
- ### Usage Tips
704
-
705
- 1. **Check support first**: Use `isLiquidGlassSupported` to conditionally render fallback UI
706
- 2. **Background content**: Glass effects work best over images or colorful backgrounds
707
- 3. **Interactive mode**: Only applies on mount; cannot be toggled after initial render
708
- 4. **Android fallback**: Set `android.fallbackBackgroundColor` for a semi-transparent background
709
-
710
- ---
711
-
712
- ## Design Philosophy
713
-
714
- - **Native first** — no JS re-implementation of pickers
715
- - **Headless-friendly** — works with any custom UI
716
- - **Codegen-safe** — string unions & sentinel values for type safety
717
- - **Predictable behavior** — no surprise re-renders or layout hacks
718
- - **Platform conventions** — respects native UX patterns
719
-
720
- ---
721
-
722
- ## Theming
723
-
724
- This library does not expose theming props. Components inherit their appearance from your app's native platform theme.
725
-
726
- - **iOS**: Components follow system appearance (light/dark mode) and use system-defined styles (e.g., `UIBlurEffect` for menu backgrounds). These are not customizable per-component.
727
- - **Android**: Components respect your app's Material Theme. Customize via your `styles.xml` or Material 3 theme configuration.
728
-
729
- This is intentional. The goal is native fidelity, not pixel-level customization. If you need custom styling beyond what the platform theme provides, this library may not be the right fit.
730
-
731
- ---
732
-
733
- ## Color Formats
734
-
735
- All color props in this library support the same formats as React Native's `backgroundColor`:
736
-
737
- | Format | Example | Description |
738
- | ------ | --------------------------------- | ---------------------------------- |
739
- | Hex | `#RGB`, `#RRGGBB`, `#RRGGBBAA` | Standard hex colors |
740
- | RGB | `rgb(255, 0, 0)` | RGB values (0-255) |
741
- | RGBA | `rgba(255, 0, 0, 0.5)` | RGB with alpha (0-1) |
742
- | HSL | `hsl(0, 100%, 50%)` | Hue (0-360), saturation, lightness |
743
- | HSLA | `hsla(0, 100%, 50%, 0.5)` | HSL with alpha (0-1) |
744
- | Named | `red`, `steelblue`, `transparent` | CSS named colors |
745
-
746
- **Props that accept colors:**
747
-
748
- - `ContextMenu`: `imageColor` (icon tint)
749
- - `SegmentedControl`: `ios.selectedSegmentTintColor`
750
- - `LiquidGlass`: `ios.tintColor`, `android.fallbackBackgroundColor`
751
-
752
- ```tsx
753
- // All of these are equivalent
754
- <ContextMenu actions={[{ id: '1', title: 'Red', imageColor: '#FF0000' }]} />
755
- <ContextMenu actions={[{ id: '1', title: 'Red', imageColor: 'rgb(255, 0, 0)' }]} />
756
- <ContextMenu actions={[{ id: '1', title: 'Red', imageColor: 'hsl(0, 100%, 50%)' }]} />
757
- <ContextMenu actions={[{ id: '1', title: 'Red', imageColor: 'red' }]} />
758
- ```
759
-
760
- ---
761
-
762
- ## Android Theme Configuration
763
-
764
- > **⚠️ Your app may hard crash if you skip this section.** Android components require specific theme configuration. Components can crash immediately on mount if the required theme attributes are missing.
765
-
766
- ### Theme Requirements by Component
767
-
768
- | Component | Mode | Required Theme | Crash if Missing |
769
- | -------------------- | ---------------------------- | ------------------- | ---------------- |
770
- | **SegmentedControl** | (always M3) | `Theme.Material3.*` | ✅ Yes |
771
- | **DatePicker** | `android.material: 'm3'` | `Theme.Material3.*` | ✅ Yes |
772
- | **DatePicker** | `android.material: 'system'` | `Theme.AppCompat.*` | ✅ Yes |
773
- | **SelectionMenu** | `android.material: 'm3'` | `Theme.Material3.*` | ✅ Yes |
774
- | **SelectionMenu** | `android.material: 'system'` | `Theme.AppCompat.*` | ✅ Yes |
775
- | **ContextMenu** | — | Any | ❌ No |
776
- | **LiquidGlass** | — | Any | ❌ No |
777
-
778
- ### Material 3 Theme Setup (Required for SegmentedControl)
779
-
780
- `SegmentedControl` always uses Material 3 widgets (`MaterialButtonToggleGroup`). Your app **must** use a Material 3 theme or the app will crash on component mount.
781
-
782
- **1. Update your app theme in `android/app/src/main/res/values/styles.xml`:**
783
-
784
- ```xml
785
- <resources>
786
- <!-- Base application theme - MUST inherit from Material3 -->
787
- <style name="AppTheme" parent="Theme.Material3.DayNight.NoActionBar">
788
- <!-- Material 3 requires these color attributes -->
789
- <item name="colorPrimary">@color/md_theme_primary</item>
790
- <item name="colorOnPrimary">@color/md_theme_onPrimary</item>
791
- <item name="colorPrimaryContainer">@color/md_theme_primaryContainer</item>
792
- <item name="colorOnPrimaryContainer">@color/md_theme_onPrimaryContainer</item>
793
- <item name="colorSecondary">@color/md_theme_secondary</item>
794
- <item name="colorOnSecondary">@color/md_theme_onSecondary</item>
795
- <item name="colorSecondaryContainer">@color/md_theme_secondaryContainer</item>
796
- <item name="colorOnSecondaryContainer">@color/md_theme_onSecondaryContainer</item>
797
- <item name="colorTertiary">@color/md_theme_tertiary</item>
798
- <item name="colorOnTertiary">@color/md_theme_onTertiary</item>
799
- <item name="colorBackground">@color/md_theme_background</item>
800
- <item name="colorOnBackground">@color/md_theme_onBackground</item>
801
- <item name="colorSurface">@color/md_theme_surface</item>
802
- <item name="colorOnSurface">@color/md_theme_onSurface</item>
803
- <item name="colorError">@color/md_theme_error</item>
804
- <item name="colorOnError">@color/md_theme_onError</item>
805
- </style>
806
- </resources>
807
- ```
808
-
809
- **2. Define your Material 3 colors in `android/app/src/main/res/values/colors.xml`:**
810
-
811
- ```xml
812
- <resources>
813
- <!-- Generate these using Material Theme Builder: https://m3.material.io/theme-builder -->
814
- <color name="md_theme_primary">#6750A4</color>
815
- <color name="md_theme_onPrimary">#FFFFFF</color>
816
- <color name="md_theme_primaryContainer">#EADDFF</color>
817
- <color name="md_theme_onPrimaryContainer">#21005D</color>
818
- <color name="md_theme_secondary">#625B71</color>
819
- <color name="md_theme_onSecondary">#FFFFFF</color>
820
- <color name="md_theme_secondaryContainer">#E8DEF8</color>
821
- <color name="md_theme_onSecondaryContainer">#1D192B</color>
822
- <color name="md_theme_tertiary">#7D5260</color>
823
- <color name="md_theme_onTertiary">#FFFFFF</color>
824
- <color name="md_theme_background">#FFFBFE</color>
825
- <color name="md_theme_onBackground">#1C1B1F</color>
826
- <color name="md_theme_surface">#FFFBFE</color>
827
- <color name="md_theme_onSurface">#1C1B1F</color>
828
- <color name="md_theme_error">#B3261E</color>
829
- <color name="md_theme_onError">#FFFFFF</color>
830
- </resources>
831
- ```
832
-
833
- > **Tip:** Use Google's [Material Theme Builder](https://m3.material.io/theme-builder) to generate a complete color scheme.
834
-
835
- ### Common Crash Scenarios
836
-
837
- #### Crash: `Cannot find theme attribute materialButtonOutlinedStyle`
838
-
839
- **Cause:** Using `SegmentedControl` without a Material 3 theme.
840
-
841
- **Fix:** Update your theme to inherit from `Theme.Material3.*`:
842
-
843
- ```xml
844
- <!-- Change this -->
845
- <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
846
-
847
- <!-- To this -->
848
- <style name="AppTheme" parent="Theme.Material3.DayNight.NoActionBar">
849
- ```
850
-
851
- #### Crash: `You need to use a Theme.AppCompat theme`
852
-
853
- **Cause:** Using `DatePicker` or `SelectionMenu` with `android.material: 'system'` while not extending AppCompat.
854
-
855
- **Fix:** Ensure your theme inherits from `Theme.AppCompat.*` or `Theme.Material3.*` (which extends AppCompat), and your `MainActivity` extends `AppCompatActivity`.
856
-
857
- ### Mode Selection Guide
858
-
859
- Choose the appropriate mode based on your app's theme:
860
-
861
- ```tsx
862
- // If your app uses Theme.Material3.* (recommended)
863
- <DatePicker android={{ material: 'm3' }} />
864
- <SelectionMenu android={{ material: 'm3' }} />
865
- <SegmentedControl /> // Always M3
866
-
867
- // If your app uses Theme.AppCompat.*
868
- <DatePicker android={{ material: 'system' }} />
869
- <SelectionMenu android={{ material: 'system' }} />
870
- // ⚠️ SegmentedControl will crash - upgrade to Material 3
871
- ```
872
-
873
- ### Expo Configuration
874
-
875
- For Expo projects, the config plugin can configure your theme automatically. Add to `app.json`:
111
+ **Expo:** needs a dev client or EAS Build (native code, so not Expo Go). The config plugin sets up the Material 3 theme for you:
876
112
 
877
113
  ```json
878
114
  {
@@ -880,106 +116,47 @@ For Expo projects, the config plugin can configure your theme automatically. Add
880
116
  "plugins": [
881
117
  [
882
118
  "react-native-platform-components/app.plugin",
883
- {
884
- "android": {
885
- "theme": "material3"
886
- }
887
- }
119
+ { "android": { "theme": "material3" } }
888
120
  ]
889
121
  ]
890
122
  }
891
123
  }
892
124
  ```
893
125
 
894
- Then run `npx expo prebuild` to apply the configuration.
895
-
896
- ---
897
-
898
- ## Icons
899
-
900
- ContextMenu supports icons on menu items. Icons are specified by name and resolved differently on each platform.
901
-
902
- ### iOS
903
-
904
- Use [SF Symbols](https://developer.apple.com/sf-symbols/) names. These are built into iOS and require no additional setup.
905
-
906
- ```tsx
907
- // Common SF Symbols
908
- image: 'doc.on.doc'; // Copy
909
- image: 'square.and.arrow.up'; // Share
910
- image: 'trash'; // Delete
911
- image: 'pencil'; // Edit
912
- image: 'checkmark.circle'; // Checkmark
913
- ```
914
-
915
- Browse available symbols using Apple's SF Symbols app or [sfsymbols.com](https://sfsymbols.com).
916
-
917
- ### Android
918
-
919
- Use drawable resource names from your app's `res/drawable` directory. You must add these resources yourself.
920
-
921
- ```tsx
922
- // Reference drawable by name (without extension)
923
- image: 'content_copy'; // res/drawable/content_copy.xml
924
- image: 'share'; // res/drawable/share.xml
925
- image: 'delete'; // res/drawable/delete.xml
126
+ ```sh
127
+ npx expo install react-native-platform-components
128
+ npx expo prebuild
129
+ npx expo run:ios # or run:android
926
130
  ```
927
131
 
928
- **Adding drawable resources:**
929
-
930
- 1. Create vector drawable XML files in `android/app/src/main/res/drawable/`
931
- 2. Use [Material Icons](https://fonts.google.com/icons) as a source — download SVG and convert to Android Vector Drawable
932
- 3. Name the file to match the `image` prop value (e.g., `content_copy.xml` for `image: 'content_copy'`)
132
+ The library is built for the New Architecture (Fabric + Codegen) and does not support the old architecture.
933
133
 
934
- Example vector drawable (`res/drawable/content_copy.xml`):
134
+ **Compatibility:**
935
135
 
936
- ```xml
937
- <vector xmlns:android="http://schemas.android.com/apk/res/android"
938
- android:width="24dp"
939
- android:height="24dp"
940
- android:viewportWidth="24"
941
- android:viewportHeight="24">
942
- <path
943
- android:fillColor="@android:color/white"
944
- android:pathData="M16,1L4,1c-1.1,0 -2,0.9 -2,2v14h2L4,3h12L16,1zM19,5L8,5c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h11c1.1,0 2,-0.9 2,-2L21,7c0,-1.1 -0.9,-2 -2,-2zM19,21L8,21L8,7h11v14z"/>
945
- </vector>
946
- ```
136
+ | Platform | Minimum |
137
+ | ------------ | --------------------------------------------------------- |
138
+ | React Native | 0.81 with the New Architecture enabled |
139
+ | Expo SDK | 54, with a dev client or EAS Build (not Expo Go) |
140
+ | React | 19 |
141
+ | iOS | 13 (LiquidGlass needs iOS 26) |
142
+ | Android | API 24 (Android 7.0); Material Components 1.12 is bundled |
947
143
 
948
- ### Cross-platform pattern
144
+ Full details: [Installation](https://jarx-concepts.github.io/react-native-platform-components/installation).
949
145
 
950
- Use `Platform.OS` to provide the correct icon name for each platform:
146
+ ## Documentation
951
147
 
952
- ```tsx
953
- import { Platform } from 'react-native';
954
-
955
- const actions = [
956
- {
957
- id: 'copy',
958
- title: 'Copy',
959
- image: Platform.OS === 'ios' ? 'doc.on.doc' : 'content_copy',
960
- },
961
- {
962
- id: 'share',
963
- title: 'Share',
964
- image: Platform.OS === 'ios' ? 'square.and.arrow.up' : 'share',
965
- },
966
- {
967
- id: 'delete',
968
- title: 'Delete',
969
- image: Platform.OS === 'ios' ? 'trash' : 'delete',
970
- attributes: { destructive: true },
971
- },
972
- ];
973
- ```
148
+ Everything else lives on the documentation site:
974
149
 
975
- ---
150
+ - [Quick Start](https://jarx-concepts.github.io/react-native-platform-components/quick-start): copy-paste examples for every component
151
+ - [DatePicker](https://jarx-concepts.github.io/react-native-platform-components/components/datepicker), [ContextMenu](https://jarx-concepts.github.io/react-native-platform-components/components/contextmenu), [SelectionMenu](https://jarx-concepts.github.io/react-native-platform-components/components/selectionmenu), [SegmentedControl](https://jarx-concepts.github.io/react-native-platform-components/components/segmentedcontrol), [LiquidGlass](https://jarx-concepts.github.io/react-native-platform-components/components/liquidglass): props, platform options and behavior
152
+ - [Android Theme Configuration](https://jarx-concepts.github.io/react-native-platform-components/guides/android-theme): Material 3 setup and what happens without it
153
+ - [Icons](https://jarx-concepts.github.io/react-native-platform-components/guides/icons): SF Symbols, drawables and images
154
+ - [Theming and Colors](https://jarx-concepts.github.io/react-native-platform-components/guides/theming): design philosophy, theming, accepted color formats
976
155
 
977
156
  ## Contributing
978
157
 
979
158
  See the [contributing guide](CONTRIBUTING.md) to learn how to contribute to the repository and the development workflow.
980
159
 
981
- **Have a component request?** If there's a native UI component you'd like to see added, [open an issue](https://github.com/JarX-Concepts/react-native-platform-components/issues/new) describing the component and its native APIs on iOS and Android.
982
-
983
160
  ## License
984
161
 
985
162
  MIT