@react-stately/select 3.0.0-nightly-6a86b5cdd-250829 → 3.0.0-nightly-e717ee924-250830

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/dist/types.d.ts CHANGED
@@ -1,13 +1,39 @@
1
- import { CollectionStateBase, FocusStrategy, Key } from "@react-types/shared";
1
+ import { CollectionStateBase, FocusStrategy, Key, Node } from "@react-types/shared";
2
2
  import { FormValidationState } from "@react-stately/form";
3
+ import { ListState } from "@react-stately/list";
3
4
  import { OverlayTriggerState } from "@react-stately/overlays";
4
- import { SelectProps } from "@react-types/select";
5
- import { SingleSelectListState } from "@react-stately/list";
6
- export interface SelectStateOptions<T> extends Omit<SelectProps<T>, 'children'>, CollectionStateBase<T> {
5
+ import { SelectionMode, SelectProps, ValueType } from "@react-types/select";
6
+ export interface SelectStateOptions<T, M extends SelectionMode = 'single'> extends Omit<SelectProps<T, M>, 'children'>, CollectionStateBase<T> {
7
7
  }
8
- export interface SelectState<T> extends SingleSelectListState<T>, OverlayTriggerState, FormValidationState {
9
- /** The default selected key. */
8
+ export interface SelectState<T, M extends SelectionMode = 'single'> extends ListState<T>, OverlayTriggerState, FormValidationState {
9
+ /**
10
+ * The key for the first selected item.
11
+ * @deprecated
12
+ */
13
+ readonly selectedKey: Key | null;
14
+ /**
15
+ * The default selected key.
16
+ * @deprecated
17
+ */
10
18
  readonly defaultSelectedKey: Key | null;
19
+ /**
20
+ * Sets the selected key.
21
+ * @deprecated
22
+ */
23
+ setSelectedKey(key: Key | null): void;
24
+ /** The current select value. */
25
+ readonly value: ValueType<M>;
26
+ /** The default select value. */
27
+ readonly defaultValue: ValueType<M>;
28
+ /** Sets the select value. */
29
+ setValue(value: Key | Key[] | null): void;
30
+ /**
31
+ * The value of the first selected item.
32
+ * @deprecated
33
+ */
34
+ readonly selectedItem: Node<T> | null;
35
+ /** The value of the selected items. */
36
+ readonly selectedItems: Node<T>[];
11
37
  /** Whether the select is currently focused. */
12
38
  readonly isFocused: boolean;
13
39
  /** Sets whether the select is focused. */
@@ -24,7 +50,7 @@ export interface SelectState<T> extends SingleSelectListState<T>, OverlayTrigger
24
50
  * of items from props, handles the open state for the popup menu, and manages
25
51
  * multiple selection state.
26
52
  */
27
- export function useSelectState<T extends object>(props: SelectStateOptions<T>): SelectState<T>;
53
+ export function useSelectState<T extends object, M extends SelectionMode = 'single'>(props: SelectStateOptions<T, M>): SelectState<T, M>;
28
54
  export type { SelectProps } from '@react-types/select';
29
55
 
30
56
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"mappings":";;;;;AAmBA,oCAAoC,CAAC,CAAE,SAAQ,IAAI,CAAC,YAAY,CAAC,CAAC,EAAE,UAAU,CAAC,EAAE,oBAAoB,CAAC,CAAC;CAAG;AAE1G,6BAA6B,CAAC,CAAE,SAAQ,sBAAsB,CAAC,CAAC,EAAE,mBAAmB,EAAE,mBAAmB;IACxG,gCAAgC;IAChC,QAAQ,CAAC,kBAAkB,EAAE,GAAG,GAAG,IAAI,CAAC;IAExC,+CAA+C;IAC/C,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAE5B,0CAA0C;IAC1C,UAAU,CAAC,SAAS,EAAE,OAAO,GAAG,IAAI,CAAC;IAErC,oEAAoE;IACpE,QAAQ,CAAC,aAAa,EAAE,aAAa,GAAG,IAAI,CAAC;IAE7C,sBAAsB;IACtB,IAAI,CAAC,aAAa,CAAC,EAAE,aAAa,GAAG,IAAI,GAAG,IAAI,CAAC;IAEjD,wBAAwB;IACxB,MAAM,CAAC,aAAa,CAAC,EAAE,aAAa,GAAG,IAAI,GAAG,IAAI,CAAA;CACnD;AAED;;;;GAIG;AACH,+BAA+B,CAAC,SAAS,MAAM,EAAE,KAAK,EAAE,mBAAmB,CAAC,CAAC,GAAG,YAAY,CAAC,CAAC,CA6C7F;AC7ED,YAAY,EAAC,WAAW,EAAC,MAAM,qBAAqB,CAAC","sources":["packages/@react-stately/select/src/packages/@react-stately/select/src/useSelectState.ts","packages/@react-stately/select/src/packages/@react-stately/select/src/index.ts","packages/@react-stately/select/src/index.ts"],"sourcesContent":[null,null,"/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nexport {useSelectState} from './useSelectState';\n\nexport type {SelectProps} from '@react-types/select';\nexport type {SelectState, SelectStateOptions} from './useSelectState';\n"],"names":[],"version":3,"file":"types.d.ts.map"}
1
+ {"mappings":";;;;;AAoBA,oCAAoC,CAAC,EAAE,CAAC,SAAS,aAAa,GAAG,QAAQ,CAAE,SAAQ,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC,EAAE,UAAU,CAAC,EAAE,oBAAoB,CAAC,CAAC;CAAG;AAEjJ,6BAA6B,CAAC,EAAE,CAAC,SAAS,aAAa,GAAG,QAAQ,CAAE,SAAQ,UAAU,CAAC,CAAC,EAAE,mBAAmB,EAAE,mBAAmB;IAChI;;;OAGG;IACH,QAAQ,CAAC,WAAW,EAAE,GAAG,GAAG,IAAI,CAAC;IAEjC;;;OAGG;IACH,QAAQ,CAAC,kBAAkB,EAAE,GAAG,GAAG,IAAI,CAAC;IAExC;;;OAGG;IACH,cAAc,CAAC,GAAG,EAAE,GAAG,GAAG,IAAI,GAAG,IAAI,CAAC;IAEtC,gCAAgC;IAChC,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC;IAE7B,gCAAgC;IAChC,QAAQ,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC,CAAC;IAEpC,6BAA6B;IAC7B,QAAQ,CAAC,KAAK,EAAE,GAAG,GAAG,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC;IAE1C;;;OAGG;IACH,QAAQ,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC,GAAG,IAAI,CAAC;IAEtC,uCAAuC;IACvC,QAAQ,CAAC,aAAa,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC;IAElC,+CAA+C;IAC/C,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAE5B,0CAA0C;IAC1C,UAAU,CAAC,SAAS,EAAE,OAAO,GAAG,IAAI,CAAC;IAErC,oEAAoE;IACpE,QAAQ,CAAC,aAAa,EAAE,aAAa,GAAG,IAAI,CAAC;IAE7C,sBAAsB;IACtB,IAAI,CAAC,aAAa,CAAC,EAAE,aAAa,GAAG,IAAI,GAAG,IAAI,CAAC;IAEjD,wBAAwB;IACxB,MAAM,CAAC,aAAa,CAAC,EAAE,aAAa,GAAG,IAAI,GAAG,IAAI,CAAA;CACnD;AAED;;;;GAIG;AACH,+BAA+B,CAAC,SAAS,MAAM,EAAE,CAAC,SAAS,aAAa,GAAG,QAAQ,EAAE,KAAK,EAAE,mBAAmB,CAAC,EAAE,CAAC,CAAC,GAAG,YAAY,CAAC,EAAE,CAAC,CAAC,CAgGvI;AClKD,YAAY,EAAC,WAAW,EAAC,MAAM,qBAAqB,CAAC","sources":["packages/@react-stately/select/src/packages/@react-stately/select/src/useSelectState.ts","packages/@react-stately/select/src/packages/@react-stately/select/src/index.ts","packages/@react-stately/select/src/index.ts"],"sourcesContent":[null,null,"/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nexport {useSelectState} from './useSelectState';\n\nexport type {SelectProps} from '@react-types/select';\nexport type {SelectState, SelectStateOptions} from './useSelectState';\n"],"names":[],"version":3,"file":"types.d.ts.map"}
@@ -1,6 +1,7 @@
1
1
  var $5KJtg$reactstatelyform = require("@react-stately/form");
2
- var $5KJtg$reactstatelyoverlays = require("@react-stately/overlays");
3
2
  var $5KJtg$reactstatelylist = require("@react-stately/list");
3
+ var $5KJtg$reactstatelyoverlays = require("@react-stately/overlays");
4
+ var $5KJtg$reactstatelyutils = require("@react-stately/utils");
4
5
  var $5KJtg$react = require("react");
5
6
 
6
7
 
@@ -23,29 +24,94 @@ $parcel$export(module.exports, "useSelectState", () => $80ebb60e77198879$export$
23
24
 
24
25
 
25
26
 
27
+
26
28
  function $80ebb60e77198879$export$5159ec8b34d4ec12(props) {
29
+ let { selectionMode: selectionMode = 'single' } = props;
27
30
  let triggerState = (0, $5KJtg$reactstatelyoverlays.useOverlayTriggerState)(props);
28
31
  let [focusStrategy, setFocusStrategy] = (0, $5KJtg$react.useState)(null);
29
- let listState = (0, $5KJtg$reactstatelylist.useSingleSelectListState)({
32
+ let defaultValue = (0, $5KJtg$react.useMemo)(()=>{
33
+ var _props_defaultSelectedKey, _props_defaultValue;
34
+ return (_props_defaultValue = props.defaultValue) !== null && _props_defaultValue !== void 0 ? _props_defaultValue : selectionMode === 'single' ? (_props_defaultSelectedKey = props.defaultSelectedKey) !== null && _props_defaultSelectedKey !== void 0 ? _props_defaultSelectedKey : null : [];
35
+ }, [
36
+ props.defaultValue,
37
+ props.defaultSelectedKey,
38
+ selectionMode
39
+ ]);
40
+ let value = (0, $5KJtg$react.useMemo)(()=>{
41
+ var _props_value;
42
+ return (_props_value = props.value) !== null && _props_value !== void 0 ? _props_value : selectionMode === 'single' ? props.selectedKey : undefined;
43
+ }, [
44
+ props.value,
45
+ props.selectedKey,
46
+ selectionMode
47
+ ]);
48
+ let [controlledValue, setControlledValue] = (0, $5KJtg$reactstatelyutils.useControlledState)(value, defaultValue, props.onChange);
49
+ let setValue = (value)=>{
50
+ if (selectionMode === 'single') {
51
+ var _props_onSelectionChange;
52
+ var _value_;
53
+ let key = Array.isArray(value) ? (_value_ = value[0]) !== null && _value_ !== void 0 ? _value_ : null : value;
54
+ setControlledValue(key);
55
+ if (key !== controlledValue) (_props_onSelectionChange = props.onSelectionChange) === null || _props_onSelectionChange === void 0 ? void 0 : _props_onSelectionChange.call(props, key);
56
+ } else {
57
+ let keys = [];
58
+ if (Array.isArray(value)) keys = value;
59
+ else if (value != null) keys = [
60
+ value
61
+ ];
62
+ setControlledValue(keys);
63
+ }
64
+ };
65
+ let listState = (0, $5KJtg$reactstatelylist.useListState)({
30
66
  ...props,
31
- onSelectionChange: (key)=>{
32
- if (props.onSelectionChange != null) props.onSelectionChange(key);
33
- triggerState.close();
67
+ selectionMode: selectionMode,
68
+ disallowEmptySelection: selectionMode === 'single',
69
+ allowDuplicateSelectionEvents: true,
70
+ selectedKeys: (0, $5KJtg$react.useMemo)(()=>$80ebb60e77198879$var$convertValue(controlledValue), [
71
+ controlledValue
72
+ ]),
73
+ onSelectionChange: (keys)=>{
74
+ // impossible, but TS doesn't know that
75
+ if (keys === 'all') return;
76
+ if (selectionMode === 'single') {
77
+ var _keys_values_next_value;
78
+ let key = (_keys_values_next_value = keys.values().next().value) !== null && _keys_values_next_value !== void 0 ? _keys_values_next_value : null;
79
+ setValue(key);
80
+ triggerState.close();
81
+ } else setValue([
82
+ ...keys
83
+ ]);
34
84
  validationState.commitValidation();
35
85
  }
36
86
  });
87
+ let selectedKey = listState.selectionManager.firstSelectedKey;
88
+ let selectedItems = (0, $5KJtg$react.useMemo)(()=>{
89
+ return [
90
+ ...listState.selectionManager.selectedKeys
91
+ ].map((key)=>listState.collection.getItem(key)).filter((item)=>item != null);
92
+ }, [
93
+ listState.selectionManager.selectedKeys,
94
+ listState.collection
95
+ ]);
37
96
  let validationState = (0, $5KJtg$reactstatelyform.useFormValidationState)({
38
97
  ...props,
39
- value: listState.selectedKey
98
+ value: Array.isArray(controlledValue) && controlledValue.length === 0 ? null : controlledValue
40
99
  });
41
100
  let [isFocused, setFocused] = (0, $5KJtg$react.useState)(false);
42
- let [initialSelectedKey] = (0, $5KJtg$react.useState)(listState.selectedKey);
43
- var _props_defaultSelectedKey;
101
+ let [initialValue] = (0, $5KJtg$react.useState)(controlledValue);
102
+ var _selectedItems_, _props_defaultSelectedKey;
44
103
  return {
45
104
  ...validationState,
46
105
  ...listState,
47
106
  ...triggerState,
48
- defaultSelectedKey: (_props_defaultSelectedKey = props.defaultSelectedKey) !== null && _props_defaultSelectedKey !== void 0 ? _props_defaultSelectedKey : initialSelectedKey,
107
+ value: controlledValue,
108
+ defaultValue: defaultValue !== null && defaultValue !== void 0 ? defaultValue : initialValue,
109
+ setValue: setValue,
110
+ selectedKey: selectedKey,
111
+ setSelectedKey: setValue,
112
+ selectedItem: (_selectedItems_ = selectedItems[0]) !== null && _selectedItems_ !== void 0 ? _selectedItems_ : null,
113
+ selectedItems: selectedItems,
114
+ defaultSelectedKey: (_props_defaultSelectedKey = props.defaultSelectedKey) !== null && _props_defaultSelectedKey !== void 0 ? _props_defaultSelectedKey : props.selectionMode === 'single' ? initialValue : null,
49
115
  focusStrategy: focusStrategy,
50
116
  open (focusStrategy = null) {
51
117
  // Don't open if the collection is empty.
@@ -64,6 +130,13 @@ function $80ebb60e77198879$export$5159ec8b34d4ec12(props) {
64
130
  setFocused: setFocused
65
131
  };
66
132
  }
133
+ function $80ebb60e77198879$var$convertValue(value) {
134
+ if (value === undefined) return undefined;
135
+ if (value === null) return [];
136
+ return Array.isArray(value) ? value : [
137
+ value
138
+ ];
139
+ }
67
140
 
68
141
 
69
142
  //# sourceMappingURL=useSelectState.main.js.map
@@ -1 +1 @@
1
- {"mappings":";;;;;;;;;;;AAAA;;;;;;;;;;CAUC;;;;AAoCM,SAAS,0CAAiC,KAA4B;IAC3E,IAAI,eAAe,CAAA,GAAA,kDAAqB,EAAE;IAC1C,IAAI,CAAC,eAAe,iBAAiB,GAAG,CAAA,GAAA,qBAAO,EAAwB;IACvE,IAAI,YAAY,CAAA,GAAA,gDAAuB,EAAE;QACvC,GAAG,KAAK;QACR,mBAAmB,CAAC;YAClB,IAAI,MAAM,iBAAiB,IAAI,MAC7B,MAAM,iBAAiB,CAAC;YAG1B,aAAa,KAAK;YAClB,gBAAgB,gBAAgB;QAClC;IACF;IAEA,IAAI,kBAAkB,CAAA,GAAA,8CAAqB,EAAE;QAC3C,GAAG,KAAK;QACR,OAAO,UAAU,WAAW;IAC9B;IAEA,IAAI,CAAC,WAAW,WAAW,GAAG,CAAA,GAAA,qBAAO,EAAE;IACvC,IAAI,CAAC,mBAAmB,GAAG,CAAA,GAAA,qBAAO,EAAE,UAAU,WAAW;QAMnC;IAJtB,OAAO;QACL,GAAG,eAAe;QAClB,GAAG,SAAS;QACZ,GAAG,YAAY;QACf,oBAAoB,CAAA,4BAAA,MAAM,kBAAkB,cAAxB,uCAAA,4BAA4B;uBAChD;QACA,MAAK,gBAAsC,IAAI;YAC7C,yCAAyC;YACzC,IAAI,UAAU,UAAU,CAAC,IAAI,KAAK,GAAG;gBACnC,iBAAiB;gBACjB,aAAa,IAAI;YACnB;QACF;QACA,QAAO,gBAAsC,IAAI;YAC/C,IAAI,UAAU,UAAU,CAAC,IAAI,KAAK,GAAG;gBACnC,iBAAiB;gBACjB,aAAa,MAAM;YACrB;QACF;mBACA;oBACA;IACF;AACF","sources":["packages/@react-stately/select/src/useSelectState.ts"],"sourcesContent":["/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {CollectionStateBase, FocusStrategy, Key} from '@react-types/shared';\nimport {FormValidationState, useFormValidationState} from '@react-stately/form';\nimport {OverlayTriggerState, useOverlayTriggerState} from '@react-stately/overlays';\nimport {SelectProps} from '@react-types/select';\nimport {SingleSelectListState, useSingleSelectListState} from '@react-stately/list';\nimport {useState} from 'react';\n\nexport interface SelectStateOptions<T> extends Omit<SelectProps<T>, 'children'>, CollectionStateBase<T> {}\n\nexport interface SelectState<T> extends SingleSelectListState<T>, OverlayTriggerState, FormValidationState {\n /** The default selected key. */\n readonly defaultSelectedKey: Key | null,\n\n /** Whether the select is currently focused. */\n readonly isFocused: boolean,\n\n /** Sets whether the select is focused. */\n setFocused(isFocused: boolean): void,\n\n /** Controls which item will be auto focused when the menu opens. */\n readonly focusStrategy: FocusStrategy | null,\n\n /** Opens the menu. */\n open(focusStrategy?: FocusStrategy | null): void,\n\n /** Toggles the menu. */\n toggle(focusStrategy?: FocusStrategy | null): void\n}\n\n/**\n * Provides state management for a select component. Handles building a collection\n * of items from props, handles the open state for the popup menu, and manages\n * multiple selection state.\n */\nexport function useSelectState<T extends object>(props: SelectStateOptions<T>): SelectState<T> {\n let triggerState = useOverlayTriggerState(props);\n let [focusStrategy, setFocusStrategy] = useState<FocusStrategy | null>(null);\n let listState = useSingleSelectListState({\n ...props,\n onSelectionChange: (key) => {\n if (props.onSelectionChange != null) {\n props.onSelectionChange(key);\n }\n\n triggerState.close();\n validationState.commitValidation();\n }\n });\n\n let validationState = useFormValidationState({\n ...props,\n value: listState.selectedKey\n });\n\n let [isFocused, setFocused] = useState(false);\n let [initialSelectedKey] = useState(listState.selectedKey);\n\n return {\n ...validationState,\n ...listState,\n ...triggerState,\n defaultSelectedKey: props.defaultSelectedKey ?? initialSelectedKey,\n focusStrategy,\n open(focusStrategy: FocusStrategy | null = null) {\n // Don't open if the collection is empty.\n if (listState.collection.size !== 0) {\n setFocusStrategy(focusStrategy);\n triggerState.open();\n }\n },\n toggle(focusStrategy: FocusStrategy | null = null) {\n if (listState.collection.size !== 0) {\n setFocusStrategy(focusStrategy);\n triggerState.toggle();\n }\n },\n isFocused,\n setFocused\n };\n}\n"],"names":[],"version":3,"file":"useSelectState.main.js.map"}
1
+ {"mappings":"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","sources":["packages/@react-stately/select/src/useSelectState.ts"],"sourcesContent":["/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {CollectionStateBase, FocusStrategy, Key, Node, Selection} from '@react-types/shared';\nimport {FormValidationState, useFormValidationState} from '@react-stately/form';\nimport {ListState, useListState} from '@react-stately/list';\nimport {OverlayTriggerState, useOverlayTriggerState} from '@react-stately/overlays';\nimport {SelectionMode, SelectProps, ValueType} from '@react-types/select';\nimport {useControlledState} from '@react-stately/utils';\nimport {useMemo, useState} from 'react';\n\nexport interface SelectStateOptions<T, M extends SelectionMode = 'single'> extends Omit<SelectProps<T, M>, 'children'>, CollectionStateBase<T> {}\n\nexport interface SelectState<T, M extends SelectionMode = 'single'> extends ListState<T>, OverlayTriggerState, FormValidationState {\n /**\n * The key for the first selected item.\n * @deprecated\n */\n readonly selectedKey: Key | null,\n\n /**\n * The default selected key.\n * @deprecated\n */\n readonly defaultSelectedKey: Key | null,\n\n /**\n * Sets the selected key.\n * @deprecated\n */\n setSelectedKey(key: Key | null): void,\n\n /** The current select value. */\n readonly value: ValueType<M>,\n\n /** The default select value. */\n readonly defaultValue: ValueType<M>,\n\n /** Sets the select value. */\n setValue(value: Key | Key[] | null): void,\n\n /**\n * The value of the first selected item.\n * @deprecated\n */\n readonly selectedItem: Node<T> | null,\n\n /** The value of the selected items. */\n readonly selectedItems: Node<T>[],\n\n /** Whether the select is currently focused. */\n readonly isFocused: boolean,\n\n /** Sets whether the select is focused. */\n setFocused(isFocused: boolean): void,\n\n /** Controls which item will be auto focused when the menu opens. */\n readonly focusStrategy: FocusStrategy | null,\n\n /** Opens the menu. */\n open(focusStrategy?: FocusStrategy | null): void,\n\n /** Toggles the menu. */\n toggle(focusStrategy?: FocusStrategy | null): void\n}\n\n/**\n * Provides state management for a select component. Handles building a collection\n * of items from props, handles the open state for the popup menu, and manages\n * multiple selection state.\n */\nexport function useSelectState<T extends object, M extends SelectionMode = 'single'>(props: SelectStateOptions<T, M>): SelectState<T, M> {\n let {selectionMode = 'single' as M} = props;\n let triggerState = useOverlayTriggerState(props);\n let [focusStrategy, setFocusStrategy] = useState<FocusStrategy | null>(null);\n let defaultValue = useMemo(() => {\n return props.defaultValue ?? (selectionMode === 'single' ? props.defaultSelectedKey ?? null : []) as ValueType<M>;\n }, [props.defaultValue, props.defaultSelectedKey, selectionMode]);\n let value = useMemo(() => {\n return props.value ?? (selectionMode === 'single' ? props.selectedKey : undefined) as ValueType<M>;\n }, [props.value, props.selectedKey, selectionMode]);\n let [controlledValue, setControlledValue] = useControlledState<ValueType<M>>(value as any, defaultValue as any, props.onChange);\n let setValue = (value: Key | Key[] | null) => {\n if (selectionMode === 'single') {\n let key = Array.isArray(value) ? value[0] ?? null : value;\n setControlledValue(key as ValueType<M>);\n if (key !== controlledValue) {\n props.onSelectionChange?.(key);\n }\n } else {\n let keys: Key[] = [];\n if (Array.isArray(value)) {\n keys = value;\n } else if (value != null) {\n keys = [value];\n }\n\n setControlledValue(keys as ValueType<M>);\n }\n };\n\n let listState = useListState({\n ...props,\n selectionMode,\n disallowEmptySelection: selectionMode === 'single',\n allowDuplicateSelectionEvents: true,\n selectedKeys: useMemo(() => convertValue(controlledValue), [controlledValue]),\n onSelectionChange: (keys: Selection) => {\n // impossible, but TS doesn't know that\n if (keys === 'all') {\n return;\n }\n\n if (selectionMode === 'single') {\n let key = keys.values().next().value ?? null;\n setValue(key);\n triggerState.close();\n } else {\n setValue([...keys]);\n }\n\n validationState.commitValidation();\n }\n });\n\n let selectedKey = listState.selectionManager.firstSelectedKey;\n let selectedItems = useMemo(() => {\n return [...listState.selectionManager.selectedKeys].map(key => listState.collection.getItem(key)).filter(item => item != null);\n }, [listState.selectionManager.selectedKeys, listState.collection]);\n\n let validationState = useFormValidationState({\n ...props,\n value: Array.isArray(controlledValue) && controlledValue.length === 0 ? null : controlledValue as any\n });\n\n let [isFocused, setFocused] = useState(false);\n let [initialValue] = useState(controlledValue);\n\n return {\n ...validationState,\n ...listState,\n ...triggerState,\n value: controlledValue,\n defaultValue: defaultValue ?? initialValue,\n setValue,\n selectedKey,\n setSelectedKey: setValue,\n selectedItem: selectedItems[0] ?? null,\n selectedItems,\n defaultSelectedKey: props.defaultSelectedKey ?? (props.selectionMode === 'single' ? initialValue as Key : null),\n focusStrategy,\n open(focusStrategy: FocusStrategy | null = null) {\n // Don't open if the collection is empty.\n if (listState.collection.size !== 0) {\n setFocusStrategy(focusStrategy);\n triggerState.open();\n }\n },\n toggle(focusStrategy: FocusStrategy | null = null) {\n if (listState.collection.size !== 0) {\n setFocusStrategy(focusStrategy);\n triggerState.toggle();\n }\n },\n isFocused,\n setFocused\n };\n}\n\nfunction convertValue(value: Key | Key[] | null | undefined) {\n if (value === undefined) {\n return undefined;\n }\n if (value === null) {\n return [];\n }\n return Array.isArray(value) ? value : [value];\n}\n"],"names":[],"version":3,"file":"useSelectState.main.js.map"}
@@ -1,7 +1,8 @@
1
1
  import {useFormValidationState as $6FfNf$useFormValidationState} from "@react-stately/form";
2
+ import {useListState as $6FfNf$useListState} from "@react-stately/list";
2
3
  import {useOverlayTriggerState as $6FfNf$useOverlayTriggerState} from "@react-stately/overlays";
3
- import {useSingleSelectListState as $6FfNf$useSingleSelectListState} from "@react-stately/list";
4
- import {useState as $6FfNf$useState} from "react";
4
+ import {useControlledState as $6FfNf$useControlledState} from "@react-stately/utils";
5
+ import {useState as $6FfNf$useState, useMemo as $6FfNf$useMemo} from "react";
5
6
 
6
7
  /*
7
8
  * Copyright 2020 Adobe. All rights reserved.
@@ -17,29 +18,94 @@ import {useState as $6FfNf$useState} from "react";
17
18
 
18
19
 
19
20
 
21
+
20
22
  function $2bc3a590c5373a4e$export$5159ec8b34d4ec12(props) {
23
+ let { selectionMode: selectionMode = 'single' } = props;
21
24
  let triggerState = (0, $6FfNf$useOverlayTriggerState)(props);
22
25
  let [focusStrategy, setFocusStrategy] = (0, $6FfNf$useState)(null);
23
- let listState = (0, $6FfNf$useSingleSelectListState)({
26
+ let defaultValue = (0, $6FfNf$useMemo)(()=>{
27
+ var _props_defaultSelectedKey, _props_defaultValue;
28
+ return (_props_defaultValue = props.defaultValue) !== null && _props_defaultValue !== void 0 ? _props_defaultValue : selectionMode === 'single' ? (_props_defaultSelectedKey = props.defaultSelectedKey) !== null && _props_defaultSelectedKey !== void 0 ? _props_defaultSelectedKey : null : [];
29
+ }, [
30
+ props.defaultValue,
31
+ props.defaultSelectedKey,
32
+ selectionMode
33
+ ]);
34
+ let value = (0, $6FfNf$useMemo)(()=>{
35
+ var _props_value;
36
+ return (_props_value = props.value) !== null && _props_value !== void 0 ? _props_value : selectionMode === 'single' ? props.selectedKey : undefined;
37
+ }, [
38
+ props.value,
39
+ props.selectedKey,
40
+ selectionMode
41
+ ]);
42
+ let [controlledValue, setControlledValue] = (0, $6FfNf$useControlledState)(value, defaultValue, props.onChange);
43
+ let setValue = (value)=>{
44
+ if (selectionMode === 'single') {
45
+ var _props_onSelectionChange;
46
+ var _value_;
47
+ let key = Array.isArray(value) ? (_value_ = value[0]) !== null && _value_ !== void 0 ? _value_ : null : value;
48
+ setControlledValue(key);
49
+ if (key !== controlledValue) (_props_onSelectionChange = props.onSelectionChange) === null || _props_onSelectionChange === void 0 ? void 0 : _props_onSelectionChange.call(props, key);
50
+ } else {
51
+ let keys = [];
52
+ if (Array.isArray(value)) keys = value;
53
+ else if (value != null) keys = [
54
+ value
55
+ ];
56
+ setControlledValue(keys);
57
+ }
58
+ };
59
+ let listState = (0, $6FfNf$useListState)({
24
60
  ...props,
25
- onSelectionChange: (key)=>{
26
- if (props.onSelectionChange != null) props.onSelectionChange(key);
27
- triggerState.close();
61
+ selectionMode: selectionMode,
62
+ disallowEmptySelection: selectionMode === 'single',
63
+ allowDuplicateSelectionEvents: true,
64
+ selectedKeys: (0, $6FfNf$useMemo)(()=>$2bc3a590c5373a4e$var$convertValue(controlledValue), [
65
+ controlledValue
66
+ ]),
67
+ onSelectionChange: (keys)=>{
68
+ // impossible, but TS doesn't know that
69
+ if (keys === 'all') return;
70
+ if (selectionMode === 'single') {
71
+ var _keys_values_next_value;
72
+ let key = (_keys_values_next_value = keys.values().next().value) !== null && _keys_values_next_value !== void 0 ? _keys_values_next_value : null;
73
+ setValue(key);
74
+ triggerState.close();
75
+ } else setValue([
76
+ ...keys
77
+ ]);
28
78
  validationState.commitValidation();
29
79
  }
30
80
  });
81
+ let selectedKey = listState.selectionManager.firstSelectedKey;
82
+ let selectedItems = (0, $6FfNf$useMemo)(()=>{
83
+ return [
84
+ ...listState.selectionManager.selectedKeys
85
+ ].map((key)=>listState.collection.getItem(key)).filter((item)=>item != null);
86
+ }, [
87
+ listState.selectionManager.selectedKeys,
88
+ listState.collection
89
+ ]);
31
90
  let validationState = (0, $6FfNf$useFormValidationState)({
32
91
  ...props,
33
- value: listState.selectedKey
92
+ value: Array.isArray(controlledValue) && controlledValue.length === 0 ? null : controlledValue
34
93
  });
35
94
  let [isFocused, setFocused] = (0, $6FfNf$useState)(false);
36
- let [initialSelectedKey] = (0, $6FfNf$useState)(listState.selectedKey);
37
- var _props_defaultSelectedKey;
95
+ let [initialValue] = (0, $6FfNf$useState)(controlledValue);
96
+ var _selectedItems_, _props_defaultSelectedKey;
38
97
  return {
39
98
  ...validationState,
40
99
  ...listState,
41
100
  ...triggerState,
42
- defaultSelectedKey: (_props_defaultSelectedKey = props.defaultSelectedKey) !== null && _props_defaultSelectedKey !== void 0 ? _props_defaultSelectedKey : initialSelectedKey,
101
+ value: controlledValue,
102
+ defaultValue: defaultValue !== null && defaultValue !== void 0 ? defaultValue : initialValue,
103
+ setValue: setValue,
104
+ selectedKey: selectedKey,
105
+ setSelectedKey: setValue,
106
+ selectedItem: (_selectedItems_ = selectedItems[0]) !== null && _selectedItems_ !== void 0 ? _selectedItems_ : null,
107
+ selectedItems: selectedItems,
108
+ defaultSelectedKey: (_props_defaultSelectedKey = props.defaultSelectedKey) !== null && _props_defaultSelectedKey !== void 0 ? _props_defaultSelectedKey : props.selectionMode === 'single' ? initialValue : null,
43
109
  focusStrategy: focusStrategy,
44
110
  open (focusStrategy = null) {
45
111
  // Don't open if the collection is empty.
@@ -58,6 +124,13 @@ function $2bc3a590c5373a4e$export$5159ec8b34d4ec12(props) {
58
124
  setFocused: setFocused
59
125
  };
60
126
  }
127
+ function $2bc3a590c5373a4e$var$convertValue(value) {
128
+ if (value === undefined) return undefined;
129
+ if (value === null) return [];
130
+ return Array.isArray(value) ? value : [
131
+ value
132
+ ];
133
+ }
61
134
 
62
135
 
63
136
  export {$2bc3a590c5373a4e$export$5159ec8b34d4ec12 as useSelectState};
@@ -1,7 +1,8 @@
1
1
  import {useFormValidationState as $6FfNf$useFormValidationState} from "@react-stately/form";
2
+ import {useListState as $6FfNf$useListState} from "@react-stately/list";
2
3
  import {useOverlayTriggerState as $6FfNf$useOverlayTriggerState} from "@react-stately/overlays";
3
- import {useSingleSelectListState as $6FfNf$useSingleSelectListState} from "@react-stately/list";
4
- import {useState as $6FfNf$useState} from "react";
4
+ import {useControlledState as $6FfNf$useControlledState} from "@react-stately/utils";
5
+ import {useState as $6FfNf$useState, useMemo as $6FfNf$useMemo} from "react";
5
6
 
6
7
  /*
7
8
  * Copyright 2020 Adobe. All rights reserved.
@@ -17,29 +18,94 @@ import {useState as $6FfNf$useState} from "react";
17
18
 
18
19
 
19
20
 
21
+
20
22
  function $2bc3a590c5373a4e$export$5159ec8b34d4ec12(props) {
23
+ let { selectionMode: selectionMode = 'single' } = props;
21
24
  let triggerState = (0, $6FfNf$useOverlayTriggerState)(props);
22
25
  let [focusStrategy, setFocusStrategy] = (0, $6FfNf$useState)(null);
23
- let listState = (0, $6FfNf$useSingleSelectListState)({
26
+ let defaultValue = (0, $6FfNf$useMemo)(()=>{
27
+ var _props_defaultSelectedKey, _props_defaultValue;
28
+ return (_props_defaultValue = props.defaultValue) !== null && _props_defaultValue !== void 0 ? _props_defaultValue : selectionMode === 'single' ? (_props_defaultSelectedKey = props.defaultSelectedKey) !== null && _props_defaultSelectedKey !== void 0 ? _props_defaultSelectedKey : null : [];
29
+ }, [
30
+ props.defaultValue,
31
+ props.defaultSelectedKey,
32
+ selectionMode
33
+ ]);
34
+ let value = (0, $6FfNf$useMemo)(()=>{
35
+ var _props_value;
36
+ return (_props_value = props.value) !== null && _props_value !== void 0 ? _props_value : selectionMode === 'single' ? props.selectedKey : undefined;
37
+ }, [
38
+ props.value,
39
+ props.selectedKey,
40
+ selectionMode
41
+ ]);
42
+ let [controlledValue, setControlledValue] = (0, $6FfNf$useControlledState)(value, defaultValue, props.onChange);
43
+ let setValue = (value)=>{
44
+ if (selectionMode === 'single') {
45
+ var _props_onSelectionChange;
46
+ var _value_;
47
+ let key = Array.isArray(value) ? (_value_ = value[0]) !== null && _value_ !== void 0 ? _value_ : null : value;
48
+ setControlledValue(key);
49
+ if (key !== controlledValue) (_props_onSelectionChange = props.onSelectionChange) === null || _props_onSelectionChange === void 0 ? void 0 : _props_onSelectionChange.call(props, key);
50
+ } else {
51
+ let keys = [];
52
+ if (Array.isArray(value)) keys = value;
53
+ else if (value != null) keys = [
54
+ value
55
+ ];
56
+ setControlledValue(keys);
57
+ }
58
+ };
59
+ let listState = (0, $6FfNf$useListState)({
24
60
  ...props,
25
- onSelectionChange: (key)=>{
26
- if (props.onSelectionChange != null) props.onSelectionChange(key);
27
- triggerState.close();
61
+ selectionMode: selectionMode,
62
+ disallowEmptySelection: selectionMode === 'single',
63
+ allowDuplicateSelectionEvents: true,
64
+ selectedKeys: (0, $6FfNf$useMemo)(()=>$2bc3a590c5373a4e$var$convertValue(controlledValue), [
65
+ controlledValue
66
+ ]),
67
+ onSelectionChange: (keys)=>{
68
+ // impossible, but TS doesn't know that
69
+ if (keys === 'all') return;
70
+ if (selectionMode === 'single') {
71
+ var _keys_values_next_value;
72
+ let key = (_keys_values_next_value = keys.values().next().value) !== null && _keys_values_next_value !== void 0 ? _keys_values_next_value : null;
73
+ setValue(key);
74
+ triggerState.close();
75
+ } else setValue([
76
+ ...keys
77
+ ]);
28
78
  validationState.commitValidation();
29
79
  }
30
80
  });
81
+ let selectedKey = listState.selectionManager.firstSelectedKey;
82
+ let selectedItems = (0, $6FfNf$useMemo)(()=>{
83
+ return [
84
+ ...listState.selectionManager.selectedKeys
85
+ ].map((key)=>listState.collection.getItem(key)).filter((item)=>item != null);
86
+ }, [
87
+ listState.selectionManager.selectedKeys,
88
+ listState.collection
89
+ ]);
31
90
  let validationState = (0, $6FfNf$useFormValidationState)({
32
91
  ...props,
33
- value: listState.selectedKey
92
+ value: Array.isArray(controlledValue) && controlledValue.length === 0 ? null : controlledValue
34
93
  });
35
94
  let [isFocused, setFocused] = (0, $6FfNf$useState)(false);
36
- let [initialSelectedKey] = (0, $6FfNf$useState)(listState.selectedKey);
37
- var _props_defaultSelectedKey;
95
+ let [initialValue] = (0, $6FfNf$useState)(controlledValue);
96
+ var _selectedItems_, _props_defaultSelectedKey;
38
97
  return {
39
98
  ...validationState,
40
99
  ...listState,
41
100
  ...triggerState,
42
- defaultSelectedKey: (_props_defaultSelectedKey = props.defaultSelectedKey) !== null && _props_defaultSelectedKey !== void 0 ? _props_defaultSelectedKey : initialSelectedKey,
101
+ value: controlledValue,
102
+ defaultValue: defaultValue !== null && defaultValue !== void 0 ? defaultValue : initialValue,
103
+ setValue: setValue,
104
+ selectedKey: selectedKey,
105
+ setSelectedKey: setValue,
106
+ selectedItem: (_selectedItems_ = selectedItems[0]) !== null && _selectedItems_ !== void 0 ? _selectedItems_ : null,
107
+ selectedItems: selectedItems,
108
+ defaultSelectedKey: (_props_defaultSelectedKey = props.defaultSelectedKey) !== null && _props_defaultSelectedKey !== void 0 ? _props_defaultSelectedKey : props.selectionMode === 'single' ? initialValue : null,
43
109
  focusStrategy: focusStrategy,
44
110
  open (focusStrategy = null) {
45
111
  // Don't open if the collection is empty.
@@ -58,6 +124,13 @@ function $2bc3a590c5373a4e$export$5159ec8b34d4ec12(props) {
58
124
  setFocused: setFocused
59
125
  };
60
126
  }
127
+ function $2bc3a590c5373a4e$var$convertValue(value) {
128
+ if (value === undefined) return undefined;
129
+ if (value === null) return [];
130
+ return Array.isArray(value) ? value : [
131
+ value
132
+ ];
133
+ }
61
134
 
62
135
 
63
136
  export {$2bc3a590c5373a4e$export$5159ec8b34d4ec12 as useSelectState};
@@ -1 +1 @@
1
- {"mappings":";;;;;AAAA;;;;;;;;;;CAUC;;;;AAoCM,SAAS,0CAAiC,KAA4B;IAC3E,IAAI,eAAe,CAAA,GAAA,6BAAqB,EAAE;IAC1C,IAAI,CAAC,eAAe,iBAAiB,GAAG,CAAA,GAAA,eAAO,EAAwB;IACvE,IAAI,YAAY,CAAA,GAAA,+BAAuB,EAAE;QACvC,GAAG,KAAK;QACR,mBAAmB,CAAC;YAClB,IAAI,MAAM,iBAAiB,IAAI,MAC7B,MAAM,iBAAiB,CAAC;YAG1B,aAAa,KAAK;YAClB,gBAAgB,gBAAgB;QAClC;IACF;IAEA,IAAI,kBAAkB,CAAA,GAAA,6BAAqB,EAAE;QAC3C,GAAG,KAAK;QACR,OAAO,UAAU,WAAW;IAC9B;IAEA,IAAI,CAAC,WAAW,WAAW,GAAG,CAAA,GAAA,eAAO,EAAE;IACvC,IAAI,CAAC,mBAAmB,GAAG,CAAA,GAAA,eAAO,EAAE,UAAU,WAAW;QAMnC;IAJtB,OAAO;QACL,GAAG,eAAe;QAClB,GAAG,SAAS;QACZ,GAAG,YAAY;QACf,oBAAoB,CAAA,4BAAA,MAAM,kBAAkB,cAAxB,uCAAA,4BAA4B;uBAChD;QACA,MAAK,gBAAsC,IAAI;YAC7C,yCAAyC;YACzC,IAAI,UAAU,UAAU,CAAC,IAAI,KAAK,GAAG;gBACnC,iBAAiB;gBACjB,aAAa,IAAI;YACnB;QACF;QACA,QAAO,gBAAsC,IAAI;YAC/C,IAAI,UAAU,UAAU,CAAC,IAAI,KAAK,GAAG;gBACnC,iBAAiB;gBACjB,aAAa,MAAM;YACrB;QACF;mBACA;oBACA;IACF;AACF","sources":["packages/@react-stately/select/src/useSelectState.ts"],"sourcesContent":["/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {CollectionStateBase, FocusStrategy, Key} from '@react-types/shared';\nimport {FormValidationState, useFormValidationState} from '@react-stately/form';\nimport {OverlayTriggerState, useOverlayTriggerState} from '@react-stately/overlays';\nimport {SelectProps} from '@react-types/select';\nimport {SingleSelectListState, useSingleSelectListState} from '@react-stately/list';\nimport {useState} from 'react';\n\nexport interface SelectStateOptions<T> extends Omit<SelectProps<T>, 'children'>, CollectionStateBase<T> {}\n\nexport interface SelectState<T> extends SingleSelectListState<T>, OverlayTriggerState, FormValidationState {\n /** The default selected key. */\n readonly defaultSelectedKey: Key | null,\n\n /** Whether the select is currently focused. */\n readonly isFocused: boolean,\n\n /** Sets whether the select is focused. */\n setFocused(isFocused: boolean): void,\n\n /** Controls which item will be auto focused when the menu opens. */\n readonly focusStrategy: FocusStrategy | null,\n\n /** Opens the menu. */\n open(focusStrategy?: FocusStrategy | null): void,\n\n /** Toggles the menu. */\n toggle(focusStrategy?: FocusStrategy | null): void\n}\n\n/**\n * Provides state management for a select component. Handles building a collection\n * of items from props, handles the open state for the popup menu, and manages\n * multiple selection state.\n */\nexport function useSelectState<T extends object>(props: SelectStateOptions<T>): SelectState<T> {\n let triggerState = useOverlayTriggerState(props);\n let [focusStrategy, setFocusStrategy] = useState<FocusStrategy | null>(null);\n let listState = useSingleSelectListState({\n ...props,\n onSelectionChange: (key) => {\n if (props.onSelectionChange != null) {\n props.onSelectionChange(key);\n }\n\n triggerState.close();\n validationState.commitValidation();\n }\n });\n\n let validationState = useFormValidationState({\n ...props,\n value: listState.selectedKey\n });\n\n let [isFocused, setFocused] = useState(false);\n let [initialSelectedKey] = useState(listState.selectedKey);\n\n return {\n ...validationState,\n ...listState,\n ...triggerState,\n defaultSelectedKey: props.defaultSelectedKey ?? initialSelectedKey,\n focusStrategy,\n open(focusStrategy: FocusStrategy | null = null) {\n // Don't open if the collection is empty.\n if (listState.collection.size !== 0) {\n setFocusStrategy(focusStrategy);\n triggerState.open();\n }\n },\n toggle(focusStrategy: FocusStrategy | null = null) {\n if (listState.collection.size !== 0) {\n setFocusStrategy(focusStrategy);\n triggerState.toggle();\n }\n },\n isFocused,\n setFocused\n };\n}\n"],"names":[],"version":3,"file":"useSelectState.module.js.map"}
1
+ {"mappings":"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","sources":["packages/@react-stately/select/src/useSelectState.ts"],"sourcesContent":["/*\n * Copyright 2020 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {CollectionStateBase, FocusStrategy, Key, Node, Selection} from '@react-types/shared';\nimport {FormValidationState, useFormValidationState} from '@react-stately/form';\nimport {ListState, useListState} from '@react-stately/list';\nimport {OverlayTriggerState, useOverlayTriggerState} from '@react-stately/overlays';\nimport {SelectionMode, SelectProps, ValueType} from '@react-types/select';\nimport {useControlledState} from '@react-stately/utils';\nimport {useMemo, useState} from 'react';\n\nexport interface SelectStateOptions<T, M extends SelectionMode = 'single'> extends Omit<SelectProps<T, M>, 'children'>, CollectionStateBase<T> {}\n\nexport interface SelectState<T, M extends SelectionMode = 'single'> extends ListState<T>, OverlayTriggerState, FormValidationState {\n /**\n * The key for the first selected item.\n * @deprecated\n */\n readonly selectedKey: Key | null,\n\n /**\n * The default selected key.\n * @deprecated\n */\n readonly defaultSelectedKey: Key | null,\n\n /**\n * Sets the selected key.\n * @deprecated\n */\n setSelectedKey(key: Key | null): void,\n\n /** The current select value. */\n readonly value: ValueType<M>,\n\n /** The default select value. */\n readonly defaultValue: ValueType<M>,\n\n /** Sets the select value. */\n setValue(value: Key | Key[] | null): void,\n\n /**\n * The value of the first selected item.\n * @deprecated\n */\n readonly selectedItem: Node<T> | null,\n\n /** The value of the selected items. */\n readonly selectedItems: Node<T>[],\n\n /** Whether the select is currently focused. */\n readonly isFocused: boolean,\n\n /** Sets whether the select is focused. */\n setFocused(isFocused: boolean): void,\n\n /** Controls which item will be auto focused when the menu opens. */\n readonly focusStrategy: FocusStrategy | null,\n\n /** Opens the menu. */\n open(focusStrategy?: FocusStrategy | null): void,\n\n /** Toggles the menu. */\n toggle(focusStrategy?: FocusStrategy | null): void\n}\n\n/**\n * Provides state management for a select component. Handles building a collection\n * of items from props, handles the open state for the popup menu, and manages\n * multiple selection state.\n */\nexport function useSelectState<T extends object, M extends SelectionMode = 'single'>(props: SelectStateOptions<T, M>): SelectState<T, M> {\n let {selectionMode = 'single' as M} = props;\n let triggerState = useOverlayTriggerState(props);\n let [focusStrategy, setFocusStrategy] = useState<FocusStrategy | null>(null);\n let defaultValue = useMemo(() => {\n return props.defaultValue ?? (selectionMode === 'single' ? props.defaultSelectedKey ?? null : []) as ValueType<M>;\n }, [props.defaultValue, props.defaultSelectedKey, selectionMode]);\n let value = useMemo(() => {\n return props.value ?? (selectionMode === 'single' ? props.selectedKey : undefined) as ValueType<M>;\n }, [props.value, props.selectedKey, selectionMode]);\n let [controlledValue, setControlledValue] = useControlledState<ValueType<M>>(value as any, defaultValue as any, props.onChange);\n let setValue = (value: Key | Key[] | null) => {\n if (selectionMode === 'single') {\n let key = Array.isArray(value) ? value[0] ?? null : value;\n setControlledValue(key as ValueType<M>);\n if (key !== controlledValue) {\n props.onSelectionChange?.(key);\n }\n } else {\n let keys: Key[] = [];\n if (Array.isArray(value)) {\n keys = value;\n } else if (value != null) {\n keys = [value];\n }\n\n setControlledValue(keys as ValueType<M>);\n }\n };\n\n let listState = useListState({\n ...props,\n selectionMode,\n disallowEmptySelection: selectionMode === 'single',\n allowDuplicateSelectionEvents: true,\n selectedKeys: useMemo(() => convertValue(controlledValue), [controlledValue]),\n onSelectionChange: (keys: Selection) => {\n // impossible, but TS doesn't know that\n if (keys === 'all') {\n return;\n }\n\n if (selectionMode === 'single') {\n let key = keys.values().next().value ?? null;\n setValue(key);\n triggerState.close();\n } else {\n setValue([...keys]);\n }\n\n validationState.commitValidation();\n }\n });\n\n let selectedKey = listState.selectionManager.firstSelectedKey;\n let selectedItems = useMemo(() => {\n return [...listState.selectionManager.selectedKeys].map(key => listState.collection.getItem(key)).filter(item => item != null);\n }, [listState.selectionManager.selectedKeys, listState.collection]);\n\n let validationState = useFormValidationState({\n ...props,\n value: Array.isArray(controlledValue) && controlledValue.length === 0 ? null : controlledValue as any\n });\n\n let [isFocused, setFocused] = useState(false);\n let [initialValue] = useState(controlledValue);\n\n return {\n ...validationState,\n ...listState,\n ...triggerState,\n value: controlledValue,\n defaultValue: defaultValue ?? initialValue,\n setValue,\n selectedKey,\n setSelectedKey: setValue,\n selectedItem: selectedItems[0] ?? null,\n selectedItems,\n defaultSelectedKey: props.defaultSelectedKey ?? (props.selectionMode === 'single' ? initialValue as Key : null),\n focusStrategy,\n open(focusStrategy: FocusStrategy | null = null) {\n // Don't open if the collection is empty.\n if (listState.collection.size !== 0) {\n setFocusStrategy(focusStrategy);\n triggerState.open();\n }\n },\n toggle(focusStrategy: FocusStrategy | null = null) {\n if (listState.collection.size !== 0) {\n setFocusStrategy(focusStrategy);\n triggerState.toggle();\n }\n },\n isFocused,\n setFocused\n };\n}\n\nfunction convertValue(value: Key | Key[] | null | undefined) {\n if (value === undefined) {\n return undefined;\n }\n if (value === null) {\n return [];\n }\n return Array.isArray(value) ? value : [value];\n}\n"],"names":[],"version":3,"file":"useSelectState.module.js.map"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@react-stately/select",
3
- "version": "3.0.0-nightly-6a86b5cdd-250829",
3
+ "version": "3.0.0-nightly-e717ee924-250830",
4
4
  "description": "Spectrum UI components in React",
5
5
  "license": "Apache-2.0",
6
6
  "main": "dist/main.js",
@@ -26,11 +26,12 @@
26
26
  "url": "https://github.com/adobe/react-spectrum"
27
27
  },
28
28
  "dependencies": {
29
- "@react-stately/form": "3.0.0-nightly-6a86b5cdd-250829",
30
- "@react-stately/list": "3.0.0-nightly-6a86b5cdd-250829",
31
- "@react-stately/overlays": "3.0.0-nightly-6a86b5cdd-250829",
32
- "@react-types/select": "3.0.0-nightly-6a86b5cdd-250829",
33
- "@react-types/shared": "3.0.0-nightly-6a86b5cdd-250829",
29
+ "@react-stately/form": "3.0.0-nightly-e717ee924-250830",
30
+ "@react-stately/list": "3.0.0-nightly-e717ee924-250830",
31
+ "@react-stately/overlays": "3.0.0-nightly-e717ee924-250830",
32
+ "@react-stately/utils": "3.0.0-nightly-e717ee924-250830",
33
+ "@react-types/select": "3.0.0-nightly-e717ee924-250830",
34
+ "@react-types/shared": "3.0.0-nightly-e717ee924-250830",
34
35
  "@swc/helpers": "^0.5.0"
35
36
  },
36
37
  "peerDependencies": {
@@ -10,19 +10,53 @@
10
10
  * governing permissions and limitations under the License.
11
11
  */
12
12
 
13
- import {CollectionStateBase, FocusStrategy, Key} from '@react-types/shared';
13
+ import {CollectionStateBase, FocusStrategy, Key, Node, Selection} from '@react-types/shared';
14
14
  import {FormValidationState, useFormValidationState} from '@react-stately/form';
15
+ import {ListState, useListState} from '@react-stately/list';
15
16
  import {OverlayTriggerState, useOverlayTriggerState} from '@react-stately/overlays';
16
- import {SelectProps} from '@react-types/select';
17
- import {SingleSelectListState, useSingleSelectListState} from '@react-stately/list';
18
- import {useState} from 'react';
17
+ import {SelectionMode, SelectProps, ValueType} from '@react-types/select';
18
+ import {useControlledState} from '@react-stately/utils';
19
+ import {useMemo, useState} from 'react';
19
20
 
20
- export interface SelectStateOptions<T> extends Omit<SelectProps<T>, 'children'>, CollectionStateBase<T> {}
21
+ export interface SelectStateOptions<T, M extends SelectionMode = 'single'> extends Omit<SelectProps<T, M>, 'children'>, CollectionStateBase<T> {}
21
22
 
22
- export interface SelectState<T> extends SingleSelectListState<T>, OverlayTriggerState, FormValidationState {
23
- /** The default selected key. */
23
+ export interface SelectState<T, M extends SelectionMode = 'single'> extends ListState<T>, OverlayTriggerState, FormValidationState {
24
+ /**
25
+ * The key for the first selected item.
26
+ * @deprecated
27
+ */
28
+ readonly selectedKey: Key | null,
29
+
30
+ /**
31
+ * The default selected key.
32
+ * @deprecated
33
+ */
24
34
  readonly defaultSelectedKey: Key | null,
25
35
 
36
+ /**
37
+ * Sets the selected key.
38
+ * @deprecated
39
+ */
40
+ setSelectedKey(key: Key | null): void,
41
+
42
+ /** The current select value. */
43
+ readonly value: ValueType<M>,
44
+
45
+ /** The default select value. */
46
+ readonly defaultValue: ValueType<M>,
47
+
48
+ /** Sets the select value. */
49
+ setValue(value: Key | Key[] | null): void,
50
+
51
+ /**
52
+ * The value of the first selected item.
53
+ * @deprecated
54
+ */
55
+ readonly selectedItem: Node<T> | null,
56
+
57
+ /** The value of the selected items. */
58
+ readonly selectedItems: Node<T>[],
59
+
26
60
  /** Whether the select is currently focused. */
27
61
  readonly isFocused: boolean,
28
62
 
@@ -44,34 +78,85 @@ export interface SelectState<T> extends SingleSelectListState<T>, OverlayTrigger
44
78
  * of items from props, handles the open state for the popup menu, and manages
45
79
  * multiple selection state.
46
80
  */
47
- export function useSelectState<T extends object>(props: SelectStateOptions<T>): SelectState<T> {
81
+ export function useSelectState<T extends object, M extends SelectionMode = 'single'>(props: SelectStateOptions<T, M>): SelectState<T, M> {
82
+ let {selectionMode = 'single' as M} = props;
48
83
  let triggerState = useOverlayTriggerState(props);
49
84
  let [focusStrategy, setFocusStrategy] = useState<FocusStrategy | null>(null);
50
- let listState = useSingleSelectListState({
85
+ let defaultValue = useMemo(() => {
86
+ return props.defaultValue ?? (selectionMode === 'single' ? props.defaultSelectedKey ?? null : []) as ValueType<M>;
87
+ }, [props.defaultValue, props.defaultSelectedKey, selectionMode]);
88
+ let value = useMemo(() => {
89
+ return props.value ?? (selectionMode === 'single' ? props.selectedKey : undefined) as ValueType<M>;
90
+ }, [props.value, props.selectedKey, selectionMode]);
91
+ let [controlledValue, setControlledValue] = useControlledState<ValueType<M>>(value as any, defaultValue as any, props.onChange);
92
+ let setValue = (value: Key | Key[] | null) => {
93
+ if (selectionMode === 'single') {
94
+ let key = Array.isArray(value) ? value[0] ?? null : value;
95
+ setControlledValue(key as ValueType<M>);
96
+ if (key !== controlledValue) {
97
+ props.onSelectionChange?.(key);
98
+ }
99
+ } else {
100
+ let keys: Key[] = [];
101
+ if (Array.isArray(value)) {
102
+ keys = value;
103
+ } else if (value != null) {
104
+ keys = [value];
105
+ }
106
+
107
+ setControlledValue(keys as ValueType<M>);
108
+ }
109
+ };
110
+
111
+ let listState = useListState({
51
112
  ...props,
52
- onSelectionChange: (key) => {
53
- if (props.onSelectionChange != null) {
54
- props.onSelectionChange(key);
113
+ selectionMode,
114
+ disallowEmptySelection: selectionMode === 'single',
115
+ allowDuplicateSelectionEvents: true,
116
+ selectedKeys: useMemo(() => convertValue(controlledValue), [controlledValue]),
117
+ onSelectionChange: (keys: Selection) => {
118
+ // impossible, but TS doesn't know that
119
+ if (keys === 'all') {
120
+ return;
121
+ }
122
+
123
+ if (selectionMode === 'single') {
124
+ let key = keys.values().next().value ?? null;
125
+ setValue(key);
126
+ triggerState.close();
127
+ } else {
128
+ setValue([...keys]);
55
129
  }
56
130
 
57
- triggerState.close();
58
131
  validationState.commitValidation();
59
132
  }
60
133
  });
61
134
 
135
+ let selectedKey = listState.selectionManager.firstSelectedKey;
136
+ let selectedItems = useMemo(() => {
137
+ return [...listState.selectionManager.selectedKeys].map(key => listState.collection.getItem(key)).filter(item => item != null);
138
+ }, [listState.selectionManager.selectedKeys, listState.collection]);
139
+
62
140
  let validationState = useFormValidationState({
63
141
  ...props,
64
- value: listState.selectedKey
142
+ value: Array.isArray(controlledValue) && controlledValue.length === 0 ? null : controlledValue as any
65
143
  });
66
144
 
67
145
  let [isFocused, setFocused] = useState(false);
68
- let [initialSelectedKey] = useState(listState.selectedKey);
146
+ let [initialValue] = useState(controlledValue);
69
147
 
70
148
  return {
71
149
  ...validationState,
72
150
  ...listState,
73
151
  ...triggerState,
74
- defaultSelectedKey: props.defaultSelectedKey ?? initialSelectedKey,
152
+ value: controlledValue,
153
+ defaultValue: defaultValue ?? initialValue,
154
+ setValue,
155
+ selectedKey,
156
+ setSelectedKey: setValue,
157
+ selectedItem: selectedItems[0] ?? null,
158
+ selectedItems,
159
+ defaultSelectedKey: props.defaultSelectedKey ?? (props.selectionMode === 'single' ? initialValue as Key : null),
75
160
  focusStrategy,
76
161
  open(focusStrategy: FocusStrategy | null = null) {
77
162
  // Don't open if the collection is empty.
@@ -90,3 +175,13 @@ export function useSelectState<T extends object>(props: SelectStateOptions<T>):
90
175
  setFocused
91
176
  };
92
177
  }
178
+
179
+ function convertValue(value: Key | Key[] | null | undefined) {
180
+ if (value === undefined) {
181
+ return undefined;
182
+ }
183
+ if (value === null) {
184
+ return [];
185
+ }
186
+ return Array.isArray(value) ? value : [value];
187
+ }