@jobber/components-native 0.105.4-addeditor-cab44cf.11 → 0.106.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 (38) hide show
  1. package/dist/docs/ActionItem/ActionItem.md +1 -1
  2. package/dist/docs/ButtonGroup/ButtonGroup.md +2 -2
  3. package/dist/docs/Chip/Chip.md +4 -4
  4. package/dist/docs/EmptyState/EmptyState.md +1 -1
  5. package/dist/docs/Icon/Icon.md +2 -1
  6. package/dist/docs/IconButton/IconButton.md +1 -1
  7. package/dist/docs/usage-guidelines/usage-guidelines.md +5 -5
  8. package/dist/package.json +5 -3
  9. package/dist/src/primitives/Portal/index.js +5 -0
  10. package/dist/src/primitives/Select/SelectPrimitive.js +173 -0
  11. package/dist/src/primitives/Select/SelectPrimitive.style.js +112 -0
  12. package/dist/src/primitives/Select/SelectPrimitive.test.js +243 -0
  13. package/dist/src/primitives/Select/index.js +1 -0
  14. package/dist/src/primitives/Select/types.js +1 -0
  15. package/dist/src/primitives/index.js +2 -0
  16. package/dist/src/utils/test/PortalHostWrapper.js +11 -0
  17. package/dist/src/utils/test/index.js +1 -0
  18. package/dist/tsconfig.build.tsbuildinfo +1 -1
  19. package/dist/types/src/primitives/Portal/index.d.ts +1 -0
  20. package/dist/types/src/primitives/Select/SelectPrimitive.d.ts +67 -0
  21. package/dist/types/src/primitives/Select/SelectPrimitive.style.d.ts +105 -0
  22. package/dist/types/src/primitives/Select/SelectPrimitive.test.d.ts +1 -0
  23. package/dist/types/src/primitives/Select/index.d.ts +2 -0
  24. package/dist/types/src/primitives/Select/types.d.ts +41 -0
  25. package/dist/types/src/primitives/index.d.ts +2 -0
  26. package/dist/types/src/utils/test/PortalHostWrapper.d.ts +10 -0
  27. package/dist/types/src/utils/test/index.d.ts +1 -0
  28. package/package.json +5 -3
  29. package/src/primitives/Portal/index.ts +5 -0
  30. package/src/primitives/Select/SelectPrimitive.stories.tsx +221 -0
  31. package/src/primitives/Select/SelectPrimitive.style.ts +141 -0
  32. package/src/primitives/Select/SelectPrimitive.test.tsx +372 -0
  33. package/src/primitives/Select/SelectPrimitive.tsx +292 -0
  34. package/src/primitives/Select/index.ts +17 -0
  35. package/src/primitives/Select/types.ts +96 -0
  36. package/src/primitives/index.ts +2 -0
  37. package/src/utils/test/PortalHostWrapper.tsx +19 -0
  38. package/src/utils/test/index.ts +1 -0
@@ -59,7 +59,7 @@ entire contents of the ActionItem should be read as one element.
59
59
  | `actionIconColour` | `ActionIconColour` | No | `interactive` | Colour of the action icon |
60
60
  | `children` | `ReactNode` | No | — | Content to display. |
61
61
  | `icon` | `IconNames` | No | — | Name of the icon to display before content |
62
- | `iconColor` | `"task" | "text" | "warning" | "icon" | "white" | "grey" | "greyBlue" | "greyBlueDark" | "greyBlueLighter" | "blue" | "lightBlue" | "green" | "yellow" | "red" | "navy" | "orange" | ... 33 more ... | "brandHighlight"` | No | — | Colour of the icon displayed before content |
62
+ | `iconColor` | `"task" | "text" | "warning" | "icon" | "iconSecondary" | "white" | "grey" | "greyBlue" | "greyBlueDark" | "greyBlueLighter" | "blue" | "lightBlue" | "green" | "yellow" | "red" | ... 35 more ... | "brandHighlight"` | No | — | Colour of the icon displayed before content |
63
63
  | `onPress` | `() => void` | No | — | Press handler |
64
64
  | `testID` | `string` | No | `actionItem` | |
65
65
  | `title` | `string` | No | — | Title of the Action Item |
@@ -74,7 +74,7 @@ to match the height of the largest button.
74
74
  | `buttonVariation` | `ButtonVariation` | No | — | Themes the action button to the type of action it performs (default: "work") |
