@xsolla/xui-multi-select 0.184.0 → 0.185.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 +56 -0
- package/native/index.d.mts +31 -1
- package/native/index.d.ts +31 -1
- package/native/index.js +171 -41
- package/native/index.js.map +1 -1
- package/native/index.mjs +178 -42
- package/native/index.mjs.map +1 -1
- package/package.json +5 -5
- package/web/index.d.mts +31 -1
- package/web/index.d.ts +31 -1
- package/web/index.js +171 -41
- package/web/index.js.map +1 -1
- package/web/index.mjs +178 -42
- package/web/index.mjs.map +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xsolla/xui-multi-select",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.185.0",
|
|
4
4
|
"main": "./web/index.js",
|
|
5
5
|
"module": "./web/index.mjs",
|
|
6
6
|
"types": "./web/index.d.ts",
|
|
@@ -10,10 +10,10 @@
|
|
|
10
10
|
"build:native": "PLATFORM=native tsup"
|
|
11
11
|
},
|
|
12
12
|
"dependencies": {
|
|
13
|
-
"@xsolla/xui-checkbox": "0.
|
|
14
|
-
"@xsolla/xui-core": "0.
|
|
15
|
-
"@xsolla/xui-dropdown": "0.
|
|
16
|
-
"@xsolla/xui-primitives-core": "0.
|
|
13
|
+
"@xsolla/xui-checkbox": "0.185.0",
|
|
14
|
+
"@xsolla/xui-core": "0.185.0",
|
|
15
|
+
"@xsolla/xui-dropdown": "0.185.0",
|
|
16
|
+
"@xsolla/xui-primitives-core": "0.185.0"
|
|
17
17
|
},
|
|
18
18
|
"peerDependencies": {
|
|
19
19
|
"react": ">=16.8.0",
|
package/web/index.d.mts
CHANGED
|
@@ -5,6 +5,7 @@ import { ThemeOverrideProps } from '@xsolla/xui-core';
|
|
|
5
5
|
type MultiSelectValue = (string | number)[];
|
|
6
6
|
type MultiSelectVariant = "tag" | "text";
|
|
7
7
|
type MultiSelectSize = "xs" | "sm" | "md" | "lg" | "xl";
|
|
8
|
+
type MultiSelectOptionOverflow = "truncate" | "wrap" | "scroll";
|
|
8
9
|
type MultiSelectState = "default" | "hover" | "focus" | "disable" | "error";
|
|
9
10
|
interface MultiSelectOption {
|
|
10
11
|
label: ReactNode;
|
|
@@ -83,6 +84,35 @@ interface MultiSelectProps extends ThemeOverrideProps {
|
|
|
83
84
|
* @default 300
|
|
84
85
|
*/
|
|
85
86
|
maxHeight?: number;
|
|
87
|
+
/**
|
|
88
|
+
* How long option labels in the dropdown handle horizontal overflow.
|
|
89
|
+
* - `"truncate"` — clamp each label to a single line with an ellipsis.
|
|
90
|
+
* - `"wrap"` — allow labels to wrap onto multiple lines (rows grow taller).
|
|
91
|
+
* - `"scroll"` — keep labels on one line and scroll the list horizontally
|
|
92
|
+
* (legacy behavior). Web only — falls back to `"wrap"` on native, which
|
|
93
|
+
* cannot horizontally scroll a text row.
|
|
94
|
+
* @default "truncate"
|
|
95
|
+
*/
|
|
96
|
+
optionOverflow?: MultiSelectOptionOverflow;
|
|
97
|
+
/**
|
|
98
|
+
* When true, shows a search input at the top of the built-in dropdown that
|
|
99
|
+
* filters options in memory by their label as the user types. Mirrors the
|
|
100
|
+
* `searchable` behavior of the Select component. Web only — ignored on
|
|
101
|
+
* native and when `dropdownMenu` is false.
|
|
102
|
+
* @default false
|
|
103
|
+
*/
|
|
104
|
+
searchable?: boolean;
|
|
105
|
+
/**
|
|
106
|
+
* Placeholder text for the search input. Only used when `searchable` is true.
|
|
107
|
+
* @default "Search"
|
|
108
|
+
*/
|
|
109
|
+
searchPlaceholder?: string;
|
|
110
|
+
/**
|
|
111
|
+
* Message shown in the dropdown when the search filter matches no options.
|
|
112
|
+
* Only used when `searchable` is true.
|
|
113
|
+
* @default "No results"
|
|
114
|
+
*/
|
|
115
|
+
noOptionsMessage?: string;
|
|
86
116
|
/**
|
|
87
117
|
* When false, the built-in options list and backdrop are not shown and the control
|
|
88
118
|
* does not open on click. Use with an external picker (e.g. grouped select) wired
|
|
@@ -112,4 +142,4 @@ interface MultiSelectProps extends ThemeOverrideProps {
|
|
|
112
142
|
|
|
113
143
|
declare const MultiSelect: react.ForwardRefExoticComponent<MultiSelectProps & react.RefAttributes<HTMLDivElement>>;
|
|
114
144
|
|
|
115
|
-
export { MultiSelect, type MultiSelectOption, type MultiSelectProps, type MultiSelectSize, type MultiSelectState, type MultiSelectValue, type MultiSelectVariant };
|
|
145
|
+
export { MultiSelect, type MultiSelectOption, type MultiSelectOptionOverflow, type MultiSelectProps, type MultiSelectSize, type MultiSelectState, type MultiSelectValue, type MultiSelectVariant };
|
package/web/index.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ import { ThemeOverrideProps } from '@xsolla/xui-core';
|
|
|
5
5
|
type MultiSelectValue = (string | number)[];
|
|
6
6
|
type MultiSelectVariant = "tag" | "text";
|
|
7
7
|
type MultiSelectSize = "xs" | "sm" | "md" | "lg" | "xl";
|
|
8
|
+
type MultiSelectOptionOverflow = "truncate" | "wrap" | "scroll";
|
|
8
9
|
type MultiSelectState = "default" | "hover" | "focus" | "disable" | "error";
|
|
9
10
|
interface MultiSelectOption {
|
|
10
11
|
label: ReactNode;
|
|
@@ -83,6 +84,35 @@ interface MultiSelectProps extends ThemeOverrideProps {
|
|
|
83
84
|
* @default 300
|
|
84
85
|
*/
|
|
85
86
|
maxHeight?: number;
|
|
87
|
+
/**
|
|
88
|
+
* How long option labels in the dropdown handle horizontal overflow.
|
|
89
|
+
* - `"truncate"` — clamp each label to a single line with an ellipsis.
|
|
90
|
+
* - `"wrap"` — allow labels to wrap onto multiple lines (rows grow taller).
|
|
91
|
+
* - `"scroll"` — keep labels on one line and scroll the list horizontally
|
|
92
|
+
* (legacy behavior). Web only — falls back to `"wrap"` on native, which
|
|
93
|
+
* cannot horizontally scroll a text row.
|
|
94
|
+
* @default "truncate"
|
|
95
|
+
*/
|
|
96
|
+
optionOverflow?: MultiSelectOptionOverflow;
|
|
97
|
+
/**
|
|
98
|
+
* When true, shows a search input at the top of the built-in dropdown that
|
|
99
|
+
* filters options in memory by their label as the user types. Mirrors the
|
|
100
|
+
* `searchable` behavior of the Select component. Web only — ignored on
|
|
101
|
+
* native and when `dropdownMenu` is false.
|
|
102
|
+
* @default false
|
|
103
|
+
*/
|
|
104
|
+
searchable?: boolean;
|
|
105
|
+
/**
|
|
106
|
+
* Placeholder text for the search input. Only used when `searchable` is true.
|
|
107
|
+
* @default "Search"
|
|
108
|
+
*/
|
|
109
|
+
searchPlaceholder?: string;
|
|
110
|
+
/**
|
|
111
|
+
* Message shown in the dropdown when the search filter matches no options.
|
|
112
|
+
* Only used when `searchable` is true.
|
|
113
|
+
* @default "No results"
|
|
114
|
+
*/
|
|
115
|
+
noOptionsMessage?: string;
|
|
86
116
|
/**
|
|
87
117
|
* When false, the built-in options list and backdrop are not shown and the control
|
|
88
118
|
* does not open on click. Use with an external picker (e.g. grouped select) wired
|
|
@@ -112,4 +142,4 @@ interface MultiSelectProps extends ThemeOverrideProps {
|
|
|
112
142
|
|
|
113
143
|
declare const MultiSelect: react.ForwardRefExoticComponent<MultiSelectProps & react.RefAttributes<HTMLDivElement>>;
|
|
114
144
|
|
|
115
|
-
export { MultiSelect, type MultiSelectOption, type MultiSelectProps, type MultiSelectSize, type MultiSelectState, type MultiSelectValue, type MultiSelectVariant };
|
|
145
|
+
export { MultiSelect, type MultiSelectOption, type MultiSelectOptionOverflow, type MultiSelectProps, type MultiSelectSize, type MultiSelectState, type MultiSelectValue, type MultiSelectVariant };
|
package/web/index.js
CHANGED
|
@@ -359,10 +359,6 @@ var isWeb = true;
|
|
|
359
359
|
// src/MultiSelect.tsx
|
|
360
360
|
var import_xui_core4 = require("@xsolla/xui-core");
|
|
361
361
|
|
|
362
|
-
// src/MultiSelectControl.tsx
|
|
363
|
-
var import_react9 = require("react");
|
|
364
|
-
var import_xui_core3 = require("@xsolla/xui-core");
|
|
365
|
-
|
|
366
362
|
// ../../foundation/icons-base/dist/web/index.mjs
|
|
367
363
|
var import_styled_components4 = __toESM(require("styled-components"), 1);
|
|
368
364
|
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
@@ -1141,6 +1137,13 @@ var ExclamationMarkCr = (props) => /* @__PURE__ */ (0, import_jsx_runtime152.jsx
|
|
|
1141
1137
|
var solidContent172 = `<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" width="100%" height="100%"><g id="icon_remove--solid"><path id="Union" d="M20.5 3C20.7761 3 21 3.22386 21 3.5V20.5C21 20.7761 20.7761 21 20.5 21H3.5C3.22386 21 3 20.7761 3 20.5V3.5C3 3.22386 3.22386 3 3.5 3H20.5ZM12 10.5859L7.20703 5.79297L5.79297 7.20703L10.5859 12L5.79297 16.793L7.20703 18.207L12 13.4141L16.793 18.207L18.207 16.793L13.4141 12L18.207 7.20703L16.793 5.79297L12 10.5859Z" style="fill: currentColor"/></g></svg>`;
|
|
1142
1138
|
var lineContent172 = `<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" width="100%" height="100%"><g id="icon_remove--line"><path id="Union" d="M20.0303 5.41455L13.4199 12.0249L20.0195 18.6245L18.6055 20.0386L12.0059 13.439L5.41406 20.0308L4 18.6167L10.5918 12.0249L4.00879 5.44189L5.42285 4.02783L12.0059 10.6108L18.6162 4.00049L20.0303 5.41455Z" style="fill: currentColor"/></g></svg>`;
|
|
1143
1139
|
var Remove = (props) => /* @__PURE__ */ (0, import_jsx_runtime176.jsx)(BaseIcon, { ...props, solidContent: solidContent172, lineContent: lineContent172 });
|
|
1140
|
+
var solidContent706 = `<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" width="100%" height="100%"><g id="icon_search--solid"><path id="Union" d="M10.0215 2.02148C14.4398 2.02148 18.0215 5.60321 18.0215 10.0215C18.0215 11.8699 17.3926 13.5702 16.3398 14.9248L21.9785 20.5645L20.5645 21.9785L14.9248 16.3389C13.5702 17.3918 11.8701 18.0215 10.0215 18.0215C5.60321 18.0215 2.02148 14.4398 2.02148 10.0215C2.02148 5.60321 5.60321 2.02148 10.0215 2.02148ZM10.0215 4.02148C6.70778 4.02148 4.02148 6.70778 4.02148 10.0215C4.02148 13.3352 6.70778 16.0215 10.0215 16.0215C13.3352 16.0215 16.0215 13.3352 16.0215 10.0215C16.0215 6.70778 13.3352 4.02148 10.0215 4.02148ZM7.19336 7.19336C8.75546 5.63126 11.2875 5.63126 12.8496 7.19336C14.4117 8.75546 14.4117 11.2875 12.8496 12.8496C11.2875 14.4117 8.75546 14.4117 7.19336 12.8496C5.63126 11.2875 5.63127 8.75546 7.19336 7.19336Z" style="fill: currentColor"/></g></svg>`;
|
|
1141
|
+
var lineContent706 = `<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" width="100%" height="100%"><g id="icon_search--line"><path id="Union" fill-rule="evenodd" clip-rule="evenodd" d="M10 2C14.4183 2 18 5.58172 18 10C18 11.8484 17.3711 13.5488 16.3184 14.9033L21.957 20.543L20.543 21.957L14.9033 16.3174C13.5487 17.3703 11.8486 18 10 18C5.58172 18 2 14.4183 2 10C2 5.58172 5.58172 2 10 2ZM10 4C6.68629 4 4 6.68629 4 10C4 13.3137 6.68629 16 10 16C13.3137 16 16 13.3137 16 10C16 6.68629 13.3137 4 10 4Z" style="fill: currentColor"/></g></svg>`;
|
|
1142
|
+
var Search = (props) => /* @__PURE__ */ (0, import_jsx_runtime710.jsx)(BaseIcon, { ...props, solidContent: solidContent706, lineContent: lineContent706 });
|
|
1143
|
+
|
|
1144
|
+
// src/MultiSelectControl.tsx
|
|
1145
|
+
var import_react9 = require("react");
|
|
1146
|
+
var import_xui_core3 = require("@xsolla/xui-core");
|
|
1144
1147
|
|
|
1145
1148
|
// src/useMultiSelectControl.tsx
|
|
1146
1149
|
var import_react8 = require("react");
|
|
@@ -2239,10 +2242,14 @@ var MultiSelect = (0, import_react12.forwardRef)(
|
|
|
2239
2242
|
iconLeft,
|
|
2240
2243
|
iconRight,
|
|
2241
2244
|
maxHeight = 300,
|
|
2245
|
+
optionOverflow = "truncate",
|
|
2242
2246
|
dropdownMenu = true,
|
|
2243
2247
|
onTriggerPress,
|
|
2244
2248
|
menuOpen = false,
|
|
2245
2249
|
menuMinWidth,
|
|
2250
|
+
searchable = false,
|
|
2251
|
+
searchPlaceholder = "Search",
|
|
2252
|
+
noOptionsMessage = "No results",
|
|
2246
2253
|
testID,
|
|
2247
2254
|
themeMode,
|
|
2248
2255
|
themeProductContext
|
|
@@ -2251,8 +2258,12 @@ var MultiSelect = (0, import_react12.forwardRef)(
|
|
|
2251
2258
|
const modalId = (0, import_xui_core4.useModalId)();
|
|
2252
2259
|
const controlRef = (0, import_react12.useRef)(null);
|
|
2253
2260
|
const menuRef = (0, import_react12.useRef)(null);
|
|
2261
|
+
const containerRef = (0, import_react12.useRef)(null);
|
|
2262
|
+
const searchInputRef = (0, import_react12.useRef)(null);
|
|
2254
2263
|
const [menuPosition, setMenuPosition] = (0, import_react12.useState)(null);
|
|
2264
|
+
const [searchValue, setSearchValue] = (0, import_react12.useState)("");
|
|
2255
2265
|
const sizeStyles = theme.sizing.input(size);
|
|
2266
|
+
const inputColors = theme.colors.control.input;
|
|
2256
2267
|
const state = externalState || (disabled ? "disable" : "default");
|
|
2257
2268
|
const isDisable = state === "disable" || disabled;
|
|
2258
2269
|
const isError = state === "error" || !!errorMessage;
|
|
@@ -2277,7 +2288,19 @@ var MultiSelect = (0, import_react12.forwardRef)(
|
|
|
2277
2288
|
onClose();
|
|
2278
2289
|
}
|
|
2279
2290
|
}, [isDisable, dropdownMenu, onClose]);
|
|
2280
|
-
|
|
2291
|
+
(0, import_react12.useEffect)(() => {
|
|
2292
|
+
if (isOpen && searchable && isWeb) {
|
|
2293
|
+
searchInputRef.current?.focus();
|
|
2294
|
+
}
|
|
2295
|
+
}, [isOpen, searchable]);
|
|
2296
|
+
(0, import_react12.useEffect)(() => {
|
|
2297
|
+
if (!isOpen) setSearchValue("");
|
|
2298
|
+
}, [isOpen]);
|
|
2299
|
+
const getOptionText = (opt) => typeof opt.label === "string" ? opt.label : String(opt.value);
|
|
2300
|
+
const filteredOptions = searchable && searchValue ? options.filter(
|
|
2301
|
+
(opt) => getOptionText(opt).toLowerCase().includes(searchValue.toLowerCase())
|
|
2302
|
+
) : options;
|
|
2303
|
+
const menuItems = filteredOptions.map((opt) => {
|
|
2281
2304
|
const id = String(opt.value);
|
|
2282
2305
|
const checked = values.map(String).includes(id);
|
|
2283
2306
|
return {
|
|
@@ -2295,6 +2318,22 @@ var MultiSelect = (0, import_react12.forwardRef)(
|
|
|
2295
2318
|
};
|
|
2296
2319
|
const controlMenuOpen = dropdownMenu ? isOpen : Boolean(menuOpen);
|
|
2297
2320
|
const controlOnClick = dropdownMenu ? onSelectClick : onTriggerPress;
|
|
2321
|
+
const isScrollOverflow = optionOverflow === "scroll";
|
|
2322
|
+
const isWrapOverflow = optionOverflow === "wrap";
|
|
2323
|
+
const optionListOverflowX = isScrollOverflow ? "auto" : "hidden";
|
|
2324
|
+
const optionRowMinWidth = isScrollOverflow ? void 0 : 0;
|
|
2325
|
+
const optionLabelNumberOfLines = optionOverflow === "truncate" ? 1 : void 0;
|
|
2326
|
+
const optionLabelStyle = isScrollOverflow ? { whiteSpace: "nowrap" } : isWrapOverflow ? {
|
|
2327
|
+
minWidth: 0,
|
|
2328
|
+
whiteSpace: "normal",
|
|
2329
|
+
overflowWrap: "break-word",
|
|
2330
|
+
wordBreak: "break-word"
|
|
2331
|
+
} : {
|
|
2332
|
+
minWidth: 0,
|
|
2333
|
+
whiteSpace: "nowrap",
|
|
2334
|
+
overflow: "hidden",
|
|
2335
|
+
textOverflow: "ellipsis"
|
|
2336
|
+
};
|
|
2298
2337
|
const updateMenuPosition = (0, import_react12.useCallback)(() => {
|
|
2299
2338
|
if (!isWeb || !controlRef.current) return;
|
|
2300
2339
|
const rect = controlRef.current.getBoundingClientRect();
|
|
@@ -2314,13 +2353,25 @@ var MultiSelect = (0, import_react12.forwardRef)(
|
|
|
2314
2353
|
window.removeEventListener("scroll", updateMenuPosition, true);
|
|
2315
2354
|
};
|
|
2316
2355
|
}, [controlMenuOpen, dropdownMenu, isDisable, updateMenuPosition]);
|
|
2356
|
+
(0, import_react12.useEffect)(() => {
|
|
2357
|
+
if (!isWeb || !dropdownMenu || !isOpen || isDisable) return;
|
|
2358
|
+
const handleOutsideMouseDown = (event) => {
|
|
2359
|
+
const path = typeof event.composedPath === "function" ? event.composedPath() : [];
|
|
2360
|
+
const targetNode = event.target;
|
|
2361
|
+
const isInside = (el) => !!el && (path.length ? path.includes(el) : !!targetNode && el.contains(targetNode));
|
|
2362
|
+
if (isInside(containerRef.current) || isInside(menuRef.current)) return;
|
|
2363
|
+
onClose();
|
|
2364
|
+
};
|
|
2365
|
+
document.addEventListener("mousedown", handleOutsideMouseDown);
|
|
2366
|
+
return () => document.removeEventListener("mousedown", handleOutsideMouseDown);
|
|
2367
|
+
}, [dropdownMenu, isOpen, isDisable, onClose]);
|
|
2317
2368
|
const externalFieldLayout = !dropdownMenu ? {
|
|
2318
2369
|
width: "100%",
|
|
2319
2370
|
minWidth: menuMinWidth ?? EXTERNAL_MENU_MIN_WIDTH_DEFAULT,
|
|
2320
2371
|
boxSizing: "border-box"
|
|
2321
2372
|
} : void 0;
|
|
2322
2373
|
const dropdown = dropdownMenu && isOpen && !isDisable && (!isWeb || menuPosition) && /* @__PURE__ */ (0, import_jsx_runtime733.jsxs)(import_jsx_runtime733.Fragment, { children: [
|
|
2323
|
-
/* @__PURE__ */ (0, import_jsx_runtime733.jsx)(
|
|
2374
|
+
!isWeb && /* @__PURE__ */ (0, import_jsx_runtime733.jsx)(
|
|
2324
2375
|
Box,
|
|
2325
2376
|
{
|
|
2326
2377
|
"data-modal-id": modalId,
|
|
@@ -2336,7 +2387,7 @@ var MultiSelect = (0, import_react12.forwardRef)(
|
|
|
2336
2387
|
onPress: onClose
|
|
2337
2388
|
}
|
|
2338
2389
|
),
|
|
2339
|
-
/* @__PURE__ */ (0, import_jsx_runtime733.
|
|
2390
|
+
/* @__PURE__ */ (0, import_jsx_runtime733.jsxs)(
|
|
2340
2391
|
Box,
|
|
2341
2392
|
{
|
|
2342
2393
|
ref: menuRef,
|
|
@@ -2345,7 +2396,6 @@ var MultiSelect = (0, import_react12.forwardRef)(
|
|
|
2345
2396
|
borderColor: theme.colors.border.secondary,
|
|
2346
2397
|
borderWidth: 1,
|
|
2347
2398
|
borderRadius: sizeStyles.radius,
|
|
2348
|
-
paddingVertical: 4,
|
|
2349
2399
|
style: {
|
|
2350
2400
|
position: isWeb ? "fixed" : "absolute",
|
|
2351
2401
|
top: isWeb ? menuPosition?.top : "100%",
|
|
@@ -2355,54 +2405,134 @@ var MultiSelect = (0, import_react12.forwardRef)(
|
|
|
2355
2405
|
marginTop: isWeb ? void 0 : 4,
|
|
2356
2406
|
zIndex: 1001,
|
|
2357
2407
|
// Above control (1000) and backdrop (999)
|
|
2358
|
-
boxShadow: theme.shadow.popover
|
|
2359
|
-
maxHeight,
|
|
2360
|
-
overflowY: "auto"
|
|
2408
|
+
boxShadow: theme.shadow.popover
|
|
2361
2409
|
},
|
|
2362
|
-
children:
|
|
2363
|
-
|
|
2364
|
-
const contentColors = theme.colors.content;
|
|
2365
|
-
return /* @__PURE__ */ (0, import_jsx_runtime733.jsx)(
|
|
2410
|
+
children: [
|
|
2411
|
+
searchable && isWeb && /* @__PURE__ */ (0, import_jsx_runtime733.jsx)(
|
|
2366
2412
|
Box,
|
|
2367
2413
|
{
|
|
2368
|
-
testID,
|
|
2369
2414
|
paddingHorizontal: sizeStyles.paddingHorizontal,
|
|
2370
|
-
paddingVertical:
|
|
2371
|
-
|
|
2372
|
-
|
|
2373
|
-
|
|
2415
|
+
paddingVertical: sizeStyles.paddingVertical,
|
|
2416
|
+
borderBottomWidth: 1,
|
|
2417
|
+
borderColor: theme.colors.border.secondary,
|
|
2418
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime733.jsxs)(
|
|
2419
|
+
Box,
|
|
2420
|
+
{
|
|
2421
|
+
flexDirection: "row",
|
|
2422
|
+
alignItems: "center",
|
|
2423
|
+
gap: sizeStyles.paddingHorizontal / 2,
|
|
2424
|
+
paddingHorizontal: 4,
|
|
2425
|
+
children: [
|
|
2426
|
+
/* @__PURE__ */ (0, import_jsx_runtime733.jsx)(
|
|
2427
|
+
Icon,
|
|
2428
|
+
{
|
|
2429
|
+
size: sizeStyles.iconSize - 2,
|
|
2430
|
+
color: inputColors.placeholder,
|
|
2431
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime733.jsx)(Search, {})
|
|
2432
|
+
}
|
|
2433
|
+
),
|
|
2434
|
+
/* @__PURE__ */ (0, import_jsx_runtime733.jsx)(
|
|
2435
|
+
Box,
|
|
2436
|
+
{
|
|
2437
|
+
as: "input",
|
|
2438
|
+
ref: searchInputRef,
|
|
2439
|
+
testID: testID ? `${testID}-search-input` : void 0,
|
|
2440
|
+
flex: 1,
|
|
2441
|
+
type: "text",
|
|
2442
|
+
"aria-label": searchPlaceholder,
|
|
2443
|
+
value: searchValue,
|
|
2444
|
+
onChange: (e) => setSearchValue(e.target.value),
|
|
2445
|
+
placeholder: searchPlaceholder,
|
|
2446
|
+
style: {
|
|
2447
|
+
border: "none",
|
|
2448
|
+
outline: "none",
|
|
2449
|
+
background: "transparent",
|
|
2450
|
+
color: inputColors.text,
|
|
2451
|
+
fontSize: sizeStyles.fontSize,
|
|
2452
|
+
width: "100%"
|
|
2453
|
+
}
|
|
2454
|
+
}
|
|
2455
|
+
)
|
|
2456
|
+
]
|
|
2374
2457
|
}
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
|
|
2380
|
-
|
|
2381
|
-
|
|
2382
|
-
} : void 0,
|
|
2458
|
+
)
|
|
2459
|
+
}
|
|
2460
|
+
),
|
|
2461
|
+
/* @__PURE__ */ (0, import_jsx_runtime733.jsx)(
|
|
2462
|
+
Box,
|
|
2463
|
+
{
|
|
2464
|
+
paddingVertical: 4,
|
|
2383
2465
|
style: {
|
|
2384
|
-
|
|
2385
|
-
|
|
2466
|
+
maxHeight: searchable ? maxHeight - 60 : maxHeight,
|
|
2467
|
+
overflowY: "auto",
|
|
2468
|
+
overflowX: optionListOverflowX
|
|
2386
2469
|
},
|
|
2387
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime733.jsx)(
|
|
2388
|
-
|
|
2470
|
+
children: menuItems.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime733.jsx)(
|
|
2471
|
+
Box,
|
|
2389
2472
|
{
|
|
2390
|
-
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
children:
|
|
2473
|
+
paddingVertical: sizeStyles.paddingVertical * 2,
|
|
2474
|
+
paddingHorizontal: sizeStyles.paddingHorizontal,
|
|
2475
|
+
alignItems: "center",
|
|
2476
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime733.jsx)(
|
|
2477
|
+
Text,
|
|
2478
|
+
{
|
|
2479
|
+
color: theme.colors.content.tertiary,
|
|
2480
|
+
fontSize: sizeStyles.fontSize,
|
|
2481
|
+
children: noOptionsMessage
|
|
2482
|
+
}
|
|
2483
|
+
)
|
|
2394
2484
|
}
|
|
2395
|
-
)
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2485
|
+
) : menuItems.map((item, _index) => {
|
|
2486
|
+
const brandColors = theme.colors.control.brand.primary;
|
|
2487
|
+
const contentColors = theme.colors.content;
|
|
2488
|
+
return /* @__PURE__ */ (0, import_jsx_runtime733.jsx)(
|
|
2489
|
+
Box,
|
|
2490
|
+
{
|
|
2491
|
+
testID,
|
|
2492
|
+
paddingHorizontal: sizeStyles.paddingHorizontal,
|
|
2493
|
+
paddingVertical: 8,
|
|
2494
|
+
onPress: () => {
|
|
2495
|
+
if (!item.disabled) {
|
|
2496
|
+
handleItemToggle(item.id, !item.checked);
|
|
2497
|
+
}
|
|
2498
|
+
},
|
|
2499
|
+
flexDirection: "row",
|
|
2500
|
+
alignItems: "center",
|
|
2501
|
+
justifyContent: "space-between",
|
|
2502
|
+
backgroundColor: item.checked ? brandColors.bg : "transparent",
|
|
2503
|
+
hoverStyle: !item.disabled && !item.checked ? {
|
|
2504
|
+
backgroundColor: theme.colors.control.input.bgHover
|
|
2505
|
+
} : void 0,
|
|
2506
|
+
style: {
|
|
2507
|
+
cursor: item.disabled ? "not-allowed" : "pointer",
|
|
2508
|
+
opacity: item.disabled ? 0.5 : 1,
|
|
2509
|
+
minWidth: optionRowMinWidth
|
|
2510
|
+
},
|
|
2511
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime733.jsx)(
|
|
2512
|
+
Text,
|
|
2513
|
+
{
|
|
2514
|
+
color: item.checked ? contentColors.on.brand : theme.colors.content.secondary,
|
|
2515
|
+
fontSize: sizeStyles.fontSize,
|
|
2516
|
+
fontWeight: "400",
|
|
2517
|
+
numberOfLines: optionLabelNumberOfLines,
|
|
2518
|
+
style: optionLabelStyle,
|
|
2519
|
+
children: item.children
|
|
2520
|
+
}
|
|
2521
|
+
)
|
|
2522
|
+
},
|
|
2523
|
+
item.id
|
|
2524
|
+
);
|
|
2525
|
+
})
|
|
2526
|
+
}
|
|
2527
|
+
)
|
|
2528
|
+
]
|
|
2400
2529
|
}
|
|
2401
2530
|
)
|
|
2402
2531
|
] });
|
|
2403
2532
|
return /* @__PURE__ */ (0, import_jsx_runtime733.jsxs)(
|
|
2404
2533
|
Box,
|
|
2405
2534
|
{
|
|
2535
|
+
ref: containerRef,
|
|
2406
2536
|
testID,
|
|
2407
2537
|
flexDirection: "column",
|
|
2408
2538
|
gap: sizeStyles.fieldGap,
|