@xsolla/xui-multi-select 0.175.0 → 0.176.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xsolla/xui-multi-select",
3
- "version": "0.175.0",
3
+ "version": "0.176.1",
4
4
  "main": "./web/index.js",
5
5
  "module": "./web/index.mjs",
6
6
  "types": "./web/index.d.ts",
@@ -10,13 +10,14 @@
10
10
  "build:native": "PLATFORM=native tsup"
11
11
  },
12
12
  "dependencies": {
13
- "@xsolla/xui-checkbox": "0.175.0",
14
- "@xsolla/xui-core": "0.175.0",
15
- "@xsolla/xui-dropdown": "0.175.0",
16
- "@xsolla/xui-primitives-core": "0.175.0"
13
+ "@xsolla/xui-checkbox": "0.176.1",
14
+ "@xsolla/xui-core": "0.176.1",
15
+ "@xsolla/xui-dropdown": "0.176.1",
16
+ "@xsolla/xui-primitives-core": "0.176.1"
17
17
  },
18
18
  "peerDependencies": {
19
19
  "react": ">=16.8.0",
20
+ "react-dom": ">=16.8.0",
20
21
  "styled-components": ">=4"
21
22
  },
22
23
  "devDependencies": {
package/web/index.js CHANGED
@@ -35,7 +35,7 @@ __export(index_exports, {
35
35
  module.exports = __toCommonJS(index_exports);
36
36
 
37
37
  // src/MultiSelect.tsx
38
- var import_react11 = require("react");
38
+ var import_react12 = require("react");
39
39
 
40
40
  // ../../foundation/primitives-web/src/Box.tsx
41
41
  var import_react2 = __toESM(require("react"));
@@ -353,6 +353,9 @@ var Icon = ({
353
353
  return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(StyledIcon, { "data-testid": dataTestId || testID, ...props, children });
354
354
  };
355
355
 
356
+ // ../../foundation/primitives-web/src/index.tsx
357
+ var isWeb = true;
358
+
356
359
  // src/MultiSelect.tsx
357
360
  var import_xui_core4 = require("@xsolla/xui-core");
358
361
 
@@ -2205,10 +2208,20 @@ var useMultiSelect = ({
2205
2208
  };
2206
2209
  };
2207
2210
 
2211
+ // src/Portal.web.tsx
2212
+ var import_react11 = require("react");
2213
+ var import_react_dom = require("react-dom");
2214
+ var Portal = ({ children }) => {
2215
+ const [mountNode, setMountNode] = (0, import_react11.useState)(null);
2216
+ (0, import_react11.useEffect)(() => setMountNode(document.body), []);
2217
+ if (!mountNode) return null;
2218
+ return (0, import_react_dom.createPortal)(children, mountNode);
2219
+ };
2220
+
2208
2221
  // src/MultiSelect.tsx
2209
2222
  var import_jsx_runtime733 = require("react/jsx-runtime");
2210
2223
  var EXTERNAL_MENU_MIN_WIDTH_DEFAULT = 540;
2211
- var MultiSelect = (0, import_react11.forwardRef)(
2224
+ var MultiSelect = (0, import_react12.forwardRef)(
2212
2225
  ({
2213
2226
  options,
2214
2227
  errorMessage,
@@ -2235,8 +2248,10 @@ var MultiSelect = (0, import_react11.forwardRef)(
2235
2248
  themeProductContext
2236
2249
  }, ref) => {
2237
2250
  const { theme } = (0, import_xui_core4.useResolvedTheme)({ themeMode, themeProductContext });
2238
- const controlRef = (0, import_react11.useRef)(null);
2239
- const menuRef = (0, import_react11.useRef)(null);
2251
+ const modalId = (0, import_xui_core4.useModalId)();
2252
+ const controlRef = (0, import_react12.useRef)(null);
2253
+ const menuRef = (0, import_react12.useRef)(null);
2254
+ const [menuPosition, setMenuPosition] = (0, import_react12.useState)(null);
2240
2255
  const sizeStyles = theme.sizing.input(size);
2241
2256
  const state = externalState || (disabled ? "disable" : "default");
2242
2257
  const isDisable = state === "disable" || disabled;
@@ -2257,7 +2272,7 @@ var MultiSelect = (0, import_react11.forwardRef)(
2257
2272
  value,
2258
2273
  onChange
2259
2274
  });
2260
- (0, import_react11.useEffect)(() => {
2275
+ (0, import_react12.useEffect)(() => {
2261
2276
  if (isDisable || !dropdownMenu) {
2262
2277
  onClose();
2263
2278
  }
@@ -2280,11 +2295,111 @@ var MultiSelect = (0, import_react11.forwardRef)(
2280
2295
  };
2281
2296
  const controlMenuOpen = dropdownMenu ? isOpen : Boolean(menuOpen);
2282
2297
  const controlOnClick = dropdownMenu ? onSelectClick : onTriggerPress;
2298
+ const updateMenuPosition = (0, import_react12.useCallback)(() => {
2299
+ if (!isWeb || !controlRef.current) return;
2300
+ const rect = controlRef.current.getBoundingClientRect();
2301
+ setMenuPosition({
2302
+ left: rect.left,
2303
+ top: rect.bottom + 4,
2304
+ width: rect.width
2305
+ });
2306
+ }, []);
2307
+ (0, import_react12.useEffect)(() => {
2308
+ if (!isWeb || !controlMenuOpen || isDisable || !dropdownMenu) return;
2309
+ updateMenuPosition();
2310
+ window.addEventListener("resize", updateMenuPosition);
2311
+ window.addEventListener("scroll", updateMenuPosition, true);
2312
+ return () => {
2313
+ window.removeEventListener("resize", updateMenuPosition);
2314
+ window.removeEventListener("scroll", updateMenuPosition, true);
2315
+ };
2316
+ }, [controlMenuOpen, dropdownMenu, isDisable, updateMenuPosition]);
2283
2317
  const externalFieldLayout = !dropdownMenu ? {
2284
2318
  width: "100%",
2285
2319
  minWidth: menuMinWidth ?? EXTERNAL_MENU_MIN_WIDTH_DEFAULT,
2286
2320
  boxSizing: "border-box"
2287
2321
  } : void 0;
2322
+ 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)(
2324
+ Box,
2325
+ {
2326
+ "data-modal-id": modalId,
2327
+ style: {
2328
+ position: "fixed",
2329
+ top: 0,
2330
+ left: 0,
2331
+ right: 0,
2332
+ bottom: 0,
2333
+ zIndex: 999,
2334
+ cursor: "default"
2335
+ },
2336
+ onPress: onClose
2337
+ }
2338
+ ),
2339
+ /* @__PURE__ */ (0, import_jsx_runtime733.jsx)(
2340
+ Box,
2341
+ {
2342
+ ref: menuRef,
2343
+ "data-modal-id": modalId,
2344
+ backgroundColor: theme.colors.background.secondary,
2345
+ borderColor: theme.colors.border.secondary,
2346
+ borderWidth: 1,
2347
+ borderRadius: sizeStyles.radius,
2348
+ paddingVertical: 4,
2349
+ style: {
2350
+ position: isWeb ? "fixed" : "absolute",
2351
+ top: isWeb ? menuPosition?.top : "100%",
2352
+ left: isWeb ? menuPosition?.left : 0,
2353
+ right: isWeb ? void 0 : 0,
2354
+ width: isWeb ? menuPosition?.width : void 0,
2355
+ marginTop: isWeb ? void 0 : 4,
2356
+ zIndex: 1001,
2357
+ // Above control (1000) and backdrop (999)
2358
+ boxShadow: theme.shadow.popover,
2359
+ maxHeight,
2360
+ overflowY: "auto"
2361
+ },
2362
+ children: menuItems.map((item, _index) => {
2363
+ const brandColors = theme.colors.control.brand.primary;
2364
+ const contentColors = theme.colors.content;
2365
+ return /* @__PURE__ */ (0, import_jsx_runtime733.jsx)(
2366
+ Box,
2367
+ {
2368
+ testID,
2369
+ paddingHorizontal: sizeStyles.paddingHorizontal,
2370
+ paddingVertical: 8,
2371
+ onPress: () => {
2372
+ if (!item.disabled) {
2373
+ handleItemToggle(item.id, !item.checked);
2374
+ }
2375
+ },
2376
+ flexDirection: "row",
2377
+ alignItems: "center",
2378
+ justifyContent: "space-between",
2379
+ backgroundColor: item.checked ? brandColors.bg : "transparent",
2380
+ hoverStyle: !item.disabled && !item.checked ? {
2381
+ backgroundColor: theme.colors.control.input.bgHover
2382
+ } : void 0,
2383
+ style: {
2384
+ cursor: item.disabled ? "not-allowed" : "pointer",
2385
+ opacity: item.disabled ? 0.5 : 1
2386
+ },
2387
+ children: /* @__PURE__ */ (0, import_jsx_runtime733.jsx)(
2388
+ Text,
2389
+ {
2390
+ color: item.checked ? contentColors.on.brand : theme.colors.content.secondary,
2391
+ fontSize: sizeStyles.fontSize,
2392
+ fontWeight: "400",
2393
+ children: item.children
2394
+ }
2395
+ )
2396
+ },
2397
+ item.id
2398
+ );
2399
+ })
2400
+ }
2401
+ )
2402
+ ] });
2288
2403
  return /* @__PURE__ */ (0, import_jsx_runtime733.jsxs)(
2289
2404
  Box,
2290
2405
  {
@@ -2336,84 +2451,7 @@ var MultiSelect = (0, import_react11.forwardRef)(
2336
2451
  extraClear
2337
2452
  }
2338
2453
  ),
2339
- dropdownMenu && isOpen && !isDisable && /* @__PURE__ */ (0, import_jsx_runtime733.jsxs)(import_jsx_runtime733.Fragment, { children: [
2340
- /* @__PURE__ */ (0, import_jsx_runtime733.jsx)(
2341
- Box,
2342
- {
2343
- style: {
2344
- position: "fixed",
2345
- top: 0,
2346
- left: 0,
2347
- right: 0,
2348
- bottom: 0,
2349
- zIndex: 999,
2350
- cursor: "default"
2351
- },
2352
- onPress: onClose
2353
- }
2354
- ),
2355
- /* @__PURE__ */ (0, import_jsx_runtime733.jsx)(
2356
- Box,
2357
- {
2358
- ref: menuRef,
2359
- backgroundColor: theme.colors.background.secondary,
2360
- borderColor: theme.colors.border.secondary,
2361
- borderWidth: 1,
2362
- borderRadius: theme.shape.input[size].borderRadius,
2363
- paddingVertical: 4,
2364
- style: {
2365
- position: "absolute",
2366
- top: "100%",
2367
- left: 0,
2368
- right: 0,
2369
- marginTop: 4,
2370
- zIndex: 1001,
2371
- // Above control (1000) and backdrop (999)
2372
- boxShadow: theme.shadow.popover,
2373
- maxHeight,
2374
- overflowY: "auto"
2375
- },
2376
- children: menuItems.map((item, _index) => {
2377
- const brandColors = theme.colors.control.brand.primary;
2378
- const contentColors = theme.colors.content;
2379
- return /* @__PURE__ */ (0, import_jsx_runtime733.jsx)(
2380
- Box,
2381
- {
2382
- testID,
2383
- paddingHorizontal: sizeStyles.paddingHorizontal,
2384
- paddingVertical: 8,
2385
- onPress: () => {
2386
- if (!item.disabled) {
2387
- handleItemToggle(item.id, !item.checked);
2388
- }
2389
- },
2390
- flexDirection: "row",
2391
- alignItems: "center",
2392
- justifyContent: "space-between",
2393
- backgroundColor: item.checked ? brandColors.bg : "transparent",
2394
- hoverStyle: !item.disabled && !item.checked ? {
2395
- backgroundColor: theme.colors.control.input.bgHover
2396
- } : void 0,
2397
- style: {
2398
- cursor: item.disabled ? "not-allowed" : "pointer",
2399
- opacity: item.disabled ? 0.5 : 1
2400
- },
2401
- children: /* @__PURE__ */ (0, import_jsx_runtime733.jsx)(
2402
- Text,
2403
- {
2404
- color: item.checked ? contentColors.on.brand : theme.colors.content.secondary,
2405
- fontSize: sizeStyles.fontSize,
2406
- fontWeight: "400",
2407
- children: item.children
2408
- }
2409
- )
2410
- },
2411
- item.id
2412
- );
2413
- })
2414
- }
2415
- )
2416
- ] })
2454
+ isWeb ? /* @__PURE__ */ (0, import_jsx_runtime733.jsx)(Portal, { children: dropdown }) : dropdown
2417
2455
  ]
2418
2456
  }
2419
2457
  ),