@impulse-ui-native/select 9.1.2 → 11.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.
package/README.md CHANGED
@@ -55,4 +55,4 @@ export function DepartmentField() {
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
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.
58
+ On each opening, Select reveals its selected option. MultiSelect reveals the first selected option in list order. Lists that fit within the flyout stay at the top so all rows remain visible. Longer lists use native initial scrolling to reveal the opening selection. Options are single-line rows with a fixed `theme.components.select.option.height` (56 by default), also supplied to native `getItemLayout`. 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.
@@ -1,9 +1,8 @@
1
1
  import * as react from 'react';
2
- import * as react_jsx_runtime from 'react/jsx-runtime';
3
2
  import { OptionProps } from '../types/select.types.mjs';
4
3
  import '@impulse-ui-native/flyout';
5
4
  import '@impulse-ui-native/primitives';
6
5
 
7
- declare const Option: react.MemoExoticComponent<(props: OptionProps) => react_jsx_runtime.JSX.Element>;
6
+ declare const Option: react.MemoExoticComponent<(props: OptionProps) => react.JSX.Element>;
8
7
 
9
8
  export { Option };
@@ -1,41 +1,56 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
- import { memo } from "react";
2
+ import { memo, useCallback } from "react";
3
+ import { StyleSheet } from "react-native";
3
4
  import { Icon } from "@impulse-ui-native/icon";
4
5
  import { CheckIcon } from "@impulse-ui-native/icon/icons/check";
5
- import { Pressable, Typography, View } from "@impulse-ui-native/primitives";
6
+ import { Pressable, Typography } from "@impulse-ui-native/primitives";
6
7
  import {
7
8
  getSelectionItemStateTokens,
8
- useComponentsTokens
9
+ useComponentsTokens,
10
+ useStyleProps,
11
+ useThemedStyles
9
12
  } from "@impulse-ui-native/theme";
10
13
  const Option = memo(function Option2(props) {
11
- const { label, selected, ...rest } = props;
14
+ const { label, selected, style, ...rest } = props;
12
15
  const tokens = useComponentsTokens();
16
+ const styles = useThemedStyles(themedStyles);
17
+ const extractedStyleProps = useStyleProps(rest);
13
18
  const optionTokens = tokens.select.option;
14
19
  const appearanceTokens = getSelectionItemStateTokens(optionTokens.states, {
15
20
  selected
16
21
  });
17
- return /* @__PURE__ */ jsx(Pressable, { ...rest, children: /* @__PURE__ */ jsxs(
18
- View,
19
- {
20
- height: optionTokens.height,
21
- padding: optionTokens.padding,
22
+ const optionStyle = useCallback(
23
+ (state) => [
24
+ styles.option,
25
+ extractedStyleProps,
26
+ typeof style === "function" ? style(state) : style
27
+ ],
28
+ [extractedStyleProps, style, styles.option]
29
+ );
30
+ return /* @__PURE__ */ jsxs(Pressable, { ...rest, style: optionStyle, children: [
31
+ /* @__PURE__ */ jsx(Typography.Body, { flex: 1, numberOfLines: 1, ellipsizeMode: "tail", children: label }),
32
+ /* @__PURE__ */ jsx(
33
+ Icon,
34
+ {
35
+ icon: CheckIcon,
36
+ color: appearanceTokens.iconColor,
37
+ opacity: appearanceTokens.iconOpacity
38
+ }
39
+ )
40
+ ] });
41
+ });
42
+ function themedStyles(theme) {
43
+ const tokens = theme.components.select.option;
44
+ return StyleSheet.create({
45
+ option: {
46
+ height: tokens.height,
47
+ padding: tokens.padding,
22
48
  flexDirection: "row",
23
49
  alignItems: "center",
24
- justifyContent: "space-between",
25
- children: [
26
- /* @__PURE__ */ jsx(Typography.Body, { flex: 1, numberOfLines: 1, ellipsizeMode: "tail", children: label }),
27
- /* @__PURE__ */ jsx(
28
- Icon,
29
- {
30
- icon: CheckIcon,
31
- color: appearanceTokens.iconColor,
32
- opacity: appearanceTokens.iconOpacity
33
- }
34
- )
35
- ]
50
+ justifyContent: "space-between"
36
51
  }
37
- ) });
38
- });
52
+ });
53
+ }
39
54
  export {
40
55
  Option
41
56
  };
