@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/native/index.js CHANGED
@@ -306,6 +306,9 @@ var Icon = ({
306
306
  return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native3.View, { style, testID: dataTestId || testID, children: childrenWithProps });
307
307
  };
308
308
 
309
+ // ../../foundation/primitives-native/src/index.tsx
310
+ var isWeb = false;
311
+
309
312
  // src/MultiSelect.tsx
310
313
  var import_xui_core4 = require("@xsolla/xui-core");
311
314
 
@@ -2158,8 +2161,12 @@ var useMultiSelect = ({
2158
2161
  };
2159
2162
  };
2160
2163
 
2161
- // src/MultiSelect.tsx
2164
+ // src/Portal.native.tsx
2162
2165
  var import_jsx_runtime733 = require("react/jsx-runtime");
2166
+ var Portal = ({ children }) => /* @__PURE__ */ (0, import_jsx_runtime733.jsx)(import_jsx_runtime733.Fragment, { children });
2167
+
2168
+ // src/MultiSelect.tsx
2169
+ var import_jsx_runtime734 = require("react/jsx-runtime");
2163
2170
  var EXTERNAL_MENU_MIN_WIDTH_DEFAULT = 540;
2164
2171
  var MultiSelect = (0, import_react10.forwardRef)(
2165
2172
  ({
@@ -2188,8 +2195,10 @@ var MultiSelect = (0, import_react10.forwardRef)(
2188
2195
  themeProductContext
2189
2196
  }, ref) => {
2190
2197
  const { theme } = (0, import_xui_core4.useResolvedTheme)({ themeMode, themeProductContext });
2198
+ const modalId = (0, import_xui_core4.useModalId)();
2191
2199
  const controlRef = (0, import_react10.useRef)(null);
2192
2200
  const menuRef = (0, import_react10.useRef)(null);
2201
+ const [menuPosition, setMenuPosition] = (0, import_react10.useState)(null);
2193
2202
  const sizeStyles = theme.sizing.input(size);
2194
2203
  const state = externalState || (disabled ? "disable" : "default");
2195
2204
  const isDisable = state === "disable" || disabled;
@@ -2233,12 +2242,112 @@ var MultiSelect = (0, import_react10.forwardRef)(
2233
2242
  };
2234
2243
  const controlMenuOpen = dropdownMenu ? isOpen : Boolean(menuOpen);
2235
2244
  const controlOnClick = dropdownMenu ? onSelectClick : onTriggerPress;
2245
+ const updateMenuPosition = (0, import_react10.useCallback)(() => {
2246
+ if (!isWeb || !controlRef.current) return;
2247
+ const rect = controlRef.current.getBoundingClientRect();
2248
+ setMenuPosition({
2249
+ left: rect.left,
2250
+ top: rect.bottom + 4,
2251
+ width: rect.width
2252
+ });
2253
+ }, []);
2254
+ (0, import_react10.useEffect)(() => {
2255
+ if (!isWeb || !controlMenuOpen || isDisable || !dropdownMenu) return;
2256
+ updateMenuPosition();
2257
+ window.addEventListener("resize", updateMenuPosition);
2258
+ window.addEventListener("scroll", updateMenuPosition, true);
2259
+ return () => {
2260
+ window.removeEventListener("resize", updateMenuPosition);
2261
+ window.removeEventListener("scroll", updateMenuPosition, true);
2262
+ };
2263
+ }, [controlMenuOpen, dropdownMenu, isDisable, updateMenuPosition]);
2236
2264
  const externalFieldLayout = !dropdownMenu ? {
2237
2265
  width: "100%",
2238
2266
  minWidth: menuMinWidth ?? EXTERNAL_MENU_MIN_WIDTH_DEFAULT,
2239
2267
  boxSizing: "border-box"
2240
2268
  } : void 0;
2241
- return /* @__PURE__ */ (0, import_jsx_runtime733.jsxs)(
2269
+ const dropdown = dropdownMenu && isOpen && !isDisable && (!isWeb || menuPosition) && /* @__PURE__ */ (0, import_jsx_runtime734.jsxs)(import_jsx_runtime734.Fragment, { children: [
2270
+ /* @__PURE__ */ (0, import_jsx_runtime734.jsx)(
2271
+ Box,
2272
+ {
2273
+ "data-modal-id": modalId,
2274
+ style: {
2275
+ position: "fixed",
2276
+ top: 0,
2277
+ left: 0,
2278
+ right: 0,
2279
+ bottom: 0,
2280
+ zIndex: 999,
2281
+ cursor: "default"
2282
+ },
2283
+ onPress: onClose
2284
+ }
2285
+ ),
2286
+ /* @__PURE__ */ (0, import_jsx_runtime734.jsx)(
2287
+ Box,
2288
+ {
2289
+ ref: menuRef,
2290
+ "data-modal-id": modalId,
2291
+ backgroundColor: theme.colors.background.secondary,
2292
+ borderColor: theme.colors.border.secondary,
2293
+ borderWidth: 1,
2294
+ borderRadius: sizeStyles.radius,
2295
+ paddingVertical: 4,
2296
+ style: {
2297
+ position: isWeb ? "fixed" : "absolute",
2298
+ top: isWeb ? menuPosition?.top : "100%",
2299
+ left: isWeb ? menuPosition?.left : 0,
2300
+ right: isWeb ? void 0 : 0,
2301
+ width: isWeb ? menuPosition?.width : void 0,
2302
+ marginTop: isWeb ? void 0 : 4,
2303
+ zIndex: 1001,
2304
+ // Above control (1000) and backdrop (999)
2305
+ boxShadow: theme.shadow.popover,
2306
+ maxHeight,
2307
+ overflowY: "auto"
2308
+ },
2309
+ children: menuItems.map((item, _index) => {
2310
+ const brandColors = theme.colors.control.brand.primary;
2311
+ const contentColors = theme.colors.content;
2312
+ return /* @__PURE__ */ (0, import_jsx_runtime734.jsx)(
2313
+ Box,
2314
+ {
2315
+ testID,
2316
+ paddingHorizontal: sizeStyles.paddingHorizontal,
2317
+ paddingVertical: 8,
2318
+ onPress: () => {
2319
+ if (!item.disabled) {
2320
+ handleItemToggle(item.id, !item.checked);
2321
+ }
2322
+ },
2323
+ flexDirection: "row",
2324
+ alignItems: "center",
2325
+ justifyContent: "space-between",
2326
+ backgroundColor: item.checked ? brandColors.bg : "transparent",
2327
+ hoverStyle: !item.disabled && !item.checked ? {
2328
+ backgroundColor: theme.colors.control.input.bgHover
2329
+ } : void 0,
2330
+ style: {
2331
+ cursor: item.disabled ? "not-allowed" : "pointer",
2332
+ opacity: item.disabled ? 0.5 : 1
2333
+ },
2334
+ children: /* @__PURE__ */ (0, import_jsx_runtime734.jsx)(
2335
+ Text,
2336
+ {
2337
+ color: item.checked ? contentColors.on.brand : theme.colors.content.secondary,
2338
+ fontSize: sizeStyles.fontSize,
2339
+ fontWeight: "400",
2340
+ children: item.children
2341
+ }
2342
+ )
2343
+ },
2344
+ item.id
2345
+ );
2346
+ })
2347
+ }
2348
+ )
2349
+ ] });
2350
+ return /* @__PURE__ */ (0, import_jsx_runtime734.jsxs)(
2242
2351
  Box,
2243
2352
  {
2244
2353
  testID,
@@ -2246,7 +2355,7 @@ var MultiSelect = (0, import_react10.forwardRef)(
2246
2355
  gap: sizeStyles.fieldGap,
2247
2356
  style: externalFieldLayout,
2248
2357
  children: [
2249
- label && /* @__PURE__ */ (0, import_jsx_runtime733.jsx)(
2358
+ label && /* @__PURE__ */ (0, import_jsx_runtime734.jsx)(
2250
2359
  Text,
2251
2360
  {
2252
2361
  color: theme.colors.content.secondary,
@@ -2255,7 +2364,7 @@ var MultiSelect = (0, import_react10.forwardRef)(
2255
2364
  children: label
2256
2365
  }
2257
2366
  ),
2258
- /* @__PURE__ */ (0, import_jsx_runtime733.jsxs)(
2367
+ /* @__PURE__ */ (0, import_jsx_runtime734.jsxs)(
2259
2368
  Box,
2260
2369
  {
2261
2370
  ref,
@@ -2264,7 +2373,7 @@ var MultiSelect = (0, import_react10.forwardRef)(
2264
2373
  ...externalFieldLayout ? { width: "100%" } : {}
2265
2374
  },
2266
2375
  children: [
2267
- /* @__PURE__ */ (0, import_jsx_runtime733.jsx)(
2376
+ /* @__PURE__ */ (0, import_jsx_runtime734.jsx)(
2268
2377
  MultiSelectControl,
2269
2378
  {
2270
2379
  ref: controlRef,
@@ -2289,88 +2398,11 @@ var MultiSelect = (0, import_react10.forwardRef)(
2289
2398
  extraClear
2290
2399
  }
2291
2400
  ),
2292
- dropdownMenu && isOpen && !isDisable && /* @__PURE__ */ (0, import_jsx_runtime733.jsxs)(import_jsx_runtime733.Fragment, { children: [
2293
- /* @__PURE__ */ (0, import_jsx_runtime733.jsx)(
2294
- Box,
2295
- {
2296
- style: {
2297
- position: "fixed",
2298
- top: 0,
2299
- left: 0,
2300
- right: 0,
2301
- bottom: 0,
2302
- zIndex: 999,
2303
- cursor: "default"
2304
- },
2305
- onPress: onClose
2306
- }
2307
- ),
2308
- /* @__PURE__ */ (0, import_jsx_runtime733.jsx)(
2309
- Box,
2310
- {
2311
- ref: menuRef,
2312
- backgroundColor: theme.colors.background.secondary,
2313
- borderColor: theme.colors.border.secondary,
2314
- borderWidth: 1,
2315
- borderRadius: theme.shape.input[size].borderRadius,
2316
- paddingVertical: 4,
2317
- style: {
2318
- position: "absolute",
2319
- top: "100%",
2320
- left: 0,
2321
- right: 0,
2322
- marginTop: 4,
2323
- zIndex: 1001,
2324
- // Above control (1000) and backdrop (999)
2325
- boxShadow: theme.shadow.popover,
2326
- maxHeight,
2327
- overflowY: "auto"
2328
- },
2329
- children: menuItems.map((item, _index) => {
2330
- const brandColors = theme.colors.control.brand.primary;
2331
- const contentColors = theme.colors.content;
2332
- return /* @__PURE__ */ (0, import_jsx_runtime733.jsx)(
2333
- Box,
2334
- {
2335
- testID,
2336
- paddingHorizontal: sizeStyles.paddingHorizontal,
2337
- paddingVertical: 8,
2338
- onPress: () => {
2339
- if (!item.disabled) {
2340
- handleItemToggle(item.id, !item.checked);
2341
- }
2342
- },
2343
- flexDirection: "row",
2344
- alignItems: "center",
2345
- justifyContent: "space-between",
2346
- backgroundColor: item.checked ? brandColors.bg : "transparent",
2347
- hoverStyle: !item.disabled && !item.checked ? {
2348
- backgroundColor: theme.colors.control.input.bgHover
2349
- } : void 0,
2350
- style: {
2351
- cursor: item.disabled ? "not-allowed" : "pointer",
2352
- opacity: item.disabled ? 0.5 : 1
2353
- },
2354
- children: /* @__PURE__ */ (0, import_jsx_runtime733.jsx)(
2355
- Text,
2356
- {
2357
- color: item.checked ? contentColors.on.brand : theme.colors.content.secondary,
2358
- fontSize: sizeStyles.fontSize,
2359
- fontWeight: "400",
2360
- children: item.children
2361
- }
2362
- )
2363
- },
2364
- item.id
2365
- );
2366
- })
2367
- }
2368
- )
2369
- ] })
2401
+ isWeb ? /* @__PURE__ */ (0, import_jsx_runtime734.jsx)(Portal, { children: dropdown }) : dropdown
2370
2402
  ]
2371
2403
  }
2372
2404
  ),
2373
- errorMessage && /* @__PURE__ */ (0, import_jsx_runtime733.jsx)(
2405
+ errorMessage && /* @__PURE__ */ (0, import_jsx_runtime734.jsx)(
2374
2406
  Text,
2375
2407
  {
2376
2408
  color: theme.colors.content.alert.primary,