75
75
  | `customButton` | `ReactElement<unknown, string | JSXElementConstructor<any>>` | No | — | Optional custom button that can be rendered in place of the primary action button |
76
76
  | `icon` | `IconNames` | No | — | Icon to be displayed on the action button |
77
- | `iconColor` | `"task" | "text" | "warning" | "icon" | "white" | "grey" | "greyBlue" | "greyBlueDark" | "greyBlueLighter" | "blue" | "lightBlue" | "green" | "yellow" | "red" | "navy" | "orange" | ... 33 more ... | "brandHighlight"` | No | — | Determines the color of the icon. If not specified, some icons have a default system colour which will be used Others... |
77
+ | `iconColor` | `"task" | "text" | "warning" | "icon" | "iconSecondary" | "white" | "grey" | "greyBlue" | "greyBlueDark" | "greyBlueLighter" | "blue" | "lightBlue" | "green" | "yellow" | "red" | ... 35 more ... | "brandHighlight"` | No | — | Determines the color of the icon. If not specified, some icons have a default system colour which will be used Others... |
78
78
  | `loading` | `boolean` | No | — | |
79
79
 
80
80
  #### ButtonGroup.SecondaryAction
@@ -85,5 +85,5 @@ to match the height of the largest button.
85
85
  | `onPress` | `() => void` | Yes | — | Press handler for the action button |
86
86
  | `destructive` | `boolean` | No | — | Indicates whether the secondary action is destructive in nature. |
87
87
  | `icon` | `IconNames` | No | — | Icon to be displayed on the action button |
88
- | `iconColor` | `"task" | "text" | "warning" | "icon" | "white" | "grey" | "greyBlue" | "greyBlueDark" | "greyBlueLighter" | "blue" | "lightBlue" | "green" | "yellow" | "red" | "navy" | "orange" | ... 33 more ... | "brandHighlight"` | No | — | Determines the color of the icon. If not specified, some icons have a default system colour which will be used Others... |
88
+ | `iconColor` | `"task" | "text" | "warning" | "icon" | "iconSecondary" | "white" | "grey" | "greyBlue" | "greyBlueDark" | "greyBlueLighter" | "blue" | "lightBlue" | "green" | "yellow" | "red" | ... 35 more ... | "brandHighlight"` | No | — | Determines the color of the icon. If not specified, some icons have a default system colour which will be used Others... |
89
89
  | `loading` | `boolean` | No | — | |
@@ -4,7 +4,7 @@ Chip is a flexible component that can be used for
4
4
 
5
5
  * inline single- or multi-selection of items
6
6
  * triggering filtering and selection components like
7
- [Combobox](/components/Combobox)
7
+ [FilterPicker](/components/FilterPicker)
8
8
  * presenting grouped items that can be added or removed
9
9
 
