@xsolla/xui-multi-select 0.149.0-pr270.1777888548 → 0.149.1

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
@@ -139,51 +139,6 @@ export default function DisabledMultiSelect() {
139
139
  }
140
140
  ```
141
141
 
142
- ### External panel (B2B grouped select)
143
-
144
- When the option list is rendered elsewhere (for example [`@xsolla/xui-b2b-group-select`](./b2b-group-select.md)), set **`dropdownMenu={false}`** so the control does not open the built-in list. Wire the same **`value`** / **`onChange`** to both components; use **`onTriggerPress`** to toggle your panel, **`menuOpen`** for chevron/open styling, and **`menuMinWidth`** (default **540**, aligned with `GROUP_SELECT_MIN_PANEL_WIDTH`) so the field matches the panel width.
145
-
146
- ```tsx
147
- import * as React from 'react';
148
- import { MultiSelect } from '@xsolla/xui-multi-select';
149
- import {
150
- GroupSelect,
151
- GROUP_SELECT_MIN_PANEL_WIDTH,
152
- type GroupSelectGroup,
153
- } from '@xsolla/xui-b2b-group-select';
154
-
155
- const groups: GroupSelectGroup[] = [/* ... */];
156
- const flatOptions = groups.flatMap((g) =>
157
- g.items.map((it) => ({ value: it.id, label: it.label }))
158
- );
159
-
160
- export default function GroupedFieldShell() {
161
- const [value, setValue] = React.useState<string[]>([]);
162
- const [open, setOpen] = React.useState(false);
163
-
164
- return (
165
- <>
166
- <MultiSelect
167
- options={flatOptions}
168
- value={value}
169
- onChange={(v) => setValue(v.map(String))}
170
- placeholder="Select regions"
171
- size="sm"
172
- dropdownMenu={false}
173
- menuOpen={open}
174
- menuMinWidth={GROUP_SELECT_MIN_PANEL_WIDTH}
175
- onTriggerPress={() => setOpen((o) => !o)}
176
- />
177
- {open && (
178
- <GroupSelect groups={groups} value={value} onChange={setValue} />
179
- )}
180
- </>
181
- );
182
- }
183
- ```
184
-
185
- Add backdrop, click-outside, and Escape handling in your layout as needed (see Storybook).
186
-
187
142
  ## API Reference
188
143
 
189
144
  ### MultiSelect
@@ -199,10 +154,6 @@ Add backdrop, click-outside, and Escape handling in your layout as needed (see S
199
154
  | size | `"xs" \| "sm" \| "md" \| "lg" \| "xl"` | `"md"` | Component size. |
200
155
  | label | `string` | - | Label above select. |
201
156
  | disabled | `boolean` | `false` | Disabled state. |
202
- | dropdownMenu | `boolean` | `true` | When `false`, hides the built-in list; use with an external picker (e.g. B2B Group select). |
203
- | onTriggerPress | `() => void` | - | When `dropdownMenu` is false: called when the user activates the field (toggle external panel). |
204
- | menuOpen | `boolean` | `false` | When `dropdownMenu` is false: drives open/chevron state for the control. |
205
- | menuMinWidth | `number` | `540` | When `dropdownMenu` is false: field `min-width` in px (aligned with `GroupSelect`). |
206
157
 
207
158
  ## Display Behavior
208
159
 
@@ -83,29 +83,6 @@ interface MultiSelectProps extends ThemeOverrideProps {
83
83
  * @default 300
84
84
  */
85
85
  maxHeight?: number;
86
- /**
87
- * When false, the built-in options list and backdrop are not shown and the control
88
- * does not open on click. Use with an external picker (e.g. grouped select) wired
89
- * to the same `value` / `onChange`.
90
- * @default true
91
- */
92
- dropdownMenu?: boolean;
93
- /**
94
- * When `dropdownMenu` is false: fired when the user activates the field (same gesture
95
- * that would open the built-in list). Typically toggle an external panel.
96
- */
97
- onTriggerPress?: () => void;
98
- /**
99
- * When `dropdownMenu` is false: whether an external menu/panel is open — drives
100
- * chevron direction and control layering like the built-in open state.
101
- */
102
- menuOpen?: boolean;
103
- /**
104
- * When `dropdownMenu` is false: `min-width` of the field in px so it aligns with
105
- * a typical grouped panel (default **540**, same as `GroupSelect`). Use `0` for
106
- * no minimum. Ignored when the built-in dropdown is enabled.
107
- */
108
- menuMinWidth?: number;
109
86
  }
110
87
 
111
88
  declare const MultiSelect: react.ForwardRefExoticComponent<MultiSelectProps & react.RefAttributes<HTMLDivElement>>;
package/native/index.d.ts CHANGED
@@ -83,29 +83,6 @@ interface MultiSelectProps extends ThemeOverrideProps {
83
83
  * @default 300
84
84
  */
85
85
  maxHeight?: number;
86
- /**
87
- * When false, the built-in options list and backdrop are not shown and the control
88
- * does not open on click. Use with an external picker (e.g. grouped select) wired
89
- * to the same `value` / `onChange`.
90
- * @default true
91
- */
92
- dropdownMenu?: boolean;
93
- /**
94
- * When `dropdownMenu` is false: fired when the user activates the field (same gesture
95
- * that would open the built-in list). Typically toggle an external panel.
96
- */
97
- onTriggerPress?: () => void;
98
- /**
99
- * When `dropdownMenu` is false: whether an external menu/panel is open — drives
100
- * chevron direction and control layering like the built-in open state.
101
- */
102
- menuOpen?: boolean;
103
- /**
104
- * When `dropdownMenu` is false: `min-width` of the field in px so it aligns with
105
- * a typical grouped panel (default **540**, same as `GroupSelect`). Use `0` for
106
- * no minimum. Ignored when the built-in dropdown is enabled.
107
- */
108
- menuMinWidth?: number;
109
86
  }
110
87
 
111
88
  declare const MultiSelect: react.ForwardRefExoticComponent<MultiSelectProps & react.RefAttributes<HTMLDivElement>>;
package/native/index.js CHANGED
@@ -1926,7 +1926,6 @@ var MultiSelectControl = (0, import_react8.forwardRef)(
1926
1926
  iconRight,
1927
1927
  disabled = false,
1928
1928
  extraClear = false,
1929
- width,
1930
1929
  themeMode,
1931
1930
  themeProductContext
1932
1931
  }, ref) => {
@@ -1975,7 +1974,6 @@ var MultiSelectControl = (0, import_react8.forwardRef)(
1975
1974
  Box,
1976
1975
  {
1977
1976
  ref,
1978
- width,
1979
1977
  backgroundColor,
1980
1978
  borderColor,
1981
1979
  borderWidth: borderColor !== "transparent" ? 1 : 0,
@@ -1987,7 +1985,7 @@ var MultiSelectControl = (0, import_react8.forwardRef)(
1987
1985
  alignItems: "center",
1988
1986
  gap: 8,
1989
1987
  style: {
1990
- cursor: isDisable ? "not-allowed" : onClick ? "pointer" : "default",
1988
+ cursor: isDisable ? "not-allowed" : "pointer",
1991
1989
  boxSizing: "border-box",
1992
1990
  height: flexible ? "auto" : sizeStyles.height,
1993
1991
  position: "relative",
@@ -1995,7 +1993,7 @@ var MultiSelectControl = (0, import_react8.forwardRef)(
1995
1993
  // Above backdrop when open
1996
1994
  },
1997
1995
  onPress: isDisable ? void 0 : onClick,
1998
- hoverStyle: !isDisable && onClick && !isFocus && !isOpen && !isError ? {
1996
+ hoverStyle: !isDisable && !isFocus && !isOpen && !isError ? {
1999
1997
  backgroundColor: inputColors.bgHover,
2000
1998
  borderColor: inputColors.borderHover
2001
1999
  } : void 0,
@@ -2151,7 +2149,6 @@ var useMultiSelect = ({
2151
2149
 
2152
2150
  // src/MultiSelect.tsx
2153
2151
  var import_jsx_runtime733 = require("react/jsx-runtime");
2154
- var EXTERNAL_MENU_MIN_WIDTH_DEFAULT = 540;
2155
2152
  var MultiSelect = (0, import_react10.forwardRef)(
2156
2153
  ({
2157
2154
  options,
@@ -2170,10 +2167,6 @@ var MultiSelect = (0, import_react10.forwardRef)(
2170
2167
  iconLeft,
2171
2168
  iconRight,
2172
2169
  maxHeight = 300,
2173
- dropdownMenu = true,
2174
- onTriggerPress,
2175
- menuOpen = false,
2176
- menuMinWidth,
2177
2170
  themeMode,
2178
2171
  themeProductContext
2179
2172
  }, ref) => {
@@ -2201,10 +2194,10 @@ var MultiSelect = (0, import_react10.forwardRef)(
2201
2194
  onChange
2202
2195
  });
2203
2196
  (0, import_react10.useEffect)(() => {
2204
- if (isDisable || !dropdownMenu) {
2197
+ if (isDisable) {
2205
2198
  onClose();
2206
2199
  }
2207
- }, [isDisable, dropdownMenu, onClose]);
2200
+ }, [isDisable, onClose]);
2208
2201
  const menuItems = options.map((opt) => {
2209
2202
  const id = String(opt.value);
2210
2203
  const checked = values.map(String).includes(id);
@@ -2221,155 +2214,138 @@ var MultiSelect = (0, import_react10.forwardRef)(
2221
2214
  const newValues = checked ? [...values, value2] : values.filter((v) => v !== value2);
2222
2215
  onChoose(newValues.map(String));
2223
2216
  };
2224
- const controlMenuOpen = dropdownMenu ? isOpen : Boolean(menuOpen);
2225
- const controlOnClick = dropdownMenu ? onSelectClick : onTriggerPress;
2226
- const externalFieldLayout = !dropdownMenu ? {
2227
- width: "100%",
2228
- minWidth: menuMinWidth ?? EXTERNAL_MENU_MIN_WIDTH_DEFAULT,
2229
- boxSizing: "border-box"
2230
- } : void 0;
2231
- return /* @__PURE__ */ (0, import_jsx_runtime733.jsxs)(
2232
- Box,
2233
- {
2234
- flexDirection: "column",
2235
- gap: sizeStyles.fieldGap,
2236
- style: externalFieldLayout,
2237
- children: [
2238
- label && /* @__PURE__ */ (0, import_jsx_runtime733.jsx)(
2239
- Text,
2240
- {
2241
- color: theme.colors.content.secondary,
2242
- fontSize: sizeStyles.fontSize - 2,
2243
- fontWeight: "500",
2244
- children: label
2245
- }
2246
- ),
2247
- /* @__PURE__ */ (0, import_jsx_runtime733.jsxs)(
2248
- Box,
2249
- {
2250
- ref,
2251
- style: {
2252
- position: "relative",
2253
- ...externalFieldLayout ? { width: "100%" } : {}
2254
- },
2255
- children: [
2256
- /* @__PURE__ */ (0, import_jsx_runtime733.jsx)(
2257
- MultiSelectControl,
2258
- {
2259
- ref: controlRef,
2260
- isOpen: controlMenuOpen,
2261
- isFocus,
2262
- isError,
2263
- size,
2264
- state,
2265
- disabled: isDisable,
2266
- onClick: controlOnClick,
2267
- width: dropdownMenu ? void 0 : "100%",
2268
- removeValue: onRemove,
2269
- removeAllValues: onRemoveAll,
2270
- stateList,
2271
- selectedItems,
2272
- variant,
2273
- flexible,
2274
- placeholder,
2275
- removeTagsButtons,
2276
- iconLeft,
2277
- iconRight,
2278
- extraClear
2279
- }
2280
- ),
2281
- dropdownMenu && isOpen && !isDisable && /* @__PURE__ */ (0, import_jsx_runtime733.jsxs)(import_jsx_runtime733.Fragment, { children: [
2282
- /* @__PURE__ */ (0, import_jsx_runtime733.jsx)(
2283
- Box,
2284
- {
2285
- style: {
2286
- position: "fixed",
2287
- top: 0,
2288
- left: 0,
2289
- right: 0,
2290
- bottom: 0,
2291
- zIndex: 999,
2292
- cursor: "default"
2293
- },
2294
- onPress: onClose
2295
- }
2296
- ),
2297
- /* @__PURE__ */ (0, import_jsx_runtime733.jsx)(
2298
- Box,
2299
- {
2300
- ref: menuRef,
2301
- backgroundColor: theme.colors.background.secondary,
2302
- borderColor: theme.colors.border.secondary,
2303
- borderWidth: 1,
2304
- borderRadius: theme.radius.button,
2305
- paddingVertical: 4,
2306
- style: {
2307
- position: "absolute",
2308
- top: "100%",
2309
- left: 0,
2310
- right: 0,
2311
- marginTop: 4,
2312
- zIndex: 1001,
2313
- // Above control (1000) and backdrop (999)
2314
- boxShadow: theme.shadow.popover,
2315
- maxHeight,
2316
- overflowY: "auto"
2317
- },
2318
- children: menuItems.map((item, _index) => {
2319
- const brandColors = theme.colors.control.brand.primary;
2320
- const contentColors = theme.colors.content;
2321
- return /* @__PURE__ */ (0, import_jsx_runtime733.jsx)(
2322
- Box,
2217
+ return /* @__PURE__ */ (0, import_jsx_runtime733.jsxs)(Box, { flexDirection: "column", gap: sizeStyles.fieldGap, children: [
2218
+ label && /* @__PURE__ */ (0, import_jsx_runtime733.jsx)(
2219
+ Text,
2220
+ {
2221
+ color: theme.colors.content.secondary,
2222
+ fontSize: sizeStyles.fontSize - 2,
2223
+ fontWeight: "500",
2224
+ children: label
2225
+ }
2226
+ ),
2227
+ /* @__PURE__ */ (0, import_jsx_runtime733.jsxs)(
2228
+ Box,
2229
+ {
2230
+ ref,
2231
+ style: {
2232
+ position: "relative"
2233
+ },
2234
+ children: [
2235
+ /* @__PURE__ */ (0, import_jsx_runtime733.jsx)(
2236
+ MultiSelectControl,
2237
+ {
2238
+ ref: controlRef,
2239
+ isOpen,
2240
+ isFocus,
2241
+ isError,
2242
+ size,
2243
+ state,
2244
+ disabled: isDisable,
2245
+ onClick: onSelectClick,
2246
+ removeValue: onRemove,
2247
+ removeAllValues: onRemoveAll,
2248
+ stateList,
2249
+ selectedItems,
2250
+ variant,
2251
+ flexible,
2252
+ placeholder,
2253
+ removeTagsButtons,
2254
+ iconLeft,
2255
+ iconRight,
2256
+ extraClear
2257
+ }
2258
+ ),
2259
+ isOpen && !isDisable && /* @__PURE__ */ (0, import_jsx_runtime733.jsxs)(import_jsx_runtime733.Fragment, { children: [
2260
+ /* @__PURE__ */ (0, import_jsx_runtime733.jsx)(
2261
+ Box,
2262
+ {
2263
+ style: {
2264
+ position: "fixed",
2265
+ top: 0,
2266
+ left: 0,
2267
+ right: 0,
2268
+ bottom: 0,
2269
+ zIndex: 999,
2270
+ cursor: "default"
2271
+ },
2272
+ onPress: onClose
2273
+ }
2274
+ ),
2275
+ /* @__PURE__ */ (0, import_jsx_runtime733.jsx)(
2276
+ Box,
2277
+ {
2278
+ ref: menuRef,
2279
+ backgroundColor: theme.colors.background.secondary,
2280
+ borderColor: theme.colors.border.secondary,
2281
+ borderWidth: 1,
2282
+ borderRadius: theme.radius.button,
2283
+ paddingVertical: 4,
2284
+ style: {
2285
+ position: "absolute",
2286
+ top: "100%",
2287
+ left: 0,
2288
+ right: 0,
2289
+ marginTop: 4,
2290
+ zIndex: 1001,
2291
+ // Above control (1000) and backdrop (999)
2292
+ boxShadow: theme.shadow.popover,
2293
+ maxHeight,
2294
+ overflowY: "auto"
2295
+ },
2296
+ children: menuItems.map((item, _index) => {
2297
+ const brandColors = theme.colors.control.brand.primary;
2298
+ const contentColors = theme.colors.content;
2299
+ return /* @__PURE__ */ (0, import_jsx_runtime733.jsx)(
2300
+ Box,
2301
+ {
2302
+ paddingHorizontal: sizeStyles.paddingHorizontal,
2303
+ paddingVertical: 8,
2304
+ onPress: () => {
2305
+ if (!item.disabled) {
2306
+ handleItemToggle(item.id, !item.checked);
2307
+ }
2308
+ },
2309
+ flexDirection: "row",
2310
+ alignItems: "center",
2311
+ justifyContent: "space-between",
2312
+ backgroundColor: item.checked ? brandColors.bg : "transparent",
2313
+ hoverStyle: !item.disabled && !item.checked ? {
2314
+ backgroundColor: theme.colors.control.input.bgHover
2315
+ } : void 0,
2316
+ style: {
2317
+ cursor: item.disabled ? "not-allowed" : "pointer",
2318
+ opacity: item.disabled ? 0.5 : 1
2319
+ },
2320
+ children: /* @__PURE__ */ (0, import_jsx_runtime733.jsx)(
2321
+ Text,
2323
2322
  {
2324
- paddingHorizontal: sizeStyles.paddingHorizontal,
2325
- paddingVertical: 8,
2326
- onPress: () => {
2327
- if (!item.disabled) {
2328
- handleItemToggle(item.id, !item.checked);
2329
- }
2330
- },
2331
- flexDirection: "row",
2332
- alignItems: "center",
2333
- justifyContent: "space-between",
2334
- backgroundColor: item.checked ? brandColors.bg : "transparent",
2335
- hoverStyle: !item.disabled && !item.checked ? {
2336
- backgroundColor: theme.colors.control.input.bgHover
2337
- } : void 0,
2338
- style: {
2339
- cursor: item.disabled ? "not-allowed" : "pointer",
2340
- opacity: item.disabled ? 0.5 : 1
2341
- },
2342
- children: /* @__PURE__ */ (0, import_jsx_runtime733.jsx)(
2343
- Text,
2344
- {
2345
- color: item.checked ? contentColors.on.brand : theme.colors.content.secondary,
2346
- fontSize: sizeStyles.fontSize,
2347
- fontWeight: "400",
2348
- children: item.children
2349
- }
2350
- )
2351
- },
2352
- item.id
2353
- );
2354
- })
2355
- }
2356
- )
2357
- ] })
2358
- ]
2359
- }
2360
- ),
2361
- errorMessage && /* @__PURE__ */ (0, import_jsx_runtime733.jsx)(
2362
- Text,
2363
- {
2364
- color: theme.colors.content.alert.primary,
2365
- fontSize: sizeStyles.fontSize - 2,
2366
- style: { lineHeight: sizeStyles.lineHeight + "px" },
2367
- children: errorMessage
2368
- }
2369
- )
2370
- ]
2371
- }
2372
- );
2323
+ color: item.checked ? contentColors.on.brand : theme.colors.content.secondary,
2324
+ fontSize: sizeStyles.fontSize,
2325
+ fontWeight: "400",
2326
+ children: item.children
2327
+ }
2328
+ )
2329
+ },
2330
+ item.id
2331
+ );
2332
+ })
2333
+ }
2334
+ )
2335
+ ] })
2336
+ ]
2337
+ }
2338
+ ),
2339
+ errorMessage && /* @__PURE__ */ (0, import_jsx_runtime733.jsx)(
2340
+ Text,
2341
+ {
2342
+ color: theme.colors.content.alert.primary,
2343
+ fontSize: sizeStyles.fontSize - 2,
2344
+ style: { lineHeight: sizeStyles.lineHeight + "px" },
2345
+ children: errorMessage
2346
+ }
2347
+ )
2348
+ ] });
2373
2349
  }
2374
2350
  );
2375
2351
  MultiSelect.displayName = "MultiSelect";