@impulse-ui-native/select 2.3.5 → 2.5.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
@@ -8,7 +8,7 @@ Single- and multi-value select controls that present their options in a themed f
8
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
9
9
  ```
10
10
 
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 `LayerCenter` at the application root.
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.
12
12
 
13
13
  ## Main exports
14
14
 
@@ -20,9 +20,15 @@ Complete the Gesture Handler, Reanimated, Worklets, and Safe Area Context setup
20
20
  ## Usage
21
21
 
22
22
  ```tsx
23
- import { LayerCenter } from "@impulse-ui-native/layers";
23
+ import {
24
+ PortalProvider,
25
+ PortalsHost,
26
+ PortalStore,
27
+ } from "@impulse-ui-native/portal";
24
28
  import { Select } from "@impulse-ui-native/select";
25
29
 
30
+ const portalStore = new PortalStore();
31
+
26
32
  const options = [
27
33
  { label: "Design", value: "design" },
28
34
  { label: "Engineering", value: "engineering" },
@@ -33,7 +39,7 @@ export function DepartmentField() {
33
39
  const [value, setValue] = useState<string>();
34
40
 
35
41
  return (
36
- <>
42
+ <PortalProvider store={portalStore}>
37
43
  <Select
38
44
  label="Department"
39
45
  options={options}
@@ -41,8 +47,8 @@ export function DepartmentField() {
41
47
  onChange={setValue}
42
48
  placeholder="Choose a department"
43
49
  />
44
- <LayerCenter />
45
- </>
50
+ <PortalsHost />
51
+ </PortalProvider>
46
52
  );
47
53
  }
48
54
  ```
@@ -2,11 +2,14 @@ import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import { memo, useId } from "react";
3
3
  import { useIsOpen } from "@impulse-ui-native/core";
4
4
  import { Control, Tag, View } from "@impulse-ui-native/primitives";
5
+ import { useComponentsTokens } from "@impulse-ui-native/theme";
5
6
  import { useMultiSelect } from "../hooks/use-multi-select.hook";
6
7
  import { SelectControl } from "./select-control";
7
8
  import { SelectFlyout } from "./select.flyout";
8
9
  function MultiSelectComponent(props) {
9
10
  const { options, value, defaultValue, onChange, placeholder, ...rest } = props;
11
+ const tokens = useComponentsTokens();
12
+ const selectTokens = tokens.select;
10
13
  const id = useId();
11
14
  const { isOpen, open, close } = useIsOpen();
12
15
  const { selected, hasSelected, select, isSelected, getLabel } = useMultiSelect({
@@ -22,8 +25,8 @@ function MultiSelectComponent(props) {
22
25
  {
23
26
  flex: 1,
24
27
  flexDirection: "row",
25
- gap: 4,
26
- marginHorizontal: 4,
28
+ gap: selectTokens.multiValueGap,
29
+ marginHorizontal: selectTokens.multiValueMarginHorizontal,
27
30
  overflow: "hidden",
28
31
  children: selected ? selected.map((value2) => /* @__PURE__ */ jsx(
29
32
  Tag,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/multi-select.tsx"],"sourcesContent":["import { memo, ReactElement, useId } from \"react\";\n\nimport { useIsOpen } from \"@impulse-ui-native/core\";\nimport { Control, Tag, View } from \"@impulse-ui-native/primitives\";\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\nfunction MultiSelectComponent<Value extends PrimitiveValue>(\n props: MultiSelectProps<Value>,\n) {\n const { options, value, defaultValue, onChange, placeholder, ...rest } =\n props;\n const id = useId();\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={4}\n marginHorizontal={4}\n overflow=\"hidden\"\n >\n {selected\n ? selected.map((value) => (\n <Tag\n variant=\"filled\"\n size={props.size}\n key={value}\n closable\n onClose={() => select(value)}\n label={String(getLabel(value))}\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":"AA2BI,SAEI,KAFJ;AA3BJ,SAAS,MAAoB,aAAa;AAE1C,SAAS,iBAAiB;AAC1B,SAAS,SAAS,KAAK,YAAY;AAEnC,SAAS,sBAAsB;AAE/B,SAAS,qBAAqB;AAC9B,SAAS,oBAAoB;AAE7B,SAAS,qBACP,OACA;AACA,QAAM,EAAE,SAAS,OAAO,cAAc,UAAU,aAAa,GAAG,KAAK,IACnE;AACF,QAAM,KAAK,MAAM;AACjB,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,QACL,kBAAkB;AAAA,QAClB,UAAS;AAAA,QAER,qBACG,SAAS,IAAI,CAACA,WACZ;AAAA,UAAC;AAAA;AAAA,YACC,SAAQ;AAAA,YACR,MAAM,MAAM;AAAA,YAEZ,UAAQ;AAAA,YACR,SAAS,MAAM,OAAOA,MAAK;AAAA,YAC3B,OAAO,OAAO,SAASA,MAAK,CAAC;AAAA;AAAA,UAHxBA;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 { 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\nfunction MultiSelectComponent<Value extends PrimitiveValue>(\n props: MultiSelectProps<Value>,\n) {\n const { options, value, defaultValue, onChange, placeholder, ...rest } =\n props;\n const tokens = useComponentsTokens();\n const selectTokens = tokens.select;\n const id = useId();\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 <Tag\n variant=\"filled\"\n size={props.size}\n key={value}\n closable\n onClose={() => select(value)}\n label={String(getLabel(value))}\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":"AA8BI,SAEI,KAFJ;AA9BJ,SAAS,MAAoB,aAAa;AAE1C,SAAS,iBAAiB;AAC1B,SAAS,SAAS,KAAK,YAAY;AACnC,SAAS,2BAA2B;AAEpC,SAAS,sBAAsB;AAE/B,SAAS,qBAAqB;AAC9B,SAAS,oBAAoB;AAE7B,SAAS,qBACP,OACA;AACA,QAAM,EAAE,SAAS,OAAO,cAAc,UAAU,aAAa,GAAG,KAAK,IACnE;AACF,QAAM,SAAS,oBAAoB;AACnC,QAAM,eAAe,OAAO;AAC5B,QAAM,KAAK,MAAM;AACjB,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,SAAQ;AAAA,YACR,MAAM,MAAM;AAAA,YAEZ,UAAQ;AAAA,YACR,SAAS,MAAM,OAAOA,MAAK;AAAA,YAC3B,OAAO,OAAO,SAASA,MAAK,CAAC;AAAA;AAAA,UAHxBA;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"]}
@@ -4,10 +4,13 @@ import { FlatList } from "react-native";
4
4
  import { Flyout } from "@impulse-ui-native/flyout";
5
5
  import { Portal } from "@impulse-ui-native/portal";
6
6
  import { View } from "@impulse-ui-native/primitives";
7
+ import { useComponentsTokens } from "@impulse-ui-native/theme";
7
8
  import { getOptionId } from "../utils";
8
9
  import { Option } from "./option";
9
10
  const SelectFlyoutComponent = function SelectFlyoutContent(props) {
10
11
  const { options, isSelected, onSelect, ...rest } = props;
12
+ const tokens = useComponentsTokens();
13
+ const selectTokens = tokens.select;
11
14
  const renderItem = useCallback(
12
15
  ({ item }) => {
13
16
  return /* @__PURE__ */ jsx(
@@ -22,7 +25,7 @@ const SelectFlyoutComponent = function SelectFlyoutContent(props) {
22
25
  },
23
26
  [isSelected, onSelect]
24
27
  );
25
- return /* @__PURE__ */ jsx(Portal, { children: /* @__PURE__ */ jsx(Flyout, { ...rest, children: /* @__PURE__ */ jsx(View, { height: 300, children: /* @__PURE__ */ jsx(
28
+ return /* @__PURE__ */ jsx(Portal, { children: /* @__PURE__ */ jsx(Flyout, { ...rest, children: /* @__PURE__ */ jsx(View, { height: selectTokens.flyoutHeight, children: /* @__PURE__ */ jsx(
26
29
  FlatList,
27
30
  {
28
31
  data: options,
@@ -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 { Flyout } from \"@impulse-ui-native/flyout\";\nimport { Portal } from \"@impulse-ui-native/portal\";\nimport { View } from \"@impulse-ui-native/primitives\";\n\nimport { PrimitiveValue, SelectFlyoutProps, SelectOption } from \"../types\";\nimport { getOptionId } from \"../utils\";\nimport { Option } from \"./option\";\n\nconst SelectFlyoutComponent = function SelectFlyoutContent<\n Value extends PrimitiveValue,\n>(props: SelectFlyoutProps<Value>) {\n const { options, isSelected, onSelect, ...rest } = props;\n\n const renderItem = useCallback(\n ({ item }: ListRenderItemInfo<SelectOption<Value>>) => {\n return (\n <Option\n label={item.label}\n onPress={() => onSelect(item.value)}\n disabled={item.disabled}\n selected={isSelected(item.value)}\n />\n );\n },\n [isSelected, onSelect],\n );\n\n return (\n <Portal>\n <Flyout {...rest}>\n <View height={300}>\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":"AAmBQ;AAnBR,SAAS,MAAoB,mBAAmB;AAChD,SAAS,gBAAoC;AAE7C,SAAS,cAAc;AACvB,SAAS,cAAc;AACvB,SAAS,YAAY;AAGrB,SAAS,mBAAmB;AAC5B,SAAS,cAAc;AAEvB,MAAM,wBAAwB,SAAS,oBAErC,OAAiC;AACjC,QAAM,EAAE,SAAS,YAAY,UAAU,GAAG,KAAK,IAAI;AAEnD,QAAM,aAAa;AAAA,IACjB,CAAC,EAAE,KAAK,MAA+C;AACrD,aACE;AAAA,QAAC;AAAA;AAAA,UACC,OAAO,KAAK;AAAA,UACZ,SAAS,MAAM,SAAS,KAAK,KAAK;AAAA,UAClC,UAAU,KAAK;AAAA,UACf,UAAU,WAAW,KAAK,KAAK;AAAA;AAAA,MACjC;AAAA,IAEJ;AAAA,IACA,CAAC,YAAY,QAAQ;AAAA,EACvB;AAEA,SACE,oBAAC,UACC,8BAAC,UAAQ,GAAG,MACV,8BAAC,QAAK,QAAQ,KACZ;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, useCallback } from \"react\";\nimport { FlatList, ListRenderItemInfo } from \"react-native\";\n\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\nconst SelectFlyoutComponent = function SelectFlyoutContent<\n Value extends PrimitiveValue,\n>(props: SelectFlyoutProps<Value>) {\n const { options, isSelected, onSelect, ...rest } = props;\n const tokens = useComponentsTokens();\n const selectTokens = tokens.select;\n\n const renderItem = useCallback(\n ({ item }: ListRenderItemInfo<SelectOption<Value>>) => {\n return (\n <Option\n label={item.label}\n onPress={() => onSelect(item.value)}\n disabled={item.disabled}\n selected={isSelected(item.value)}\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":"AAsBQ;AAtBR,SAAS,MAAoB,mBAAmB;AAChD,SAAS,gBAAoC;AAE7C,SAAS,cAAc;AACvB,SAAS,cAAc;AACvB,SAAS,YAAY;AACrB,SAAS,2BAA2B;AAGpC,SAAS,mBAAmB;AAC5B,SAAS,cAAc;AAEvB,MAAM,wBAAwB,SAAS,oBAErC,OAAiC;AACjC,QAAM,EAAE,SAAS,YAAY,UAAU,GAAG,KAAK,IAAI;AACnD,QAAM,SAAS,oBAAoB;AACnC,QAAM,eAAe,OAAO;AAE5B,QAAM,aAAa;AAAA,IACjB,CAAC,EAAE,KAAK,MAA+C;AACrD,aACE;AAAA,QAAC;AAAA;AAAA,UACC,OAAO,KAAK;AAAA,UACZ,SAAS,MAAM,SAAS,KAAK,KAAK;AAAA,UAClC,UAAU,KAAK;AAAA,UACf,UAAU,WAAW,KAAK,KAAK;AAAA;AAAA,MACjC;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":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@impulse-ui-native/select",
3
- "version": "2.3.5",
3
+ "version": "2.5.0",
4
4
  "description": "Accessible select and option picker components for ImpulseUI Native applications.",
5
5
  "keywords": [
6
6
  "react-native",
@@ -28,15 +28,13 @@
28
28
  ],
29
29
  "sideEffects": false,
30
30
  "dependencies": {
31
- "@impulse-ui-native/theme": "2.3.5",
32
- "@impulse-ui-native/input": "2.3.5",
33
- "@impulse-ui-native/icon": "2.3.5",
34
- "@impulse-ui-native/core": "2.3.5",
35
- "@impulse-ui-native/primitives": "2.3.5",
36
- "@impulse-ui-native/flyout": "2.3.5",
37
- "@impulse-ui-native/types": "2.3.5",
38
- "@impulse-ui-native/layers": "2.3.5",
39
- "@impulse-ui-native/portal": "2.3.5"
31
+ "@impulse-ui-native/theme": "2.5.0",
32
+ "@impulse-ui-native/input": "2.5.0",
33
+ "@impulse-ui-native/icon": "2.5.0",
34
+ "@impulse-ui-native/portal": "2.5.0",
35
+ "@impulse-ui-native/flyout": "2.5.0",
36
+ "@impulse-ui-native/primitives": "2.5.0",
37
+ "@impulse-ui-native/core": "2.5.0"
40
38
  },
41
39
  "devDependencies": {
42
40
  "@shopify/flash-list": "2.0.2",