10
10
  ```tsx
@@ -236,8 +236,8 @@ export function ChipInvalidExample(
236
236
 
237
237
  * [Chips](/components/Chips) is a convenience wrapper that offers the
238
238
  single-select, multi-select, and add/dismiss functionality "out of the box"
239
- * [Combobox](/components/Combobox) is most commonly triggered by a Chip, but is
240
- a separate component
239
+ * [FilterPicker](/components/FilterPicker) is most commonly triggered by a Chip,
240
+ but is a separate component
241
241
  * [Select](../Select/Select.md) is a simpler single-select "dropdown" that
242
242
  presents as a form element and should be preferred in forms
243
243
  * [RadioGroup](/components/RadioGroup) should be used to allow the user to
@@ -256,7 +256,7 @@ ideally 1–2 words. If any of the options in the group may have longer labels,
256
256
  consider Checkbox or Radio as necessary for your selection type.
257
257
 
258
258
  In cases where a Chip displays name of its selections, such as when used to
259
- trigger a Combobox or a date range selector, use the heading to identify the
259
+ trigger a FilterPicker or a date range selector, use the heading to identify the
260
260
  "category" and the label to identify the selected items.
261
261
 
262
262
  ## Accessibility
@@ -66,7 +66,7 @@ reflow to a second line if enough content is provided.
66
66
  |------|------|----------|---------|-------------|
67
67
  | `description` | `string` | No | — | Description of the empty state. |
68
68
  | `icon` | `IconNames` | No | — | Icon to display. |
69
- | `iconColor` | `"task" | "text" | "warning" | "icon" | "white" | "grey" | "greyBlue" | "greyBlueDark" | "greyBlueLighter" | "blue" | "lightBlue" | "green" | "yellow" | "red" | "navy" | "orange" | ... 33 more ... | "brandHighlight"` | No | `blue` | Color of Icon to display. |
69
+ | `iconColor` | `"task" | "text" | "warning" | "icon" | "iconSecondary" | "white" | "grey" | "greyBlue" | "greyBlueDark" | "greyBlueLighter" | "blue" | "lightBlue" | "green" | "yellow" | "red" | ... 35 more ... | "brandHighlight"` | No | `blue` | Color of Icon to display. |
70
70
  | `primaryAction` | `Action` | No | — | Handler for the primary action. |
71
71
  | `secondaryAction` | `Action` | No | — | Handler for the secondary action. |
72
72
  | `title` | `string` | No | — | Title of the empty state. |
@@ -415,6 +415,7 @@ export function IconSizesExample() {
415
415
  | | `export` |
416
416
  | | `filter` |
417
417
  | | `future` |
418
+ | | `history` |
418
419
  | | `import` |
419
420
  | | `redo` |
420
421
  | | `remove` |
@@ -582,7 +583,7 @@ necessary.
582
583
  | Prop | Type | Required | Default | Description |
583
584
  |------|------|----------|---------|-------------|
584
585
  | `name` | `IconNames` | Yes | — | The icon to show. |
585
- | `color` | `"task" | "text" | "warning" | "icon" | "white" | "grey" | "greyBlue" | "greyBlueDark" | "greyBlueLighter" | "blue" | "lightBlue" | "green" | "yellow" | "red" | "navy" | "orange" | ... 33 more ... | "brandHighlight"` | No | — | Determines the color of the icon. If not specified, some icons have a default system colour like quotes, jobs, and in... |
586
+ | `color` | `"task" | "text" | "warning" | "icon" | "iconSecondary" | "white" | "grey" | "greyBlue" | "greyBlueDark" | "greyBlueLighter" | "blue" | "lightBlue" | "green" | "yellow" | "red" | ... 35 more ... | "brandHighlight"` | No | — | Determines the color of the icon. If not specified, some icons have a default system colour like quotes, jobs, and in... |
586
587
  | `customColor` | `string` | No | — | Sets a custom color for the icon. Can be a rgb() or hex value. |
587
588
  | `size` | `"base" | "large" | "small"` | No | `base` | Changes the size to small or large. |
588
589
  | `testID` | `string` | No | — | Used to locate this view in end-to-end tests |
@@ -19,7 +19,7 @@ regarding which icons to use.
19
19
  | `accessibilityLabel` | `string` | Yes | — | Accessibilty label for the component. It's also used for testing |
20
20
  | `name` | `IconNames` | Yes | — | The icon to show. |
21
21
  | `badge` | `ReactNode` | No | — | a component that would render over the icon e.g. the number of notifications over the activity feed icon |
22
- | `color` | `"task" | "text" | "warning" | "icon" | "white" | "grey" | "greyBlue" | "greyBlueDark" | "greyBlueLighter" | "blue" | "lightBlue" | "green" | "yellow" | "red" | "navy" | "orange" | ... 33 more ... | "brandHighlight"` | No | — | Determines the color of the icon. If not specified, some icons have a default system colour like quotes, jobs, and in... |
22
+ | `color` | `"task" | "text" | "warning" | "icon" | "iconSecondary" | "white" | "grey" | "greyBlue" | "greyBlueDark" | "greyBlueLighter" | "blue" | "lightBlue" | "green" | "yellow" | "red" | ... 35 more ... | "brandHighlight"` | No | — | Determines the color of the icon. If not specified, some icons have a default system colour like quotes, jobs, and in... |
23
23
  | `customColor` | `string` | No | — | Sets a custom color for the icon. Can be a rgb() or hex value. |
24
24
  | `onPress` | `() => void` | No | — | Press handler |
25
25
  | `testID` | `string` | No | — | Used to locate this button in tests |
@@ -17,10 +17,10 @@ deprecated.
17
17
 
18
18
  ## Deprecated components — do not use
19
19
 
20
- | Deprecated | Replacement | Notes |
21
- | --------------------- | -------------------------------------------------- | ---------------------------------------- |
22
- | `MultiSelect` | `Autocomplete` with `multiple` prop, or `Combobox` | Fully deprecated, no longer supported. |
23
- | `Chips` (dismissible) | `Autocomplete` with `multiple` prop | Dismissible Chips variant is deprecated. |
20
+ | Deprecated | Replacement | Notes |
21
+ | --------------------- | ------------------------------------------------------ | ---------------------------------------- |
22
+ | `MultiSelect` | `Autocomplete` with `multiple` prop, or `FilterPicker` | Fully deprecated, no longer supported. |
23
+ | `Chips` (dismissible) | `Autocomplete` with `multiple` prop | Dismissible Chips variant is deprecated. |
24
24
 
25
25
  ### Deprecated props on still-supported components
26
26
 
@@ -77,7 +77,7 @@ parent reads its compound children to wire up state, accessibility, and styling.
77
77
  | `Modal` v2 | `Modal.Provider`, `Modal.Activator`, `Modal.Content`, `Modal.Header`, `Modal.Actions` | Wrap with `Modal.Provider`. `Modal.Header` and `Modal.Actions` must be **direct children** of `Modal.Content` for sticky behavior to work. Use `Modal.Activator` to control focus return when the trigger element unmounts. |
78
78
  | `Banner` | `Banner.Provider`, `Banner.Content`, `Banner.Icon`, `Banner.DismissButton`, `Banner.Action` | Either the simple `<Banner type="...">children</Banner>` form, or the Provider form: `Banner.Provider` > `Banner.Content` (+ optional `Banner.Icon` / `Banner.Action` / `Banner.DismissButton`). |
79
79
  | `Card` | `Card.Header`, `Card.Body` | `Card` > `Card.Header` + `Card.Body`. The legacy `header` string/element prop still works for simple cases. Use composition for any header that needs richer markup. |
80
- | `Combobox` | `Combobox.Activator`, `Combobox.Option`, `Combobox.Action` | `Combobox` > optional `Combobox.Activator`, one or more `Combobox.Option`, optional `Combobox.Action`. Omitting `Combobox.Activator` renders the default activator. |
80
+ | `FilterPicker` | `FilterPicker.Activator`, `FilterPicker.Option`, `FilterPicker.Action` | `FilterPicker` > optional `FilterPicker.Activator`, one or more `FilterPicker.Option`, optional `FilterPicker.Action`. Omitting `FilterPicker.Activator` renders the default activator. |
81
81
  | `DataTable` | `DataTable.Container`, `DataTable.Table`, `DataTable.Header`, `DataTable.HeaderCell`, `DataTable.SortableHeader`, `DataTable.Body`, `DataTable.Row`, `DataTable.Cell`, `DataTable.RowActions`, `DataTable.Actions`, `DataTable.Footer`, `DataTable.Pagination`, `DataTable.PaginationButton` | `DataTable.Footer` is a sibling of `DataTable.Body`, not a child. Place pagination outside the table (not inside the footer). For `layout="fixed"`, pass explicit widths via `style={{ width: "..." }}` on each `HeaderCell`. |
82
82
  | `Menu` (web composable) | `Menu.Trigger`, `Menu.Content`, `Menu.Section`, `Menu.Header`, `Menu.HeaderLabel`, `Menu.Item`, `Menu.ItemIcon`, `Menu.ItemLabel`, `Menu.Separator` | `Menu` > `Menu.Trigger` + `Menu.Content` containing `Menu.Item`s (optionally grouped in `Menu.Section`s). Each `Menu.Item` must include `textValue` for type-ahead and screen readers. |
83
83
  | `Page` | `Page.Header`, `Page.HeaderContent`, `Page.TitleBar`, `Page.Title`, `Page.Subtitle`, `Page.Intro`, `Page.Actions`, `Page.ActionPrimary`, `Page.ActionSecondary`, `Page.ActionMenu`, `Page.PrimaryButton`, `Page.SecondaryButton`, `Page.Menu`, `Page.Body` | Composable `Page` API: `Page` > `Page.Header` (containing `Page.HeaderContent` with `Page.TitleBar` > `Page.Title` / `Page.Subtitle`, and `Page.Actions` with `Page.ActionPrimary` / `Page.ActionSecondary` / `Page.ActionMenu`) + `Page.Body`. The legacy props-based API (`title`, `subtitle`, `intro`, etc.) still works. |
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jobber/components-native",
3
- "version": "0.105.4-addeditor-cab44cf.11+cab44cfa",
3
+ "version": "0.106.0",
4
4
  "license": "MIT",
5
5
  "description": "React Native implementation of Atlantis",
6
6
  "repository": {
@@ -58,6 +58,8 @@
58
58
  "dependencies": {
59
59
  "@react-native-clipboard/clipboard": "^1.11.2",
60
60
  "@react-native-picker/picker": "^2.4.10",
61
+ "@rn-primitives/portal": "^1.4.0",
62
+ "@rn-primitives/select": "^1.4.0",
61
63
  "autolinker": "^4.0.0",
62
64
  "deepmerge": "^4.2.2",
63
65
  "lodash": "^4.17.21",
@@ -71,7 +73,7 @@
71
73
  "devDependencies": {
72
74
  "@babel/runtime": "^7.29.2",
73
75
  "@gorhom/bottom-sheet": "^5.2.8",
74
- "@jobber/design": "0.103.1-addeditor-cab44cf.11+cab44cfa",
76
+ "@jobber/design": "0.105.0",
75
77
  "@jobber/hooks": "2.21.0",
76
78
  "@react-native-community/datetimepicker": "^8.4.5",
77
79
  "@react-native/babel-preset": "^0.82.1",
@@ -122,5 +124,5 @@
122
124
  "react-native-screens": ">=4.18.0",
123
125
  "react-native-svg": ">=12.0.0"
124
126
  },
125
- "gitHead": "cab44cfa1430ab6784636b2d3db8ad771db0999a"
127
+ "gitHead": "b13d0074cac7624ef3b8efa7e79e26697d9e15a6"
126
128
  }
@@ -0,0 +1,5 @@
1
+ // The portal host that backs every portal-based primitive (e.g. the Select
2
+ // dropdown). Apps mount one <AtlantisPortalHost/> at their root; it shares this
3
+ // package's bundled @rn-primitives/portal instance with the primitives' Portal,
4
+ // so registered overlays render in the host.
5
+ export { PortalHost as AtlantisPortalHost } from "@rn-primitives/portal";
@@ -0,0 +1,173 @@
1
+ var __rest = (this && this.__rest) || function (s, e) {
2
+ var t = {};
3
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
4
+ t[p] = s[p];
5
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
6
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
7
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
8
+ t[p[i]] = s[p[i]];
9
+ }
10
+ return t;
11
+ };
12
+ import React from "react";
13
+ import { StyleSheet } from "react-native";
14
+ import * as Primitive from "@rn-primitives/select";
15
+ import { SafeAreaInsetsContext } from "react-native-safe-area-context";
16
+ import { useStyles } from "./SelectPrimitive.style";
17
+ import { tokens as staticTokens } from "../../utils/design";
18
+ function SelectPrimitiveRoot(_a) {
19
+ var props = __rest(_a, []);
20
+ return React.createElement(Primitive.Root, Object.assign({}, props));
21
+ }
22
+ /**
23
+ * Styled trigger field. Renders only its `children` — compose
24
+ * `SelectPrimitive.Value` and any trailing icon (e.g. a chevron) here; the
25
+ * primitive provides no chevron of its own.
26
+ */
27
+ function SelectPrimitiveTrigger(_a) {
28
+ var { children, style, testID, invalid, onPressIn, onPressOut, ref } = _a, props = __rest(_a, ["children", "style", "testID", "invalid", "onPressIn", "onPressOut", "ref"]);
29
+ const styles = useStyles();
30
+ const { open, value, disabled: rootDisabled } = Primitive.useRootContext();
31
+ const [pressed, setPressed] = React.useState(false);
32
+ // `disabled` is Root-level; the primitive's Trigger won't read it from
33
+ // context, so resolve it here and pass it down to block interaction.
34
+ const isDisabled = rootDisabled !== null && rootDisabled !== void 0 ? rootDisabled : false;
35
+ const isInvalid = !isDisabled && (invalid !== null && invalid !== void 0 ? invalid : false);
36
+ // Announce the selected option as the trigger's value.
37
+ const accessibilityValue = (value === null || value === void 0 ? void 0 : value.label) ? { text: value.label } : undefined;
38
+ return (React.createElement(Primitive.Trigger, Object.assign({ ref: ref, testID: computeTriggerTestID(testID), disabled: isDisabled, accessibilityValue: accessibilityValue, onPressIn: event => {
39
+ setPressed(true);
40
+ onPressIn === null || onPressIn === void 0 ? void 0 : onPressIn(event);
41
+ }, onPressOut: event => {
42
+ setPressed(false);
43
+ onPressOut === null || onPressOut === void 0 ? void 0 : onPressOut(event);
44
+ }, style: [
45
+ styles.trigger,
46
+ pressed && !open && styles.triggerPressed,
47
+ open && styles.triggerOpen,
48
+ isInvalid && styles.triggerInvalid,
49
+ isDisabled && styles.triggerDisabled,
50
+ style,
51
+ ] }, props), children));
52
+ }
53
+ function computeTriggerTestID(testID) {
54
+ return testID ? `ATL-${testID}-Select-Trigger` : "ATL-Select-Trigger";
55
+ }
56
+ function SelectPrimitiveValue(_a) {
57
+ var { style } = _a, props = __rest(_a, ["style"]);
58
+ const styles = useStyles();
59
+ const { value, disabled } = Primitive.useRootContext();
60
+ const isEmpty = (value === null || value === void 0 ? void 0 : value.value) === undefined;
61
+ return (React.createElement(Primitive.Value, Object.assign({ style: [
62
+ styles.value,
63
+ isEmpty && styles.valuePlaceholder,
64
+ disabled && styles.valueDisabled,
65
+ style,
66
+ ] }, props)));
67
+ }
68
+ /** Portals the dropdown into the mounted `AtlantisPortalHost`. */
69
+ function SelectPrimitivePortal(_a) {
70
+ var props = __rest(_a, []);
71
+ return React.createElement(Primitive.Portal, Object.assign({}, props));
72
+ }
73
+ /** Tap-outside dismiss surface behind the dropdown (no scrim). */
74
+ function SelectPrimitiveOverlay(_a) {
75
+ var { style, testID = "ATL-Select-Overlay" } = _a, props = __rest(_a, ["style", "testID"]);
76
+ const styles = useStyles();
77
+ return (React.createElement(Primitive.Overlay, Object.assign({ testID: testID, style: StyleSheet.flatten([styles.overlay, style]) }, props)));
78
+ }
79
+ /**
80
+ * Anchored dropdown surface: matches the trigger width, applies safe-area
81
+ * insets, and flips above the trigger when space is tight. Compose it inside
82
+ * `Portal`, alongside `Overlay`, wrapping the items in a `Viewport`.
83
+ */
84
+ function SelectPrimitiveContent(_a) {
85
+ var _b;
86
+ var { children, style, sideOffset = staticTokens["space-smaller"], insets, ref } = _a, props = __rest(_a, ["children", "style", "sideOffset", "insets", "ref"]);
87
+ const styles = useStyles();
88
+ // Read the context directly, not `useSafeAreaInsets` (which throws without a
89
+ // provider): `Content` renders at the portal host, which may sit outside one.
90
+ const safeAreaInsets = (_b = React.useContext(SafeAreaInsetsContext)) !== null && _b !== void 0 ? _b : undefined;
91
+ const { triggerPosition } = Primitive.useRootContext();
92
+ return (React.createElement(Primitive.Content, Object.assign({ ref: ref, sideOffset: sideOffset, insets: insets !== null && insets !== void 0 ? insets : safeAreaInsets, style: StyleSheet.flatten([
93
+ styles.content,
94
+ triggerPosition ? { width: triggerPosition.width } : undefined,
95
+ style,
96
+ ]) }, props), children));
97
+ }
98
+ /** Scroll container for the items (a no-op passthrough on native). */
99
+ function SelectPrimitiveViewport(_a) {
100
+ var props = __rest(_a, []);
101
+ return React.createElement(Primitive.Viewport, Object.assign({}, props));
102
+ }
103
+ /**
104
+ * Styled, pressable option row. Compose its content from `SelectPrimitive.ItemText`
105
+ * and `SelectPrimitive.ItemIndicator` (and anything else) as `children`.
106
+ */
107
+ function SelectPrimitiveItem(_a) {
108
+ var { style, disabled, ref } = _a, props = __rest(_a, ["style", "disabled", "ref"]);
109
+ const styles = useStyles();
110
+ return (React.createElement(Primitive.Item, Object.assign({ ref: ref, disabled: disabled, style: ({ pressed }) => [
111
+ styles.item,
112
+ pressed && styles.itemPressed,
113
+ style,
114
+ ] }, props)));
115
+ }
116
+ /**
117
+ * The option label as styled text (reads the label from the item context). The
118
+ * `disabled` flag is explicit — the composing layer (e.g. the sugared
119
+ * `Select.Item`) forwards the row's disabled state to grey the text.
120
+ */
121
+ function SelectPrimitiveItemText(_a) {
122
+ var { style, disabled, ref } = _a, props = __rest(_a, ["style", "disabled", "ref"]);
123
+ const styles = useStyles();
124
+ return (React.createElement(Primitive.ItemText, Object.assign({ ref: ref, style: [styles.itemText, disabled && styles.itemTextDisabled, style] }, props)));
125
+ }
126
+ /**
127
+ * The selected-state marker slot. Renders its `children` (the marker, e.g. a
128
+ * checkmark) on the selected row only — it self-hides on unselected rows. The
129
+ * marker glyph is supplied by the composing layer, not defaulted here.
130
+ */
131
+ function SelectPrimitiveItemIndicator(_a) {
132
+ var { style, ref } = _a, props = __rest(_a, ["style", "ref"]);
133
+ const styles = useStyles();
134
+ return (React.createElement(Primitive.ItemIndicator, Object.assign({ ref: ref, style: [styles.itemIndicator, style] }, props)));
135
+ }
136
+ /**
137
+ * Groups related options, typically with a `SelectPrimitive.Label` heading.
138
+ */
139
+ function SelectPrimitiveGroup(_a) {
140
+ var props = __rest(_a, []);
141
+ return React.createElement(Primitive.Group, Object.assign({}, props));
142
+ }
143
+ /**
144
+ * A styled group heading rendered inside `SelectPrimitive.Group`.
145
+ */
146
+ function SelectPrimitiveLabel(_a) {
147
+ var { style, ref } = _a, props = __rest(_a, ["style", "ref"]);
148
+ const styles = useStyles();
149
+ return (React.createElement(Primitive.Label, Object.assign({ ref: ref, style: [styles.groupLabel, style] }, props)));
150
+ }
151
+ /**
152
+ * A styled divider between groups or options.
153
+ */
154
+ function SelectPrimitiveSeparator(_a) {
155
+ var { style, ref } = _a, props = __rest(_a, ["style", "ref"]);
156
+ const styles = useStyles();
157
+ return (React.createElement(Primitive.Separator, Object.assign({ ref: ref, style: [styles.separator, style] }, props)));
158
+ }
159
+ export const SelectPrimitive = {
160
+ Root: SelectPrimitiveRoot,
161
+ Trigger: SelectPrimitiveTrigger,
162
+ Value: SelectPrimitiveValue,
163
+ Portal: SelectPrimitivePortal,
164
+ Overlay: SelectPrimitiveOverlay,
165
+ Content: SelectPrimitiveContent,
166
+ Viewport: SelectPrimitiveViewport,
167
+ Item: SelectPrimitiveItem,
168
+ ItemText: SelectPrimitiveItemText,
169
+ ItemIndicator: SelectPrimitiveItemIndicator,
170
+ Group: SelectPrimitiveGroup,
171
+ Label: SelectPrimitiveLabel,
172
+ Separator: SelectPrimitiveSeparator,
173
+ };
@@ -0,0 +1,112 @@
1
+ import { buildThemedStyles } from "../../AtlantisThemeContext";
2
+ import { getTypographyStyles } from "../../Typography";
3
+ import { tokens as staticTokens } from "../../utils/design";
4
+ const baseLineHeight = staticTokens["typography--lineHeight-base"];
5
+ export const useStyles = buildThemedStyles(tokens => {
6
+ const typographyStyles = getTypographyStyles(tokens);
7
+ // The dark theme merges a web CSS-string `shadow-base` over the native object
8
+ // shadow, leaving stray indexed keys on the value. Pick only the React Native
9
+ // shadow properties so those keys never reach the style (spreading them
10
+ // breaks style application through the dropdown's portal on react-native-web).
11
+ const shadowBase = tokens["shadow-base"];
12
+ const contentShadow = {
13
+ shadowColor: shadowBase.shadowColor,
14
+ shadowOffset: shadowBase.shadowOffset,
15
+ shadowOpacity: shadowBase.shadowOpacity,
16
+ shadowRadius: shadowBase.shadowRadius,
17
+ elevation: shadowBase.elevation,
18
+ };
19
+ return {
20
+ trigger: {
21
+ flexDirection: "row",
22
+ alignItems: "center",
23
+ gap: tokens["space-small"],
24
+ minHeight: tokens["space-largest"] + tokens["space-small"],
25
+ paddingHorizontal: tokens["space-slim"],
26
+ backgroundColor: tokens["color-surface"],
27
+ borderWidth: tokens["border-base"],
28
+ borderColor: tokens["color-border--interactive"],
29
+ borderRadius: tokens["radius-base"],
30
+ },
31
+ triggerOpen: {
32
+ borderWidth: tokens["border-thick"],
33
+ borderColor: tokens["color-interactive--subtle"],
34
+ // Keep the content from shifting when the border thickens.
35
+ paddingHorizontal: tokens["space-slim"] - (tokens["border-thick"] - tokens["border-base"]),
36
+ },
37
+ triggerPressed: {
38
+ borderWidth: tokens["border-thick"],
39
+ borderColor: tokens["color-border--interactive"],
40
+ paddingHorizontal: tokens["space-slim"] - (tokens["border-thick"] - tokens["border-base"]),
41
+ },
42
+ // Critical sets only the colour; width follows the open/pressed state.
43
+ triggerInvalid: {
44
+ borderColor: tokens["color-critical"],
45
+ },
46
+ triggerDisabled: {
47
+ backgroundColor: tokens["color-disabled--secondary"],
48
+ },
49
+ value: {
50
+ flex: 1,
51
+ color: tokens["color-text"],
52
+ fontFamily: typographyStyles.baseRegularRegular.fontFamily,
53
+ fontSize: typographyStyles.defaultSize.fontSize,
54
+ lineHeight: baseLineHeight,
55
+ letterSpacing: typographyStyles.baseLetterSpacing.letterSpacing,
56
+ },
57
+ valuePlaceholder: {
58
+ color: tokens["color-text--secondary"],
59
+ },
60
+ valueDisabled: {
61
+ color: tokens["color-disabled"],
62
+ },
63
+ overlay: {
64
+ position: "absolute",
65
+ top: 0,
66
+ right: 0,
67
+ bottom: 0,
68
+ left: 0,
69
+ },
70
+ content: Object.assign({ backgroundColor: tokens["color-surface"], borderWidth: tokens["border-base"], borderColor: tokens["color-border"], borderRadius: tokens["radius-base"], padding: tokens["space-small"] }, contentShadow),
71
+ item: {
72
+ flexDirection: "row",
73
+ alignItems: "center",
74
+ gap: tokens["space-small"],
75
+ minHeight: tokens["space-largest"] + tokens["space-small"],
76
+ padding: tokens["space-small"],
77
+ borderRadius: tokens["radius-small"],
78
+ },
79
+ itemPressed: {
80
+ backgroundColor: tokens["color-surface--hover"],
81
+ },
82
+ itemText: {
83
+ flex: 1,
84
+ color: tokens["color-text"],
85
+ fontFamily: typographyStyles.baseRegularSemiBold.fontFamily,
86
+ fontSize: typographyStyles.defaultSize.fontSize,
87
+ lineHeight: baseLineHeight,
88
+ letterSpacing: typographyStyles.baseLetterSpacing.letterSpacing,
89
+ },
90
+ itemTextDisabled: {
91
+ color: tokens["color-disabled"],
92
+ },
93
+ itemIndicator: {
94
+ justifyContent: "center",
95
+ alignItems: "center",
96
+ },
97
+ groupLabel: {
98
+ color: tokens["color-text--secondary"],
99
+ fontFamily: typographyStyles.baseRegularRegular.fontFamily,
100
+ fontSize: tokens["typography--fontSize-small"],
101
+ lineHeight: tokens["typography--lineHeight-tight"],
102
+ paddingTop: tokens["space-small"],
103
+ paddingBottom: tokens["space-smaller"],
104
+ paddingHorizontal: tokens["space-small"],
105
+ },
106
+ separator: {
107
+ height: tokens["border-base"],
108
+ backgroundColor: tokens["color-border"],
109
+ marginVertical: tokens["space-small"],
110
+ },
111
+ };
112
+ });