@impulse-ui-native/select 8.2.0 → 8.3.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.
package/README.md CHANGED
@@ -5,7 +5,7 @@ Single- and multi-value select controls that present their options in a themed f
5
5
  ## Installation
6
6
 
7
7
  ```sh
8
- pnpm add @impulse-ui-native/select @shopify/flash-list react-native-gesture-handler react-native-reanimated react-native-safe-area-context react-native-worklets
8
+ pnpm add @impulse-ui-native/select react-native-gesture-handler react-native-reanimated react-native-safe-area-context react-native-worklets
9
9
  ```
10
10
 
11
11
  Complete the Gesture Handler, Reanimated, Worklets, and Safe Area Context setup required by your React Native or Expo project. The simplest application setup is to use `ThemeProvider`, wrap the app with `GestureHandlerRootView` and `SafeAreaProvider`, and mount one `PortalsHost` inside a `PortalProvider` at the application root.
@@ -54,3 +54,5 @@ export function DepartmentField() {
54
54
  ```
55
55
 
56
56
  Both controls support controlled `value` and uncontrolled `defaultValue` usage. Values are limited to strings, numbers, `null`, and `undefined`; multi-select stores an array of those values.
57
+
58
+ On each opening, Select reveals its selected option. MultiSelect reveals the first selected option in list order. Options are single-line rows with a fixed `theme.components.select.option.height` (56 by default). The same height is supplied to native `getItemLayout`, so native `initialScrollIndex` handles positioning. Long labels truncate at the end. Selection changes while open do not change the opening target. Set `initialScrollToSelected={false}` to retain the normal starting position.
@@ -21,7 +21,15 @@ function SelectedTagComponent(props) {
21
21
  }
22
22
  const SelectedTag = memo(SelectedTagComponent);
23
23
  function MultiSelectComponent(props) {
24
- const { options, value, defaultValue, onChange, placeholder, ...rest } = props;
24
+ const {
25
+ options,
26
+ value,
27
+ defaultValue,
28
+ onChange,
29
+ placeholder,
30
+ initialScrollToSelected,
31
+ ...rest
32
+ } = props;
25
33
  const tokens = useComponentsTokens();
26
34
  const selectTokens = tokens.select;
27
35
  const id = useId();
@@ -61,6 +69,7 @@ function MultiSelectComponent(props) {
61
69
  title: "Options",
62
70
  open: isOpen,
63
71
  options,
72
+ initialScrollToSelected,
64
73
  isSelected,
65
74
  onCloseFinished: close,
66
75
  onSelect: select
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/multi-select.tsx"],"sourcesContent":["import { memo, ReactElement, useId } from \"react\";\n\nimport { useEventCallback, useIsOpen } from \"@impulse-ui-native/core\";\nimport { Control, Tag, View } from \"@impulse-ui-native/primitives\";\nimport { useComponentsTokens } from \"@impulse-ui-native/theme\";\n\nimport { useMultiSelect } from \"../hooks/use-multi-select.hook\";\nimport { MultiSelectProps, PrimitiveValue } from \"../types\";\nimport { SelectControl } from \"./select-control\";\nimport { SelectFlyout } from \"./select.flyout\";\n\ninterface SelectedTagProps<Value extends PrimitiveValue> {\n value: Value;\n label: string;\n size: MultiSelectProps<Value>[\"size\"];\n onSelect: (value: Value) => void;\n}\n\nfunction SelectedTagComponent<Value extends PrimitiveValue>(\n props: SelectedTagProps<Value>,\n) {\n const handleClose = useEventCallback(() => props.onSelect(props.value));\n\n return (\n <Tag\n variant=\"filled\"\n size={props.size}\n closable\n onClose={handleClose}\n label={props.label}\n />\n );\n}\n\nconst SelectedTag = memo(SelectedTagComponent) as <\n Value extends PrimitiveValue,\n>(\n props: SelectedTagProps<Value>,\n) => ReactElement | null;\n\nfunction MultiSelectComponent<Value extends PrimitiveValue>(\n props: MultiSelectProps<Value>,\n) {\n const { options, value, defaultValue, onChange, placeholder, ...rest } =\n props;\n\n const tokens = useComponentsTokens();\n\n const selectTokens = tokens.select;\n\n const id = useId();\n\n const { isOpen, open, close } = useIsOpen();\n\n const { selected, hasSelected, select, isSelected, getLabel } =\n useMultiSelect({\n options,\n value,\n defaultValue,\n onChange,\n });\n\n return (\n <SelectControl {...rest} onPress={open}>\n {!hasSelected ? (\n <Control.Placeholder>{placeholder}</Control.Placeholder>\n ) : null}\n {hasSelected ? (\n <View\n flex={1}\n flexDirection=\"row\"\n gap={selectTokens.multiValueGap}\n marginHorizontal={selectTokens.multiValueMarginHorizontal}\n overflow=\"hidden\"\n >\n {selected\n ? selected.map((value) => (\n <SelectedTag\n size={props.size}\n key={value}\n label={String(getLabel(value))}\n value={value}\n onSelect={select}\n />\n ))\n : null}\n </View>\n ) : null}\n <SelectFlyout\n id={id}\n title=\"Options\"\n open={isOpen}\n options={options}\n isSelected={isSelected}\n onCloseFinished={close}\n onSelect={select}\n />\n </SelectControl>\n );\n}\n\nexport const MultiSelect = memo(MultiSelectComponent) as <\n Value extends PrimitiveValue,\n>(\n props: MultiSelectProps<Value>,\n) => ReactElement | null;\n"],"mappings":"AAwBI,cAuCA,YAvCA;AAxBJ,SAAS,MAAoB,aAAa;AAE1C,SAAS,kBAAkB,iBAAiB;AAC5C,SAAS,SAAS,KAAK,YAAY;AACnC,SAAS,2BAA2B;AAEpC,SAAS,sBAAsB;AAE/B,SAAS,qBAAqB;AAC9B,SAAS,oBAAoB;AAS7B,SAAS,qBACP,OACA;AACA,QAAM,cAAc,iBAAiB,MAAM,MAAM,SAAS,MAAM,KAAK,CAAC;AAEtE,SACE;AAAA,IAAC;AAAA;AAAA,MACC,SAAQ;AAAA,MACR,MAAM,MAAM;AAAA,MACZ,UAAQ;AAAA,MACR,SAAS;AAAA,MACT,OAAO,MAAM;AAAA;AAAA,EACf;AAEJ;AAEA,MAAM,cAAc,KAAK,oBAAoB;AAM7C,SAAS,qBACP,OACA;AACA,QAAM,EAAE,SAAS,OAAO,cAAc,UAAU,aAAa,GAAG,KAAK,IACnE;AAEF,QAAM,SAAS,oBAAoB;AAEnC,QAAM,eAAe,OAAO;AAE5B,QAAM,KAAK,MAAM;AAEjB,QAAM,EAAE,QAAQ,MAAM,MAAM,IAAI,UAAU;AAE1C,QAAM,EAAE,UAAU,aAAa,QAAQ,YAAY,SAAS,IAC1D,eAAe;AAAA,IACb;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAEH,SACE,qBAAC,iBAAe,GAAG,MAAM,SAAS,MAC/B;AAAA,KAAC,cACA,oBAAC,QAAQ,aAAR,EAAqB,uBAAY,IAChC;AAAA,IACH,cACC;AAAA,MAAC;AAAA;AAAA,QACC,MAAM;AAAA,QACN,eAAc;AAAA,QACd,KAAK,aAAa;AAAA,QAClB,kBAAkB,aAAa;AAAA,QAC/B,UAAS;AAAA,QAER,qBACG,SAAS,IAAI,CAACA,WACZ;AAAA,UAAC;AAAA;AAAA,YACC,MAAM,MAAM;AAAA,YAEZ,OAAO,OAAO,SAASA,MAAK,CAAC;AAAA,YAC7B,OAAOA;AAAA,YACP,UAAU;AAAA;AAAA,UAHLA;AAAA,QAIP,CACD,IACD;AAAA;AAAA,IACN,IACE;AAAA,IACJ;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,OAAM;AAAA,QACN,MAAM;AAAA,QACN;AAAA,QACA;AAAA,QACA,iBAAiB;AAAA,QACjB,UAAU;AAAA;AAAA,IACZ;AAAA,KACF;AAEJ;AAEO,MAAM,cAAc,KAAK,oBAAoB;","names":["value"]}
1
+ {"version":3,"sources":["../../src/components/multi-select.tsx"],"sourcesContent":["import { memo, ReactElement, useId } from \"react\";\n\nimport { useEventCallback, useIsOpen } from \"@impulse-ui-native/core\";\nimport { Control, Tag, View } from \"@impulse-ui-native/primitives\";\nimport { useComponentsTokens } from \"@impulse-ui-native/theme\";\n\nimport { useMultiSelect } from \"../hooks/use-multi-select.hook\";\nimport { MultiSelectProps, PrimitiveValue } from \"../types\";\nimport { SelectControl } from \"./select-control\";\nimport { SelectFlyout } from \"./select.flyout\";\n\ninterface SelectedTagProps<Value extends PrimitiveValue> {\n value: Value;\n label: string;\n size: MultiSelectProps<Value>[\"size\"];\n onSelect: (value: Value) => void;\n}\n\nfunction SelectedTagComponent<Value extends PrimitiveValue>(\n props: SelectedTagProps<Value>,\n) {\n const handleClose = useEventCallback(() => props.onSelect(props.value));\n\n return (\n <Tag\n variant=\"filled\"\n size={props.size}\n closable\n onClose={handleClose}\n label={props.label}\n />\n );\n}\n\nconst SelectedTag = memo(SelectedTagComponent) as <\n Value extends PrimitiveValue,\n>(\n props: SelectedTagProps<Value>,\n) => ReactElement | null;\n\nfunction MultiSelectComponent<Value extends PrimitiveValue>(\n props: MultiSelectProps<Value>,\n) {\n const {\n options,\n value,\n defaultValue,\n onChange,\n placeholder,\n initialScrollToSelected,\n ...rest\n } = props;\n\n const tokens = useComponentsTokens();\n\n const selectTokens = tokens.select;\n\n const id = useId();\n\n const { isOpen, open, close } = useIsOpen();\n\n const { selected, hasSelected, select, isSelected, getLabel } =\n useMultiSelect({\n options,\n value,\n defaultValue,\n onChange,\n });\n\n return (\n <SelectControl {...rest} onPress={open}>\n {!hasSelected ? (\n <Control.Placeholder>{placeholder}</Control.Placeholder>\n ) : null}\n {hasSelected ? (\n <View\n flex={1}\n flexDirection=\"row\"\n gap={selectTokens.multiValueGap}\n marginHorizontal={selectTokens.multiValueMarginHorizontal}\n overflow=\"hidden\"\n >\n {selected\n ? selected.map((value) => (\n <SelectedTag\n size={props.size}\n key={value}\n label={String(getLabel(value))}\n value={value}\n onSelect={select}\n />\n ))\n : null}\n </View>\n ) : null}\n <SelectFlyout\n id={id}\n title=\"Options\"\n open={isOpen}\n options={options}\n initialScrollToSelected={initialScrollToSelected}\n isSelected={isSelected}\n onCloseFinished={close}\n onSelect={select}\n />\n </SelectControl>\n );\n}\n\nexport const MultiSelect = memo(MultiSelectComponent) as <\n Value extends PrimitiveValue,\n>(\n props: MultiSelectProps<Value>,\n) => ReactElement | null;\n"],"mappings":"AAwBI,cA8CA,YA9CA;AAxBJ,SAAS,MAAoB,aAAa;AAE1C,SAAS,kBAAkB,iBAAiB;AAC5C,SAAS,SAAS,KAAK,YAAY;AACnC,SAAS,2BAA2B;AAEpC,SAAS,sBAAsB;AAE/B,SAAS,qBAAqB;AAC9B,SAAS,oBAAoB;AAS7B,SAAS,qBACP,OACA;AACA,QAAM,cAAc,iBAAiB,MAAM,MAAM,SAAS,MAAM,KAAK,CAAC;AAEtE,SACE;AAAA,IAAC;AAAA;AAAA,MACC,SAAQ;AAAA,MACR,MAAM,MAAM;AAAA,MACZ,UAAQ;AAAA,MACR,SAAS;AAAA,MACT,OAAO,MAAM;AAAA;AAAA,EACf;AAEJ;AAEA,MAAM,cAAc,KAAK,oBAAoB;AAM7C,SAAS,qBACP,OACA;AACA,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG;AAAA,EACL,IAAI;AAEJ,QAAM,SAAS,oBAAoB;AAEnC,QAAM,eAAe,OAAO;AAE5B,QAAM,KAAK,MAAM;AAEjB,QAAM,EAAE,QAAQ,MAAM,MAAM,IAAI,UAAU;AAE1C,QAAM,EAAE,UAAU,aAAa,QAAQ,YAAY,SAAS,IAC1D,eAAe;AAAA,IACb;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAEH,SACE,qBAAC,iBAAe,GAAG,MAAM,SAAS,MAC/B;AAAA,KAAC,cACA,oBAAC,QAAQ,aAAR,EAAqB,uBAAY,IAChC;AAAA,IACH,cACC;AAAA,MAAC;AAAA;AAAA,QACC,MAAM;AAAA,QACN,eAAc;AAAA,QACd,KAAK,aAAa;AAAA,QAClB,kBAAkB,aAAa;AAAA,QAC/B,UAAS;AAAA,QAER,qBACG,SAAS,IAAI,CAACA,WACZ;AAAA,UAAC;AAAA;AAAA,YACC,MAAM,MAAM;AAAA,YAEZ,OAAO,OAAO,SAASA,MAAK,CAAC;AAAA,YAC7B,OAAOA;AAAA,YACP,UAAU;AAAA;AAAA,UAHLA;AAAA,QAIP,CACD,IACD;AAAA;AAAA,IACN,IACE;AAAA,IACJ;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,OAAM;AAAA,QACN,MAAM;AAAA,QACN;AAAA,QACA;AAAA,QACA;AAAA,QACA,iBAAiB;AAAA,QACjB,UAAU;AAAA;AAAA,IACZ;AAAA,KACF;AAEJ;AAEO,MAAM,cAAc,KAAK,oBAAoB;","names":["value"]}
@@ -17,12 +17,13 @@ const Option = memo(function Option2(props) {
17
17
  return /* @__PURE__ */ jsx(Pressable, { ...rest, children: /* @__PURE__ */ jsxs(
18
18
  View,
19
19
  {
20
+ height: optionTokens.height,
20
21
  padding: optionTokens.padding,
21
22
  flexDirection: "row",
22
23
  alignItems: "center",
23
24
  justifyContent: "space-between",
24
25
  children: [
25
- /* @__PURE__ */ jsx(Typography.Body, { children: label }),
26
+ /* @__PURE__ */ jsx(Typography.Body, { flex: 1, numberOfLines: 1, ellipsizeMode: "tail", children: label }),
26
27
  /* @__PURE__ */ jsx(
27
28
  Icon,
28
29
  {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/option.tsx"],"sourcesContent":["import { memo } from \"react\";\n\nimport { Icon } from \"@impulse-ui-native/icon\";\nimport { CheckIcon } from \"@impulse-ui-native/icon/icons/check\";\nimport { Pressable, Typography, View } from \"@impulse-ui-native/primitives\";\nimport {\n getSelectionItemStateTokens,\n useComponentsTokens,\n} from \"@impulse-ui-native/theme\";\n\nimport { OptionProps } from \"../types\";\n\nexport const Option = memo(function Option(props: OptionProps) {\n const { label, selected, ...rest } = props;\n\n const tokens = useComponentsTokens();\n\n const optionTokens = tokens.select.option;\n const appearanceTokens = getSelectionItemStateTokens(optionTokens.states, {\n selected,\n });\n\n return (\n <Pressable {...rest}>\n <View\n padding={optionTokens.padding}\n flexDirection=\"row\"\n alignItems=\"center\"\n justifyContent=\"space-between\"\n >\n <Typography.Body>{label}</Typography.Body>\n\n <Icon\n icon={CheckIcon}\n color={appearanceTokens.iconColor}\n opacity={appearanceTokens.iconOpacity}\n />\n </View>\n </Pressable>\n );\n});\n"],"mappings":"AAwBM,SAME,KANF;AAxBN,SAAS,YAAY;AAErB,SAAS,YAAY;AACrB,SAAS,iBAAiB;AAC1B,SAAS,WAAW,YAAY,YAAY;AAC5C;AAAA,EACE;AAAA,EACA;AAAA,OACK;AAIA,MAAM,SAAS,KAAK,SAASA,QAAO,OAAoB;AAC7D,QAAM,EAAE,OAAO,UAAU,GAAG,KAAK,IAAI;AAErC,QAAM,SAAS,oBAAoB;AAEnC,QAAM,eAAe,OAAO,OAAO;AACnC,QAAM,mBAAmB,4BAA4B,aAAa,QAAQ;AAAA,IACxE;AAAA,EACF,CAAC;AAED,SACE,oBAAC,aAAW,GAAG,MACb;AAAA,IAAC;AAAA;AAAA,MACC,SAAS,aAAa;AAAA,MACtB,eAAc;AAAA,MACd,YAAW;AAAA,MACX,gBAAe;AAAA,MAEf;AAAA,4BAAC,WAAW,MAAX,EAAiB,iBAAM;AAAA,QAExB;AAAA,UAAC;AAAA;AAAA,YACC,MAAM;AAAA,YACN,OAAO,iBAAiB;AAAA,YACxB,SAAS,iBAAiB;AAAA;AAAA,QAC5B;AAAA;AAAA;AAAA,EACF,GACF;AAEJ,CAAC;","names":["Option"]}
1
+ {"version":3,"sources":["../../src/components/option.tsx"],"sourcesContent":["import { memo } from \"react\";\n\nimport { Icon } from \"@impulse-ui-native/icon\";\nimport { CheckIcon } from \"@impulse-ui-native/icon/icons/check\";\nimport { Pressable, Typography, View } from \"@impulse-ui-native/primitives\";\nimport {\n getSelectionItemStateTokens,\n useComponentsTokens,\n} from \"@impulse-ui-native/theme\";\n\nimport { OptionProps } from \"../types\";\n\nexport const Option = memo(function Option(props: OptionProps) {\n const { label, selected, ...rest } = props;\n\n const tokens = useComponentsTokens();\n\n const optionTokens = tokens.select.option;\n const appearanceTokens = getSelectionItemStateTokens(optionTokens.states, {\n selected,\n });\n\n return (\n <Pressable {...rest}>\n <View\n height={optionTokens.height}\n padding={optionTokens.padding}\n flexDirection=\"row\"\n alignItems=\"center\"\n justifyContent=\"space-between\"\n >\n <Typography.Body flex={1} numberOfLines={1} ellipsizeMode=\"tail\">\n {label}\n </Typography.Body>\n\n <Icon\n icon={CheckIcon}\n color={appearanceTokens.iconColor}\n opacity={appearanceTokens.iconOpacity}\n />\n </View>\n </Pressable>\n );\n});\n"],"mappings":"AAwBM,SAOE,KAPF;AAxBN,SAAS,YAAY;AAErB,SAAS,YAAY;AACrB,SAAS,iBAAiB;AAC1B,SAAS,WAAW,YAAY,YAAY;AAC5C;AAAA,EACE;AAAA,EACA;AAAA,OACK;AAIA,MAAM,SAAS,KAAK,SAASA,QAAO,OAAoB;AAC7D,QAAM,EAAE,OAAO,UAAU,GAAG,KAAK,IAAI;AAErC,QAAM,SAAS,oBAAoB;AAEnC,QAAM,eAAe,OAAO,OAAO;AACnC,QAAM,mBAAmB,4BAA4B,aAAa,QAAQ;AAAA,IACxE;AAAA,EACF,CAAC;AAED,SACE,oBAAC,aAAW,GAAG,MACb;AAAA,IAAC;AAAA;AAAA,MACC,QAAQ,aAAa;AAAA,MACrB,SAAS,aAAa;AAAA,MACtB,eAAc;AAAA,MACd,YAAW;AAAA,MACX,gBAAe;AAAA,MAEf;AAAA,4BAAC,WAAW,MAAX,EAAgB,MAAM,GAAG,eAAe,GAAG,eAAc,QACvD,iBACH;AAAA,QAEA;AAAA,UAAC;AAAA;AAAA,YACC,MAAM;AAAA,YACN,OAAO,iBAAiB;AAAA,YACxB,SAAS,iBAAiB;AAAA;AAAA,QAC5B;AAAA;AAAA;AAAA,EACF,GACF;AAEJ,CAAC;","names":["Option"]}
@@ -0,0 +1,9 @@
1
+ import { ReactElement } from 'react';
2
+ import { SelectFlyoutOptionProps } from '../types/select-options.types.mjs';
3
+ import { PrimitiveValue } from '../types/select.types.mjs';
4
+ import '@impulse-ui-native/flyout';
5
+ import '@impulse-ui-native/primitives';
6
+
7
+ declare const SelectFlyoutOption: <Value extends PrimitiveValue>(props: SelectFlyoutOptionProps<Value>) => ReactElement | null;
8
+
9
+ export { SelectFlyoutOption };
@@ -0,0 +1,23 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { memo } from "react";
3
+ import { useEventCallback } from "@impulse-ui-native/core";
4
+ import { Option } from "./option";
5
+ const SelectFlyoutOptionComponent = function SelectFlyoutOption(props) {
6
+ const handlePress = useEventCallback(
7
+ () => props.onSelect(props.option.value)
8
+ );
9
+ return /* @__PURE__ */ jsx(
10
+ Option,
11
+ {
12
+ label: props.option.label,
13
+ onPress: handlePress,
14
+ disabled: props.option.disabled,
15
+ selected: props.selected
16
+ }
17
+ );
18
+ };
19
+ const SelectFlyoutOption2 = memo(SelectFlyoutOptionComponent);
20
+ export {
21
+ SelectFlyoutOption2 as SelectFlyoutOption
22
+ };
23
+ //# sourceMappingURL=select-flyout-option.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/components/select-flyout-option.tsx"],"sourcesContent":["import { memo, ReactElement } from \"react\";\n\nimport { useEventCallback } from \"@impulse-ui-native/core\";\n\nimport type { SelectFlyoutOptionProps } from \"../types/select-options.types\";\nimport { PrimitiveValue } from \"../types\";\nimport { Option } from \"./option\";\n\nconst SelectFlyoutOptionComponent = function SelectFlyoutOption<\n Value extends PrimitiveValue,\n>(props: SelectFlyoutOptionProps<Value>) {\n const handlePress = useEventCallback(() =>\n props.onSelect(props.option.value),\n );\n\n return (\n <Option\n label={props.option.label}\n onPress={handlePress}\n disabled={props.option.disabled}\n selected={props.selected}\n />\n );\n};\n\nexport const SelectFlyoutOption = memo(SelectFlyoutOptionComponent) as <\n Value extends PrimitiveValue,\n>(\n props: SelectFlyoutOptionProps<Value>,\n) => ReactElement | null;\n"],"mappings":"AAgBI;AAhBJ,SAAS,YAA0B;AAEnC,SAAS,wBAAwB;AAIjC,SAAS,cAAc;AAEvB,MAAM,8BAA8B,SAAS,mBAE3C,OAAuC;AACvC,QAAM,cAAc;AAAA,IAAiB,MACnC,MAAM,SAAS,MAAM,OAAO,KAAK;AAAA,EACnC;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,OAAO,MAAM,OAAO;AAAA,MACpB,SAAS;AAAA,MACT,UAAU,MAAM,OAAO;AAAA,MACvB,UAAU,MAAM;AAAA;AAAA,EAClB;AAEJ;AAEO,MAAMA,sBAAqB,KAAK,2BAA2B;","names":["SelectFlyoutOption"]}
@@ -0,0 +1,9 @@
1
+ import { ReactElement } from 'react';
2
+ import { SelectOptionsProps } from '../types/select-options.types.mjs';
3
+ import { PrimitiveValue } from '../types/select.types.mjs';
4
+ import '@impulse-ui-native/flyout';
5
+ import '@impulse-ui-native/primitives';
6
+
7
+ declare const SelectOptions: <Value extends PrimitiveValue>(props: SelectOptionsProps<Value>) => ReactElement | null;
8
+
9
+ export { SelectOptions };
@@ -0,0 +1,54 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { memo, useCallback, useRef } from "react";
3
+ import {
4
+ FlatList,
5
+ useFlatListInitialScroll
6
+ } from "@impulse-ui-native/flat-list";
7
+ import { useComponentsTokens } from "@impulse-ui-native/theme";
8
+ import { getOptionId } from "../utils";
9
+ import { SelectFlyoutOption } from "./select-flyout-option";
10
+ const SelectOptionsComponent = function SelectOptions(props) {
11
+ const { options, isSelected, onSelect, initialScrollToSelected } = props;
12
+ const initialSelection = useRef(isSelected);
13
+ const tokens = useComponentsTokens();
14
+ const selectedIndex = options.findIndex(
15
+ (option) => option.value !== null && option.value !== void 0 && initialSelection.current(option.value)
16
+ );
17
+ const initialScroll = useFlatListInitialScroll({
18
+ itemSize: tokens.select.option.height,
19
+ initialScrollIndex: initialScrollToSelected && selectedIndex >= 0 ? selectedIndex : void 0
20
+ });
21
+ const renderItem = useCallback(
22
+ ({ item }) => /* @__PURE__ */ jsx(
23
+ SelectFlyoutOption,
24
+ {
25
+ option: item,
26
+ selected: isSelected(item.value),
27
+ onSelect
28
+ }
29
+ ),
30
+ [isSelected, onSelect]
31
+ );
32
+ return /* @__PURE__ */ jsx(
33
+ FlatList,
34
+ {
35
+ ...initialScroll,
36
+ data: options,
37
+ renderItem,
38
+ keyExtractor: getOptionId,
39
+ showsHorizontalScrollIndicator: false,
40
+ showsVerticalScrollIndicator: false,
41
+ keyboardShouldPersistTaps: "handled",
42
+ removeClippedSubviews: true,
43
+ windowSize: 5,
44
+ initialNumToRender: 12,
45
+ maxToRenderPerBatch: 12,
46
+ updateCellsBatchingPeriod: 32
47
+ }
48
+ );
49
+ };
50
+ const SelectOptions2 = memo(SelectOptionsComponent);
51
+ export {
52
+ SelectOptions2 as SelectOptions
53
+ };
54
+ //# sourceMappingURL=select-options.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/components/select-options.tsx"],"sourcesContent":["import type { ListRenderItemInfo } from \"react-native\";\nimport { memo, ReactElement, useCallback, useRef } from \"react\";\n\nimport {\n FlatList,\n useFlatListInitialScroll,\n} from \"@impulse-ui-native/flat-list\";\nimport { useComponentsTokens } from \"@impulse-ui-native/theme\";\n\nimport type { SelectOptionsProps } from \"../types/select-options.types\";\nimport { PrimitiveValue, SelectOption } from \"../types\";\nimport { getOptionId } from \"../utils\";\nimport { SelectFlyoutOption } from \"./select-flyout-option\";\n\nconst SelectOptionsComponent = function SelectOptions<\n Value extends PrimitiveValue,\n>(props: SelectOptionsProps<Value>) {\n const { options, isSelected, onSelect, initialScrollToSelected } = props;\n\n const initialSelection = useRef(isSelected);\n\n const tokens = useComponentsTokens();\n\n // Capture selection at opening, including when options arrive later.\n const selectedIndex = options.findIndex(\n (option) =>\n option.value !== null &&\n option.value !== undefined &&\n initialSelection.current(option.value),\n );\n const initialScroll = useFlatListInitialScroll<SelectOption<Value>>({\n itemSize: tokens.select.option.height,\n initialScrollIndex:\n initialScrollToSelected && selectedIndex >= 0 ? selectedIndex : undefined,\n });\n\n const renderItem = useCallback(\n ({ item }: ListRenderItemInfo<SelectOption<Value>>) => (\n <SelectFlyoutOption\n option={item}\n selected={isSelected(item.value)}\n onSelect={onSelect}\n />\n ),\n [isSelected, onSelect],\n );\n\n return (\n <FlatList\n {...initialScroll}\n data={options}\n renderItem={renderItem}\n keyExtractor={getOptionId}\n showsHorizontalScrollIndicator={false}\n showsVerticalScrollIndicator={false}\n keyboardShouldPersistTaps=\"handled\"\n removeClippedSubviews\n windowSize={5}\n initialNumToRender={12}\n maxToRenderPerBatch={12}\n updateCellsBatchingPeriod={32}\n />\n );\n};\n\nexport const SelectOptions = memo(SelectOptionsComponent) as <\n Value extends PrimitiveValue,\n>(\n props: SelectOptionsProps<Value>,\n) => ReactElement | null;\n"],"mappings":"AAsCM;AArCN,SAAS,MAAoB,aAAa,cAAc;AAExD;AAAA,EACE;AAAA,EACA;AAAA,OACK;AACP,SAAS,2BAA2B;AAIpC,SAAS,mBAAmB;AAC5B,SAAS,0BAA0B;AAEnC,MAAM,yBAAyB,SAAS,cAEtC,OAAkC;AAClC,QAAM,EAAE,SAAS,YAAY,UAAU,wBAAwB,IAAI;AAEnE,QAAM,mBAAmB,OAAO,UAAU;AAE1C,QAAM,SAAS,oBAAoB;AAGnC,QAAM,gBAAgB,QAAQ;AAAA,IAC5B,CAAC,WACC,OAAO,UAAU,QACjB,OAAO,UAAU,UACjB,iBAAiB,QAAQ,OAAO,KAAK;AAAA,EACzC;AACA,QAAM,gBAAgB,yBAA8C;AAAA,IAClE,UAAU,OAAO,OAAO,OAAO;AAAA,IAC/B,oBACE,2BAA2B,iBAAiB,IAAI,gBAAgB;AAAA,EACpE,CAAC;AAED,QAAM,aAAa;AAAA,IACjB,CAAC,EAAE,KAAK,MACN;AAAA,MAAC;AAAA;AAAA,QACC,QAAQ;AAAA,QACR,UAAU,WAAW,KAAK,KAAK;AAAA,QAC/B;AAAA;AAAA,IACF;AAAA,IAEF,CAAC,YAAY,QAAQ;AAAA,EACvB;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACE,GAAG;AAAA,MACJ,MAAM;AAAA,MACN;AAAA,MACA,cAAc;AAAA,MACd,gCAAgC;AAAA,MAChC,8BAA8B;AAAA,MAC9B,2BAA0B;AAAA,MAC1B,uBAAqB;AAAA,MACrB,YAAY;AAAA,MACZ,oBAAoB;AAAA,MACpB,qBAAqB;AAAA,MACrB,2BAA2B;AAAA;AAAA,EAC7B;AAEJ;AAEO,MAAMA,iBAAgB,KAAK,sBAAsB;","names":["SelectOptions"]}
@@ -1,60 +1,34 @@
1
1
  import { jsx } from "react/jsx-runtime";
2
- import { memo, useCallback } from "react";
3
- import { FlatList } from "react-native";
2
+ import { memo, useState } from "react";
4
3
  import { useEventCallback } from "@impulse-ui-native/core";
5
4
  import { Flyout } from "@impulse-ui-native/flyout";
6
5
  import { Portal } from "@impulse-ui-native/portal";
7
6
  import { View } from "@impulse-ui-native/primitives";
8
7
  import { useComponentsTokens } from "@impulse-ui-native/theme";
9
- import { getOptionId } from "../utils";
10
- import { Option } from "./option";
11
- function SelectFlyoutOptionComponent(props) {
12
- const handlePress = useEventCallback(
13
- () => props.onSelect(props.option.value)
14
- );
15
- return /* @__PURE__ */ jsx(
16
- Option,
17
- {
18
- label: props.option.label,
19
- onPress: handlePress,
20
- disabled: props.option.disabled,
21
- selected: props.selected
22
- }
23
- );
24
- }
25
- const SelectFlyoutOption = memo(SelectFlyoutOptionComponent);
8
+ import { SelectOptions } from "./select-options";
26
9
  const SelectFlyoutComponent = function SelectFlyoutContent(props) {
27
- const { options, isSelected, onSelect, ...rest } = props;
10
+ const {
11
+ options,
12
+ isSelected,
13
+ onSelect,
14
+ initialScrollToSelected = true,
15
+ ...rest
16
+ } = props;
17
+ const [openingKey, setOpeningKey] = useState(0);
28
18
  const tokens = useComponentsTokens();
29
- const selectTokens = tokens.select;
30
- const renderItem = useCallback(
31
- ({ item }) => {
32
- return /* @__PURE__ */ jsx(
33
- SelectFlyoutOption,
34
- {
35
- option: item,
36
- selected: isSelected(item.value),
37
- onSelect
38
- }
39
- );
40
- },
41
- [isSelected, onSelect]
42
- );
43
- return /* @__PURE__ */ jsx(Portal, { children: /* @__PURE__ */ jsx(Flyout, { ...rest, children: /* @__PURE__ */ jsx(View, { height: selectTokens.flyoutHeight, children: /* @__PURE__ */ jsx(
44
- FlatList,
19
+ const handleOpen = useEventCallback((id) => {
20
+ setOpeningKey((key) => key + 1);
21
+ rest.onOpen?.(id);
22
+ });
23
+ return /* @__PURE__ */ jsx(Portal, { children: /* @__PURE__ */ jsx(Flyout, { ...rest, onOpen: handleOpen, children: /* @__PURE__ */ jsx(View, { height: tokens.select.flyoutHeight, children: /* @__PURE__ */ jsx(
24
+ SelectOptions,
45
25
  {
46
- data: options,
47
- renderItem,
48
- keyExtractor: getOptionId,
49
- showsHorizontalScrollIndicator: false,
50
- showsVerticalScrollIndicator: false,
51
- keyboardShouldPersistTaps: "handled",
52
- removeClippedSubviews: true,
53
- windowSize: 5,
54
- initialNumToRender: 12,
55
- maxToRenderPerBatch: 12,
56
- updateCellsBatchingPeriod: 32
57
- }
26
+ options,
27
+ isSelected,
28
+ onSelect,
29
+ initialScrollToSelected: Boolean(rest.open) && initialScrollToSelected
30
+ },
31
+ openingKey
58
32
  ) }) }) });
59
33
  };
60
34
  const SelectFlyout = memo(SelectFlyoutComponent);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/select.flyout.tsx"],"sourcesContent":["import { memo, ReactElement, useCallback } from \"react\";\nimport { FlatList, ListRenderItemInfo } from \"react-native\";\n\nimport { useEventCallback } from \"@impulse-ui-native/core\";\nimport { Flyout } from \"@impulse-ui-native/flyout\";\nimport { Portal } from \"@impulse-ui-native/portal\";\nimport { View } from \"@impulse-ui-native/primitives\";\nimport { useComponentsTokens } from \"@impulse-ui-native/theme\";\n\nimport { PrimitiveValue, SelectFlyoutProps, SelectOption } from \"../types\";\nimport { getOptionId } from \"../utils\";\nimport { Option } from \"./option\";\n\ninterface SelectFlyoutOptionProps<Value extends PrimitiveValue> {\n option: SelectOption<Value>;\n selected: boolean;\n onSelect: (value: Value) => void;\n}\n\nfunction SelectFlyoutOptionComponent<Value extends PrimitiveValue>(\n props: SelectFlyoutOptionProps<Value>,\n) {\n const handlePress = useEventCallback(() =>\n props.onSelect(props.option.value),\n );\n\n return (\n <Option\n label={props.option.label}\n onPress={handlePress}\n disabled={props.option.disabled}\n selected={props.selected}\n />\n );\n}\n\nconst SelectFlyoutOption = memo(SelectFlyoutOptionComponent) as <\n Value extends PrimitiveValue,\n>(\n props: SelectFlyoutOptionProps<Value>,\n) => ReactElement | null;\n\nconst SelectFlyoutComponent = function SelectFlyoutContent<\n Value extends PrimitiveValue,\n>(props: SelectFlyoutProps<Value>) {\n const { options, isSelected, onSelect, ...rest } = props;\n\n const tokens = useComponentsTokens();\n\n const selectTokens = tokens.select;\n\n const renderItem = useCallback(\n ({ item }: ListRenderItemInfo<SelectOption<Value>>) => {\n return (\n <SelectFlyoutOption\n option={item}\n selected={isSelected(item.value)}\n onSelect={onSelect}\n />\n );\n },\n [isSelected, onSelect],\n );\n\n return (\n <Portal>\n <Flyout {...rest}>\n <View height={selectTokens.flyoutHeight}>\n <FlatList\n data={options}\n renderItem={renderItem}\n keyExtractor={getOptionId}\n showsHorizontalScrollIndicator={false}\n showsVerticalScrollIndicator={false}\n keyboardShouldPersistTaps=\"handled\"\n removeClippedSubviews\n windowSize={5}\n initialNumToRender={12}\n maxToRenderPerBatch={12}\n updateCellsBatchingPeriod={32}\n />\n </View>\n </Flyout>\n </Portal>\n );\n};\n\nexport const SelectFlyout = memo(SelectFlyoutComponent) as <\n Value extends PrimitiveValue,\n>(\n props: SelectFlyoutProps<Value>,\n) => ReactElement | null;\n"],"mappings":"AA2BI;AA3BJ,SAAS,MAAoB,mBAAmB;AAChD,SAAS,gBAAoC;AAE7C,SAAS,wBAAwB;AACjC,SAAS,cAAc;AACvB,SAAS,cAAc;AACvB,SAAS,YAAY;AACrB,SAAS,2BAA2B;AAGpC,SAAS,mBAAmB;AAC5B,SAAS,cAAc;AAQvB,SAAS,4BACP,OACA;AACA,QAAM,cAAc;AAAA,IAAiB,MACnC,MAAM,SAAS,MAAM,OAAO,KAAK;AAAA,EACnC;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,OAAO,MAAM,OAAO;AAAA,MACpB,SAAS;AAAA,MACT,UAAU,MAAM,OAAO;AAAA,MACvB,UAAU,MAAM;AAAA;AAAA,EAClB;AAEJ;AAEA,MAAM,qBAAqB,KAAK,2BAA2B;AAM3D,MAAM,wBAAwB,SAAS,oBAErC,OAAiC;AACjC,QAAM,EAAE,SAAS,YAAY,UAAU,GAAG,KAAK,IAAI;AAEnD,QAAM,SAAS,oBAAoB;AAEnC,QAAM,eAAe,OAAO;AAE5B,QAAM,aAAa;AAAA,IACjB,CAAC,EAAE,KAAK,MAA+C;AACrD,aACE;AAAA,QAAC;AAAA;AAAA,UACC,QAAQ;AAAA,UACR,UAAU,WAAW,KAAK,KAAK;AAAA,UAC/B;AAAA;AAAA,MACF;AAAA,IAEJ;AAAA,IACA,CAAC,YAAY,QAAQ;AAAA,EACvB;AAEA,SACE,oBAAC,UACC,8BAAC,UAAQ,GAAG,MACV,8BAAC,QAAK,QAAQ,aAAa,cACzB;AAAA,IAAC;AAAA;AAAA,MACC,MAAM;AAAA,MACN;AAAA,MACA,cAAc;AAAA,MACd,gCAAgC;AAAA,MAChC,8BAA8B;AAAA,MAC9B,2BAA0B;AAAA,MAC1B,uBAAqB;AAAA,MACrB,YAAY;AAAA,MACZ,oBAAoB;AAAA,MACpB,qBAAqB;AAAA,MACrB,2BAA2B;AAAA;AAAA,EAC7B,GACF,GACF,GACF;AAEJ;AAEO,MAAM,eAAe,KAAK,qBAAqB;","names":[]}
1
+ {"version":3,"sources":["../../src/components/select.flyout.tsx"],"sourcesContent":["import { memo, ReactElement, useState } from \"react\";\n\nimport { useEventCallback } from \"@impulse-ui-native/core\";\nimport { Flyout } from \"@impulse-ui-native/flyout\";\nimport { Portal } from \"@impulse-ui-native/portal\";\nimport { View } from \"@impulse-ui-native/primitives\";\nimport { useComponentsTokens } from \"@impulse-ui-native/theme\";\n\nimport { PrimitiveValue, SelectFlyoutProps } from \"../types\";\nimport { SelectOptions } from \"./select-options\";\n\nconst SelectFlyoutComponent = function SelectFlyoutContent<\n Value extends PrimitiveValue,\n>(props: SelectFlyoutProps<Value>) {\n const {\n options,\n isSelected,\n onSelect,\n initialScrollToSelected = true,\n ...rest\n } = props;\n\n const [openingKey, setOpeningKey] = useState(0);\n\n const tokens = useComponentsTokens();\n\n const handleOpen = useEventCallback((id: string) => {\n setOpeningKey((key) => key + 1);\n rest.onOpen?.(id);\n });\n\n return (\n <Portal>\n <Flyout {...rest} onOpen={handleOpen}>\n <View height={tokens.select.flyoutHeight}>\n <SelectOptions\n key={openingKey}\n options={options}\n isSelected={isSelected}\n onSelect={onSelect}\n initialScrollToSelected={\n Boolean(rest.open) && initialScrollToSelected\n }\n />\n </View>\n </Flyout>\n </Portal>\n );\n};\n\nexport const SelectFlyout = memo(SelectFlyoutComponent) as <\n Value extends PrimitiveValue,\n>(\n props: SelectFlyoutProps<Value>,\n) => ReactElement | null;\n"],"mappings":"AAmCU;AAnCV,SAAS,MAAoB,gBAAgB;AAE7C,SAAS,wBAAwB;AACjC,SAAS,cAAc;AACvB,SAAS,cAAc;AACvB,SAAS,YAAY;AACrB,SAAS,2BAA2B;AAGpC,SAAS,qBAAqB;AAE9B,MAAM,wBAAwB,SAAS,oBAErC,OAAiC;AACjC,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA,0BAA0B;AAAA,IAC1B,GAAG;AAAA,EACL,IAAI;AAEJ,QAAM,CAAC,YAAY,aAAa,IAAI,SAAS,CAAC;AAE9C,QAAM,SAAS,oBAAoB;AAEnC,QAAM,aAAa,iBAAiB,CAAC,OAAe;AAClD,kBAAc,CAAC,QAAQ,MAAM,CAAC;AAC9B,SAAK,SAAS,EAAE;AAAA,EAClB,CAAC;AAED,SACE,oBAAC,UACC,8BAAC,UAAQ,GAAG,MAAM,QAAQ,YACxB,8BAAC,QAAK,QAAQ,OAAO,OAAO,cAC1B;AAAA,IAAC;AAAA;AAAA,MAEC;AAAA,MACA;AAAA,MACA;AAAA,MACA,yBACE,QAAQ,KAAK,IAAI,KAAK;AAAA;AAAA,IALnB;AAAA,EAOP,GACF,GACF,GACF;AAEJ;AAEO,MAAM,eAAe,KAAK,qBAAqB;","names":[]}
@@ -6,7 +6,15 @@ import { useSelect } from "../hooks/use-select.hook";
6
6
  import { SelectControl } from "./select-control";
7
7
  import { SelectFlyout } from "./select.flyout";
8
8
  function SelectComponent(props) {
9
- const { options, value, defaultValue, onChange, placeholder, ...rest } = props;
9
+ const {
10
+ options,
11
+ value,
12
+ defaultValue,
13
+ onChange,
14
+ placeholder,
15
+ initialScrollToSelected,
16
+ ...rest
17
+ } = props;
10
18
  const id = useId();
11
19
  const { isOpen, open, close } = useIsOpen();
12
20
  const { selected, hasSelected, select, isSelected, getLabel } = useSelect({
@@ -32,6 +40,7 @@ function SelectComponent(props) {
32
40
  title: "Options",
33
41
  open: isOpen,
34
42
  options,
43
+ initialScrollToSelected,
35
44
  isSelected,
36
45
  onCloseFinished: close,
37
46
  onSelect: handleOnSelect
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/select.tsx"],"sourcesContent":["import { memo, ReactElement, useCallback, useId } from \"react\";\n\nimport { useIsOpen } from \"@impulse-ui-native/core\";\nimport { Control } from \"@impulse-ui-native/primitives\";\n\nimport { useSelect } from \"../hooks/use-select.hook\";\nimport { PrimitiveValue, SelectProps } from \"../types\";\nimport { SelectControl } from \"./select-control\";\nimport { SelectFlyout } from \"./select.flyout\";\n\nfunction SelectComponent<Value extends PrimitiveValue>(\n props: SelectProps<Value>,\n) {\n const { options, value, defaultValue, onChange, placeholder, ...rest } =\n props;\n\n const id = useId();\n\n const { isOpen, open, close } = useIsOpen();\n\n const { selected, hasSelected, select, isSelected, getLabel } = useSelect({\n options,\n value,\n defaultValue,\n onChange,\n });\n\n const handleOnSelect = useCallback(\n (value: Value) => {\n select(value);\n close();\n },\n [select, close],\n );\n\n return (\n <SelectControl {...rest} onPress={open}>\n {!hasSelected ? (\n <Control.Placeholder>{placeholder}</Control.Placeholder>\n ) : null}\n {selected !== null && selected !== undefined ? (\n <Control.Value>{getLabel(selected)}</Control.Value>\n ) : null}\n <SelectFlyout\n id={id}\n title=\"Options\"\n open={isOpen}\n options={options}\n isSelected={isSelected}\n onCloseFinished={close}\n onSelect={handleOnSelect}\n />\n </SelectControl>\n );\n}\n\nexport const Select = memo(SelectComponent) as <Value extends PrimitiveValue>(\n props: SelectProps<Value>,\n) => ReactElement | null;\n"],"mappings":"AAoCI,SAEI,KAFJ;AApCJ,SAAS,MAAoB,aAAa,aAAa;AAEvD,SAAS,iBAAiB;AAC1B,SAAS,eAAe;AAExB,SAAS,iBAAiB;AAE1B,SAAS,qBAAqB;AAC9B,SAAS,oBAAoB;AAE7B,SAAS,gBACP,OACA;AACA,QAAM,EAAE,SAAS,OAAO,cAAc,UAAU,aAAa,GAAG,KAAK,IACnE;AAEF,QAAM,KAAK,MAAM;AAEjB,QAAM,EAAE,QAAQ,MAAM,MAAM,IAAI,UAAU;AAE1C,QAAM,EAAE,UAAU,aAAa,QAAQ,YAAY,SAAS,IAAI,UAAU;AAAA,IACxE;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,QAAM,iBAAiB;AAAA,IACrB,CAACA,WAAiB;AAChB,aAAOA,MAAK;AACZ,YAAM;AAAA,IACR;AAAA,IACA,CAAC,QAAQ,KAAK;AAAA,EAChB;AAEA,SACE,qBAAC,iBAAe,GAAG,MAAM,SAAS,MAC/B;AAAA,KAAC,cACA,oBAAC,QAAQ,aAAR,EAAqB,uBAAY,IAChC;AAAA,IACH,aAAa,QAAQ,aAAa,SACjC,oBAAC,QAAQ,OAAR,EAAe,mBAAS,QAAQ,GAAE,IACjC;AAAA,IACJ;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,OAAM;AAAA,QACN,MAAM;AAAA,QACN;AAAA,QACA;AAAA,QACA,iBAAiB;AAAA,QACjB,UAAU;AAAA;AAAA,IACZ;AAAA,KACF;AAEJ;AAEO,MAAM,SAAS,KAAK,eAAe;","names":["value"]}
1
+ {"version":3,"sources":["../../src/components/select.tsx"],"sourcesContent":["import { memo, ReactElement, useCallback, useId } from \"react\";\n\nimport { useIsOpen } from \"@impulse-ui-native/core\";\nimport { Control } from \"@impulse-ui-native/primitives\";\n\nimport { useSelect } from \"../hooks/use-select.hook\";\nimport { PrimitiveValue, SelectProps } from \"../types\";\nimport { SelectControl } from \"./select-control\";\nimport { SelectFlyout } from \"./select.flyout\";\n\nfunction SelectComponent<Value extends PrimitiveValue>(\n props: SelectProps<Value>,\n) {\n const {\n options,\n value,\n defaultValue,\n onChange,\n placeholder,\n initialScrollToSelected,\n ...rest\n } = props;\n\n const id = useId();\n\n const { isOpen, open, close } = useIsOpen();\n\n const { selected, hasSelected, select, isSelected, getLabel } = useSelect({\n options,\n value,\n defaultValue,\n onChange,\n });\n\n const handleOnSelect = useCallback(\n (value: Value) => {\n select(value);\n close();\n },\n [select, close],\n );\n\n return (\n <SelectControl {...rest} onPress={open}>\n {!hasSelected ? (\n <Control.Placeholder>{placeholder}</Control.Placeholder>\n ) : null}\n {selected !== null && selected !== undefined ? (\n <Control.Value>{getLabel(selected)}</Control.Value>\n ) : null}\n <SelectFlyout\n id={id}\n title=\"Options\"\n open={isOpen}\n options={options}\n initialScrollToSelected={initialScrollToSelected}\n isSelected={isSelected}\n onCloseFinished={close}\n onSelect={handleOnSelect}\n />\n </SelectControl>\n );\n}\n\nexport const Select = memo(SelectComponent) as <Value extends PrimitiveValue>(\n props: SelectProps<Value>,\n) => ReactElement | null;\n"],"mappings":"AA2CI,SAEI,KAFJ;AA3CJ,SAAS,MAAoB,aAAa,aAAa;AAEvD,SAAS,iBAAiB;AAC1B,SAAS,eAAe;AAExB,SAAS,iBAAiB;AAE1B,SAAS,qBAAqB;AAC9B,SAAS,oBAAoB;AAE7B,SAAS,gBACP,OACA;AACA,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG;AAAA,EACL,IAAI;AAEJ,QAAM,KAAK,MAAM;AAEjB,QAAM,EAAE,QAAQ,MAAM,MAAM,IAAI,UAAU;AAE1C,QAAM,EAAE,UAAU,aAAa,QAAQ,YAAY,SAAS,IAAI,UAAU;AAAA,IACxE;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,QAAM,iBAAiB;AAAA,IACrB,CAACA,WAAiB;AAChB,aAAOA,MAAK;AACZ,YAAM;AAAA,IACR;AAAA,IACA,CAAC,QAAQ,KAAK;AAAA,EAChB;AAEA,SACE,qBAAC,iBAAe,GAAG,MAAM,SAAS,MAC/B;AAAA,KAAC,cACA,oBAAC,QAAQ,aAAR,EAAqB,uBAAY,IAChC;AAAA,IACH,aAAa,QAAQ,aAAa,SACjC,oBAAC,QAAQ,OAAR,EAAe,mBAAS,QAAQ,GAAE,IACjC;AAAA,IACJ;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,OAAM;AAAA,QACN,MAAM;AAAA,QACN;AAAA,QACA;AAAA,QACA;AAAA,QACA,iBAAiB;AAAA,QACjB,UAAU;AAAA;AAAA,IACZ;AAAA,KACF;AAEJ;AAEO,MAAM,SAAS,KAAK,eAAe;","names":["value"]}
@@ -0,0 +1,12 @@
1
+ import { PrimitiveValue, SelectOption, SelectFlyoutProps } from './select.types.mjs';
2
+ import '@impulse-ui-native/flyout';
3
+ import '@impulse-ui-native/primitives';
4
+
5
+ type SelectOptionsProps<Value extends PrimitiveValue> = Pick<SelectFlyoutProps<Value>, "options" | "isSelected" | "onSelect" | "initialScrollToSelected">;
6
+ interface SelectFlyoutOptionProps<Value extends PrimitiveValue> {
7
+ option: SelectOption<Value>;
8
+ selected: boolean;
9
+ onSelect: (value: Value) => void;
10
+ }
11
+
12
+ export type { SelectFlyoutOptionProps, SelectOptionsProps };
@@ -0,0 +1 @@
1
+ //# sourceMappingURL=select-options.types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -10,6 +10,8 @@ type SelectOption<Value> = {
10
10
  };
11
11
  interface CommonSelectProps<Value> extends Partial<ControlComponentProps>, ControlComponentCommonProps {
12
12
  loading?: boolean;
13
+ /** Reveal the selection on each opening. Defaults to true. */
14
+ initialScrollToSelected?: boolean;
13
15
  onChange?: (value: Value | undefined) => void;
14
16
  }
15
17
  interface SelectControlProps<Value> extends CommonSelectProps<Value> {
@@ -27,6 +29,7 @@ interface MultiSelectProps<Value extends PrimitiveValue> extends Partial<Control
27
29
  }
28
30
  interface SelectFlyoutProps<Value extends PrimitiveValue> extends FlyoutProps {
29
31
  options: SelectOption<Value>[];
32
+ initialScrollToSelected?: boolean;
30
33
  isSelected: (value: Value) => boolean;
31
34
  onSelect: (value: Value) => void;
32
35
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@impulse-ui-native/select",
3
- "version": "8.2.0",
3
+ "version": "8.3.0",
4
4
  "description": "Select and option picker components for ImpulseUI Native applications.",
5
5
  "keywords": [
6
6
  "react-native",
@@ -28,30 +28,29 @@
28
28
  ],
29
29
  "sideEffects": false,
30
30
  "dependencies": {
31
- "@impulse-ui-native/theme": "8.2.0",
32
- "@impulse-ui-native/icon": "8.2.0",
33
- "@impulse-ui-native/input": "8.2.0",
34
- "@impulse-ui-native/core": "8.2.0",
35
- "@impulse-ui-native/primitives": "8.2.0",
36
- "@impulse-ui-native/flyout": "8.2.0",
37
- "@impulse-ui-native/portal": "8.2.0"
31
+ "@impulse-ui-native/theme": "8.3.0",
32
+ "@impulse-ui-native/icon": "8.3.0",
33
+ "@impulse-ui-native/input": "8.3.0",
34
+ "@impulse-ui-native/primitives": "8.3.0",
35
+ "@impulse-ui-native/core": "8.3.0",
36
+ "@impulse-ui-native/flyout": "8.3.0",
37
+ "@impulse-ui-native/portal": "8.3.0",
38
+ "@impulse-ui-native/flat-list": "8.3.0"
38
39
  },
39
40
  "devDependencies": {
40
- "@shopify/flash-list": "2.0.2",
41
41
  "@types/react": "~19.2.14",
42
42
  "eslint": "^9.38.0",
43
43
  "prettier": "^3.6.2",
44
44
  "react": "19.2.3",
45
45
  "react-native": "0.86.2",
46
46
  "typescript": "~6.0.3",
47
+ "@impulse-ui-native/eslint-config": "1.0.0",
47
48
  "@impulse-ui-native/prettier-config": "1.0.0",
48
- "@impulse-ui-native/tsconfig": "1.0.0",
49
- "@impulse-ui-native/eslint-config": "1.0.0"
49
+ "@impulse-ui-native/tsconfig": "1.0.0"
50
50
  },
51
51
  "peerDependencies": {
52
52
  "react": ">=18",
53
- "react-native": ">=0.73",
54
- "@shopify/flash-list": ">=2"
53
+ "react-native": ">=0.73"
55
54
  },
56
55
  "publishConfig": {
57
56
  "access": "public"