@@ -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 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"]}
1
+ {"version":3,"sources":["../../src/components/option.tsx"],"sourcesContent":["import type { PressableStateCallbackType } from \"react-native\";\nimport { memo, useCallback } from \"react\";\nimport { StyleSheet } from \"react-native\";\n\nimport type { AppTheme } from \"@impulse-ui-native/theme\";\nimport { Icon } from \"@impulse-ui-native/icon\";\nimport { CheckIcon } from \"@impulse-ui-native/icon/icons/check\";\nimport { Pressable, Typography } from \"@impulse-ui-native/primitives\";\nimport {\n getSelectionItemStateTokens,\n useComponentsTokens,\n useStyleProps,\n useThemedStyles,\n} from \"@impulse-ui-native/theme\";\n\nimport { OptionProps } from \"../types\";\n\nexport const Option = memo(function Option(props: OptionProps) {\n const { label, selected, style, ...rest } = props;\n\n const tokens = useComponentsTokens();\n const styles = useThemedStyles(themedStyles);\n const extractedStyleProps = useStyleProps(rest);\n\n const optionTokens = tokens.select.option;\n const appearanceTokens = getSelectionItemStateTokens(optionTokens.states, {\n selected,\n });\n\n const optionStyle = useCallback(\n (state: PressableStateCallbackType) => [\n styles.option,\n extractedStyleProps,\n typeof style === \"function\" ? style(state) : style,\n ],\n [extractedStyleProps, style, styles.option],\n );\n\n return (\n <Pressable {...rest} style={optionStyle}>\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 </Pressable>\n );\n});\n\nfunction themedStyles(theme: AppTheme) {\n const tokens = theme.components.select.option;\n\n return StyleSheet.create({\n option: {\n height: tokens.height,\n padding: tokens.padding,\n flexDirection: \"row\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n },\n });\n}\n"],"mappings":"AAuCI,SACE,KADF;AAtCJ,SAAS,MAAM,mBAAmB;AAClC,SAAS,kBAAkB;AAG3B,SAAS,YAAY;AACrB,SAAS,iBAAiB;AAC1B,SAAS,WAAW,kBAAkB;AACtC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAIA,MAAM,SAAS,KAAK,SAASA,QAAO,OAAoB;AAC7D,QAAM,EAAE,OAAO,UAAU,OAAO,GAAG,KAAK,IAAI;AAE5C,QAAM,SAAS,oBAAoB;AACnC,QAAM,SAAS,gBAAgB,YAAY;AAC3C,QAAM,sBAAsB,cAAc,IAAI;AAE9C,QAAM,eAAe,OAAO,OAAO;AACnC,QAAM,mBAAmB,4BAA4B,aAAa,QAAQ;AAAA,IACxE;AAAA,EACF,CAAC;AAED,QAAM,cAAc;AAAA,IAClB,CAAC,UAAsC;AAAA,MACrC,OAAO;AAAA,MACP;AAAA,MACA,OAAO,UAAU,aAAa,MAAM,KAAK,IAAI;AAAA,IAC/C;AAAA,IACA,CAAC,qBAAqB,OAAO,OAAO,MAAM;AAAA,EAC5C;AAEA,SACE,qBAAC,aAAW,GAAG,MAAM,OAAO,aAC1B;AAAA,wBAAC,WAAW,MAAX,EAAgB,MAAM,GAAG,eAAe,GAAG,eAAc,QACvD,iBACH;AAAA,IAEA;AAAA,MAAC;AAAA;AAAA,QACC,MAAM;AAAA,QACN,OAAO,iBAAiB;AAAA,QACxB,SAAS,iBAAiB;AAAA;AAAA,IAC5B;AAAA,KACF;AAEJ,CAAC;AAED,SAAS,aAAa,OAAiB;AACrC,QAAM,SAAS,MAAM,WAAW,OAAO;AAEvC,SAAO,WAAW,OAAO;AAAA,IACvB,QAAQ;AAAA,MACN,QAAQ,OAAO;AAAA,MACf,SAAS,OAAO;AAAA,MAChB,eAAe;AAAA,MACf,YAAY;AAAA,MACZ,gBAAgB;AAAA,IAClB;AAAA,EACF,CAAC;AACH;","names":["Option"]}
@@ -1,62 +1,34 @@
1
- import { jsx, jsxs } from "react/jsx-runtime";
2
- import { memo } from "react";
3
- import { Icon } from "@impulse-ui-native/icon";
4
- import { Control, Pressable } from "@impulse-ui-native/primitives";
5
- import {
6
- getFieldStateTokens,
7
- useComponentsTokens
8
- } from "@impulse-ui-native/theme";
9
- function SelectControlComponent(props) {
10
- const {
11
- size = "medium",
12
- variant = "outlined",
13
- label,
14
- error,
15
- disabled,
16
- loading,
17
- PrefixIcon,
18
- Prefix,
19
- onPressPrefix,
20
- SuffixIcon,
21
- Suffix,
22
- onPressSuffix,
23
- onPress,
24
- children
25
- } = props;
26
- const addonTokens = useComponentsTokens().controlAddon;
27
- const addonColor = getFieldStateTokens(addonTokens.variants[variant], {
28
- disabled,
29
- error: Boolean(error)
30
- }).iconColor;
31
- const SuffixContent = loading ? Control.Loader : Suffix;
32
- const hasPrefix = Prefix || PrefixIcon;
33
- const showPrefixIcon = !Prefix && PrefixIcon;
34
- const hasSuffix = SuffixContent || SuffixIcon;
35
- const showSuffixIcon = !SuffixContent && SuffixIcon;
36
- return /* @__PURE__ */ jsx(
37
- Control.Provider,
38
- {
39
- size,
40
- variant,
41
- error,
42
- disabled,
43
- children: /* @__PURE__ */ jsxs(Control.Root, { children: [
44
- /* @__PURE__ */ jsx(Control.Label, { children: label }),
45
- /* @__PURE__ */ jsx(Pressable, { onPress, children: /* @__PURE__ */ jsxs(Control.Container, { children: [
46
- hasPrefix ? /* @__PURE__ */ jsxs(Control.Addon, { onPress: onPressPrefix, children: [
47
- Prefix ? /* @__PURE__ */ jsx(Prefix, {}) : null,
48
- showPrefixIcon ? /* @__PURE__ */ jsx(Icon, { color: addonColor, icon: PrefixIcon }) : null
49
- ] }) : null,
50
- children,
51
- hasSuffix ? /* @__PURE__ */ jsxs(Control.Addon, { onPress: onPressSuffix, children: [
52
- SuffixContent ? /* @__PURE__ */ jsx(SuffixContent, {}) : null,
53
- showSuffixIcon ? /* @__PURE__ */ jsx(Icon, { color: addonColor, icon: SuffixIcon }) : null
54
- ] }) : null
55
- ] }) }),
56
- error ? /* @__PURE__ */ jsx(Control.Error, { children: error }) : null
57
- ] })
58
- }
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { memo, useMemo } from "react";
3
+ import { Control } from "@impulse-ui-native/primitives";
4
+ function SelectControlComponent({
5
+ loading,
6
+ PrefixIcon,
7
+ Prefix,
8
+ SuffixIcon,
9
+ Suffix,
10
+ children,
11
+ ...props
12
+ }) {
13
+ const prefix = useMemo(
14
+ () => {
15
+ if (Prefix) {
16
+ return /* @__PURE__ */ jsx(Prefix, {});
17
+ }
18
+ return PrefixIcon ? /* @__PURE__ */ jsx(Control.Icon, { icon: PrefixIcon }) : null;
19
+ },
20
+ [Prefix, PrefixIcon]
59
21
  );
22
+ const suffix = useMemo(() => {
23
+ if (loading) {
24
+ return /* @__PURE__ */ jsx(Control.Loader, {});
25
+ }
26
+ if (Suffix) {
27
+ return /* @__PURE__ */ jsx(Suffix, {});
28
+ }
29
+ return SuffixIcon ? /* @__PURE__ */ jsx(Control.Icon, { icon: SuffixIcon }) : null;
30
+ }, [loading, Suffix, SuffixIcon]);
31
+ return /* @__PURE__ */ jsx(Control.Field, { ...props, prefix, suffix, children });
60
32
  }
61
33
  const SelectControl = memo(SelectControlComponent);
62
34
  export {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/select-control.tsx"],"sourcesContent":["import type { PropsWithChildren, ReactElement } from \"react\";\nimport { memo } from \"react\";\n\nimport { Icon } from \"@impulse-ui-native/icon\";\nimport { Control, Pressable } from \"@impulse-ui-native/primitives\";\nimport {\n getFieldStateTokens,\n useComponentsTokens,\n} from \"@impulse-ui-native/theme\";\n\nimport type { PrimitiveValue, SelectControlProps } from \"../types\";\n\nfunction SelectControlComponent<Value extends PrimitiveValue>(\n props: PropsWithChildren<SelectControlProps<Value>>,\n) {\n const {\n size = \"medium\",\n variant = \"outlined\",\n label,\n error,\n disabled,\n loading,\n PrefixIcon,\n Prefix,\n onPressPrefix,\n SuffixIcon,\n Suffix,\n onPressSuffix,\n onPress,\n children,\n } = props;\n\n const addonTokens = useComponentsTokens().controlAddon;\n const addonColor = getFieldStateTokens(addonTokens.variants[variant], {\n disabled,\n error: Boolean(error),\n }).iconColor;\n\n const SuffixContent = loading ? Control.Loader : Suffix;\n\n const hasPrefix = Prefix || PrefixIcon;\n const showPrefixIcon = !Prefix && PrefixIcon;\n const hasSuffix = SuffixContent || SuffixIcon;\n const showSuffixIcon = !SuffixContent && SuffixIcon;\n\n return (\n <Control.Provider\n size={size}\n variant={variant}\n error={error}\n disabled={disabled}\n >\n <Control.Root>\n <Control.Label>{label}</Control.Label>\n <Pressable onPress={onPress}>\n <Control.Container>\n {hasPrefix ? (\n <Control.Addon onPress={onPressPrefix}>\n {Prefix ? <Prefix /> : null}\n {showPrefixIcon ? (\n <Icon color={addonColor} icon={PrefixIcon} />\n ) : null}\n </Control.Addon>\n ) : null}\n {children}\n {hasSuffix ? (\n <Control.Addon onPress={onPressSuffix}>\n {SuffixContent ? <SuffixContent /> : null}\n {showSuffixIcon ? (\n <Icon color={addonColor} icon={SuffixIcon} />\n ) : null}\n </Control.Addon>\n ) : null}\n </Control.Container>\n </Pressable>\n {error ? <Control.Error>{error}</Control.Error> : null}\n </Control.Root>\n </Control.Provider>\n );\n}\n\nexport const SelectControl = memo(SelectControlComponent) as <\n Value extends PrimitiveValue,\n>(\n props: PropsWithChildren<SelectControlProps<Value>>,\n) => ReactElement | null;\n"],"mappings":"AAqDQ,cAIM,YAJN;AApDR,SAAS,YAAY;AAErB,SAAS,YAAY;AACrB,SAAS,SAAS,iBAAiB;AACnC;AAAA,EACE;AAAA,EACA;AAAA,OACK;AAIP,SAAS,uBACP,OACA;AACA,QAAM;AAAA,IACJ,OAAO;AAAA,IACP,UAAU;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI;AAEJ,QAAM,cAAc,oBAAoB,EAAE;AAC1C,QAAM,aAAa,oBAAoB,YAAY,SAAS,OAAO,GAAG;AAAA,IACpE;AAAA,IACA,OAAO,QAAQ,KAAK;AAAA,EACtB,CAAC,EAAE;AAEH,QAAM,gBAAgB,UAAU,QAAQ,SAAS;AAEjD,QAAM,YAAY,UAAU;AAC5B,QAAM,iBAAiB,CAAC,UAAU;AAClC,QAAM,YAAY,iBAAiB;AACnC,QAAM,iBAAiB,CAAC,iBAAiB;AAEzC,SACE;AAAA,IAAC,QAAQ;AAAA,IAAR;AAAA,MACC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MAEA,+BAAC,QAAQ,MAAR,EACC;AAAA,4BAAC,QAAQ,OAAR,EAAe,iBAAM;AAAA,QACtB,oBAAC,aAAU,SACT,+BAAC,QAAQ,WAAR,EACE;AAAA,sBACC,qBAAC,QAAQ,OAAR,EAAc,SAAS,eACrB;AAAA,qBAAS,oBAAC,UAAO,IAAK;AAAA,YACtB,iBACC,oBAAC,QAAK,OAAO,YAAY,MAAM,YAAY,IACzC;AAAA,aACN,IACE;AAAA,UACH;AAAA,UACA,YACC,qBAAC,QAAQ,OAAR,EAAc,SAAS,eACrB;AAAA,4BAAgB,oBAAC,iBAAc,IAAK;AAAA,YACpC,iBACC,oBAAC,QAAK,OAAO,YAAY,MAAM,YAAY,IACzC;AAAA,aACN,IACE;AAAA,WACN,GACF;AAAA,QACC,QAAQ,oBAAC,QAAQ,OAAR,EAAe,iBAAM,IAAmB;AAAA,SACpD;AAAA;AAAA,EACF;AAEJ;AAEO,MAAM,gBAAgB,KAAK,sBAAsB;","names":[]}
1
+ {"version":3,"sources":["../../src/components/select-control.tsx"],"sourcesContent":["import type { PropsWithChildren, ReactElement } from \"react\";\nimport { memo, useMemo } from \"react\";\n\nimport { Control } from \"@impulse-ui-native/primitives\";\n\nimport type { PrimitiveValue, SelectControlProps } from \"../types\";\n\nfunction SelectControlComponent<Value extends PrimitiveValue>({\n loading,\n PrefixIcon,\n Prefix,\n SuffixIcon,\n Suffix,\n children,\n ...props\n}: PropsWithChildren<SelectControlProps<Value>>) {\n const prefix = useMemo(\n () => {\n if (Prefix) {\n return <Prefix />;\n }\n\n return PrefixIcon ? <Control.Icon icon={PrefixIcon} /> : null;\n },\n [Prefix, PrefixIcon],\n );\n const suffix = useMemo(() => {\n if (loading) {\n return <Control.Loader />;\n }\n\n if (Suffix) {\n return <Suffix />;\n }\n\n return SuffixIcon ? <Control.Icon icon={SuffixIcon} /> : null;\n }, [loading, Suffix, SuffixIcon]);\n\n return (\n <Control.Field {...props} prefix={prefix} suffix={suffix}>\n {children}\n </Control.Field>\n );\n}\n\nexport const SelectControl = memo(SelectControlComponent) as <\n Value extends PrimitiveValue,\n>(\n props: PropsWithChildren<SelectControlProps<Value>>,\n) => ReactElement | null;\n"],"mappings":"AAmBe;AAlBf,SAAS,MAAM,eAAe;AAE9B,SAAS,eAAe;AAIxB,SAAS,uBAAqD;AAAA,EAC5D;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAAiD;AAC/C,QAAM,SAAS;AAAA,IACb,MAAM;AACJ,UAAI,QAAQ;AACV,eAAO,oBAAC,UAAO;AAAA,MACjB;AAEA,aAAO,aAAa,oBAAC,QAAQ,MAAR,EAAa,MAAM,YAAY,IAAK;AAAA,IAC3D;AAAA,IACA,CAAC,QAAQ,UAAU;AAAA,EACrB;AACA,QAAM,SAAS,QAAQ,MAAM;AAC3B,QAAI,SAAS;AACX,aAAO,oBAAC,QAAQ,QAAR,EAAe;AAAA,IACzB;AAEA,QAAI,QAAQ;AACV,aAAO,oBAAC,UAAO;AAAA,IACjB;AAEA,WAAO,aAAa,oBAAC,QAAQ,MAAR,EAAa,MAAM,YAAY,IAAK;AAAA,EAC3D,GAAG,CAAC,SAAS,QAAQ,UAAU,CAAC;AAEhC,SACE,oBAAC,QAAQ,OAAR,EAAe,GAAG,OAAO,QAAgB,QACvC,UACH;AAEJ;AAEO,MAAM,gBAAgB,KAAK,sBAAsB;","names":[]}
@@ -1,5 +1,5 @@
1
1
  import { jsx } from "react/jsx-runtime";
2
- import { memo, useCallback, useRef } from "react";
2
+ import { memo, useCallback, useMemo, useRef } from "react";
3
3
  import {
4
4
  FlatList,
5
5
  useFlatListInitialScroll
@@ -10,23 +10,34 @@ import { SelectFlyoutOption } from "./select-flyout-option";
10
10
  const SelectOptionsComponent = function SelectOptions(props) {
11
11
  const { options, isSelected, onSelect, initialScrollToSelected } = props;
12
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)
13
+ const { select: tokens } = useComponentsTokens();
14
+ const optionHeight = tokens.option.height;
15
+ const optionsHeight = options.length * optionHeight;
16
+ const canScroll = optionsHeight > tokens.flyoutHeight;
17
+ const selectedIndex = useMemo(
18
+ () => options.findIndex(
19
+ (option) => option.value !== null && option.value !== void 0 && initialSelection.current(option.value)
20
+ ),
21
+ [options]
16
22
  );
23
+ const shouldScrollToSelected = initialScrollToSelected && canScroll && selectedIndex >= 0;
24
+ const initialScrollIndex = shouldScrollToSelected ? selectedIndex : void 0;
17
25
  const initialScroll = useFlatListInitialScroll({
18
- itemSize: tokens.select.option.height,
19
- initialScrollIndex: initialScrollToSelected && selectedIndex >= 0 ? selectedIndex : void 0
26
+ itemSize: optionHeight,
27
+ initialScrollIndex
20
28
  });
21
29
  const renderItem = useCallback(
22
- ({ item }) => /* @__PURE__ */ jsx(
23
- SelectFlyoutOption,
24
- {
25
- option: item,
26
- selected: isSelected(item.value),
27
- onSelect
28
- }
29
- ),
30
+ ({ item }) => {
31
+ const selected = isSelected(item.value);
32
+ return /* @__PURE__ */ jsx(
33
+ SelectFlyoutOption,
34
+ {
35
+ option: item,
36
+ selected,
37
+ onSelect
38
+ }
39
+ );
40
+ },
30
41
  [isSelected, onSelect]
31
42
  );
32
43
  return /* @__PURE__ */ jsx(
@@ -1 +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
+ {"version":3,"sources":["../../src/components/select-options.tsx"],"sourcesContent":["import type { ListRenderItemInfo } from \"react-native\";\nimport { memo, ReactElement, useCallback, useMemo, 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 { select: tokens } = useComponentsTokens();\n\n const optionHeight = tokens.option.height;\n const optionsHeight = options.length * optionHeight;\n const canScroll = optionsHeight > tokens.flyoutHeight;\n\n const selectedIndex = useMemo(\n () =>\n options.findIndex(\n (option) =>\n option.value !== null &&\n option.value !== undefined &&\n initialSelection.current(option.value),\n ),\n [options],\n );\n\n const shouldScrollToSelected =\n initialScrollToSelected && canScroll && selectedIndex >= 0;\n const initialScrollIndex = shouldScrollToSelected ? selectedIndex : undefined;\n\n const initialScroll = useFlatListInitialScroll<SelectOption<Value>>({\n itemSize: optionHeight,\n initialScrollIndex,\n });\n\n const renderItem = useCallback(\n ({ item }: ListRenderItemInfo<SelectOption<Value>>) => {\n const selected = isSelected(item.value);\n\n return (\n <SelectFlyoutOption\n option={item}\n selected={selected}\n onSelect={onSelect}\n />\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":"AAoDQ;AAnDR,SAAS,MAAoB,aAAa,SAAS,cAAc;AAEjE;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,EAAE,QAAQ,OAAO,IAAI,oBAAoB;AAE/C,QAAM,eAAe,OAAO,OAAO;AACnC,QAAM,gBAAgB,QAAQ,SAAS;AACvC,QAAM,YAAY,gBAAgB,OAAO;AAEzC,QAAM,gBAAgB;AAAA,IACpB,MACE,QAAQ;AAAA,MACN,CAAC,WACC,OAAO,UAAU,QACjB,OAAO,UAAU,UACjB,iBAAiB,QAAQ,OAAO,KAAK;AAAA,IACzC;AAAA,IACF,CAAC,OAAO;AAAA,EACV;AAEA,QAAM,yBACJ,2BAA2B,aAAa,iBAAiB;AAC3D,QAAM,qBAAqB,yBAAyB,gBAAgB;AAEpE,QAAM,gBAAgB,yBAA8C;AAAA,IAClE,UAAU;AAAA,IACV;AAAA,EACF,CAAC;AAED,QAAM,aAAa;AAAA,IACjB,CAAC,EAAE,KAAK,MAA+C;AACrD,YAAM,WAAW,WAAW,KAAK,KAAK;AAEtC,aACE;AAAA,QAAC;AAAA;AAAA,UACC,QAAQ;AAAA,UACR;AAAA,UACA;AAAA;AAAA,MACF;AAAA,IAEJ;AAAA,IACA,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"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@impulse-ui-native/select",
3
- "version": "9.1.2",
3
+ "version": "11.0.0",
4
4
  "description": "Select and option picker components for ImpulseUI Native applications.",
5
5
  "keywords": [
6
6
  "react-native",
@@ -28,25 +28,25 @@
28
28
  ],
29
29
  "sideEffects": false,
30
30
  "dependencies": {
31
- "@impulse-ui-native/theme": "9.1.2",
32
- "@impulse-ui-native/icon": "9.1.2",
33
- "@impulse-ui-native/core": "9.1.2",
34
- "@impulse-ui-native/primitives": "9.1.2",
35
- "@impulse-ui-native/input": "9.1.2",
36
- "@impulse-ui-native/flyout": "9.1.2",
37
- "@impulse-ui-native/portal": "9.1.2",
38
- "@impulse-ui-native/flat-list": "9.1.2"
31
+ "@impulse-ui-native/theme": "11.0.0",
32
+ "@impulse-ui-native/input": "11.0.0",
33
+ "@impulse-ui-native/icon": "11.0.0",
34
+ "@impulse-ui-native/core": "11.0.0",
35
+ "@impulse-ui-native/primitives": "11.0.0",
36
+ "@impulse-ui-native/flyout": "11.0.0",
37
+ "@impulse-ui-native/portal": "11.0.0",
38
+ "@impulse-ui-native/flat-list": "11.0.0"
39
39
  },
40
40
  "devDependencies": {
41
- "@types/react": "~19.2.14",
41
+ "@impulse-ui-native/eslint-config": "1.0.0",
42
+ "@impulse-ui-native/prettier-config": "1.0.0",
43
+ "@impulse-ui-native/tsconfig": "1.0.0",
44
+ "@types/react": "~19.3.0",
42
45
  "eslint": "^9.38.0",
43
46
  "prettier": "^3.6.2",
44
- "react": "19.2.3",
45
- "react-native": "0.86.2",
46
- "typescript": "~6.0.3",
47
- "@impulse-ui-native/prettier-config": "1.0.0",
48
- "@impulse-ui-native/eslint-config": "1.0.0",
49
- "@impulse-ui-native/tsconfig": "1.0.0"
47
+ "react": "19.3.0",
48
+ "react-native": "0.88.0",
49
+ "typescript": "~6.0.3"
50
50
  },
51
51
  "peerDependencies": {
52
52
  "react": ">=18",