@xsolla/xui-multi-select 0.176.0 → 0.177.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/native/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/MultiSelect.tsx
2
- import { forwardRef as forwardRef4, useRef as useRef4, useEffect as useEffect3 } from "react";
2
+ import { forwardRef as forwardRef4, useRef as useRef4, useEffect as useEffect3, useState as useState3, useCallback as useCallback2 } from "react";
3
3
 
4
4
  // ../../foundation/primitives-native/src/Box.tsx
5
5
  import {
@@ -277,8 +277,11 @@ var Icon = ({
277
277
  return /* @__PURE__ */ jsx3(View2, { style, testID: dataTestId || testID, children: childrenWithProps });
278
278
  };
279
279
 
280
+ // ../../foundation/primitives-native/src/index.tsx
281
+ var isWeb = false;
282
+
280
283
  // src/MultiSelect.tsx
281
- import { useResolvedTheme as useResolvedTheme4 } from "@xsolla/xui-core";
284
+ import { useModalId, useResolvedTheme as useResolvedTheme4 } from "@xsolla/xui-core";
282
285
 
283
286
  // src/MultiSelectControl.tsx
284
287
  import { forwardRef as forwardRef3, useRef as useRef2 } from "react";
@@ -2134,8 +2137,12 @@ var useMultiSelect = ({
2134
2137
  };
2135
2138
  };
2136
2139
 
2140
+ // src/Portal.native.tsx
2141
+ import { Fragment, jsx as jsx726 } from "react/jsx-runtime";
2142
+ var Portal = ({ children }) => /* @__PURE__ */ jsx726(Fragment, { children });
2143
+
2137
2144
  // src/MultiSelect.tsx
2138
- import { Fragment, jsx as jsx726, jsxs as jsxs4 } from "react/jsx-runtime";
2145
+ import { Fragment as Fragment2, jsx as jsx727, jsxs as jsxs4 } from "react/jsx-runtime";
2139
2146
  var EXTERNAL_MENU_MIN_WIDTH_DEFAULT = 540;
2140
2147
  var MultiSelect = forwardRef4(
2141
2148
  ({
@@ -2164,8 +2171,10 @@ var MultiSelect = forwardRef4(
2164
2171
  themeProductContext
2165
2172
  }, ref) => {
2166
2173
  const { theme } = useResolvedTheme4({ themeMode, themeProductContext });
2174
+ const modalId = useModalId();
2167
2175
  const controlRef = useRef4(null);
2168
2176
  const menuRef = useRef4(null);
2177
+ const [menuPosition, setMenuPosition] = useState3(null);
2169
2178
  const sizeStyles = theme.sizing.input(size);
2170
2179
  const state = externalState || (disabled ? "disable" : "default");
2171
2180
  const isDisable = state === "disable" || disabled;
@@ -2209,11 +2218,111 @@ var MultiSelect = forwardRef4(
2209
2218
  };
2210
2219
  const controlMenuOpen = dropdownMenu ? isOpen : Boolean(menuOpen);
2211
2220
  const controlOnClick = dropdownMenu ? onSelectClick : onTriggerPress;
2221
+ const updateMenuPosition = useCallback2(() => {
2222
+ if (!isWeb || !controlRef.current) return;
2223
+ const rect = controlRef.current.getBoundingClientRect();
2224
+ setMenuPosition({
2225
+ left: rect.left,
2226
+ top: rect.bottom + 4,
2227
+ width: rect.width
2228
+ });
2229
+ }, []);
2230
+ useEffect3(() => {
2231
+ if (!isWeb || !controlMenuOpen || isDisable || !dropdownMenu) return;
2232
+ updateMenuPosition();
2233
+ window.addEventListener("resize", updateMenuPosition);
2234
+ window.addEventListener("scroll", updateMenuPosition, true);
2235
+ return () => {
2236
+ window.removeEventListener("resize", updateMenuPosition);
2237
+ window.removeEventListener("scroll", updateMenuPosition, true);
2238
+ };
2239
+ }, [controlMenuOpen, dropdownMenu, isDisable, updateMenuPosition]);
2212
2240
  const externalFieldLayout = !dropdownMenu ? {
2213
2241
  width: "100%",
2214
2242
  minWidth: menuMinWidth ?? EXTERNAL_MENU_MIN_WIDTH_DEFAULT,
2215
2243
  boxSizing: "border-box"
2216
2244
  } : void 0;
2245
+ const dropdown = dropdownMenu && isOpen && !isDisable && (!isWeb || menuPosition) && /* @__PURE__ */ jsxs4(Fragment2, { children: [
2246
+ /* @__PURE__ */ jsx727(
2247
+ Box,
2248
+ {
2249
+ "data-modal-id": modalId,
2250
+ style: {
2251
+ position: "fixed",
2252
+ top: 0,
2253
+ left: 0,
2254
+ right: 0,
2255
+ bottom: 0,
2256
+ zIndex: 999,
2257
+ cursor: "default"
2258
+ },
2259
+ onPress: onClose
2260
+ }
2261
+ ),
2262
+ /* @__PURE__ */ jsx727(
2263
+ Box,
2264
+ {
2265
+ ref: menuRef,
2266
+ "data-modal-id": modalId,
2267
+ backgroundColor: theme.colors.background.secondary,
2268
+ borderColor: theme.colors.border.secondary,
2269
+ borderWidth: 1,
2270
+ borderRadius: sizeStyles.radius,
2271
+ paddingVertical: 4,
2272
+ style: {
2273
+ position: isWeb ? "fixed" : "absolute",
2274
+ top: isWeb ? menuPosition?.top : "100%",
2275
+ left: isWeb ? menuPosition?.left : 0,
2276
+ right: isWeb ? void 0 : 0,
2277
+ width: isWeb ? menuPosition?.width : void 0,
2278
+ marginTop: isWeb ? void 0 : 4,
2279
+ zIndex: 1001,
2280
+ // Above control (1000) and backdrop (999)
2281
+ boxShadow: theme.shadow.popover,
2282
+ maxHeight,
2283
+ overflowY: "auto"
2284
+ },
2285
+ children: menuItems.map((item, _index) => {
2286
+ const brandColors = theme.colors.control.brand.primary;
2287
+ const contentColors = theme.colors.content;
2288
+ return /* @__PURE__ */ jsx727(
2289
+ Box,
2290
+ {
2291
+ testID,
2292
+ paddingHorizontal: sizeStyles.paddingHorizontal,
2293
+ paddingVertical: 8,
2294
+ onPress: () => {
2295
+ if (!item.disabled) {
2296
+ handleItemToggle(item.id, !item.checked);
2297
+ }
2298
+ },
2299
+ flexDirection: "row",
2300
+ alignItems: "center",
2301
+ justifyContent: "space-between",
2302
+ backgroundColor: item.checked ? brandColors.bg : "transparent",
2303
+ hoverStyle: !item.disabled && !item.checked ? {
2304
+ backgroundColor: theme.colors.control.input.bgHover
2305
+ } : void 0,
2306
+ style: {
2307
+ cursor: item.disabled ? "not-allowed" : "pointer",
2308
+ opacity: item.disabled ? 0.5 : 1
2309
+ },
2310
+ children: /* @__PURE__ */ jsx727(
2311
+ Text,
2312
+ {
2313
+ color: item.checked ? contentColors.on.brand : theme.colors.content.secondary,
2314
+ fontSize: sizeStyles.fontSize,
2315
+ fontWeight: "400",
2316
+ children: item.children
2317
+ }
2318
+ )
2319
+ },
2320
+ item.id
2321
+ );
2322
+ })
2323
+ }
2324
+ )
2325
+ ] });
2217
2326
  return /* @__PURE__ */ jsxs4(
2218
2327
  Box,
2219
2328
  {
@@ -2222,7 +2331,7 @@ var MultiSelect = forwardRef4(
2222
2331
  gap: sizeStyles.fieldGap,
2223
2332
  style: externalFieldLayout,
2224
2333
  children: [
2225
- label && /* @__PURE__ */ jsx726(
2334
+ label && /* @__PURE__ */ jsx727(
2226
2335
  Text,
2227
2336
  {
2228
2337
  color: theme.colors.content.secondary,
@@ -2240,7 +2349,7 @@ var MultiSelect = forwardRef4(
2240
2349
  ...externalFieldLayout ? { width: "100%" } : {}
2241
2350
  },
2242
2351
  children: [
2243
- /* @__PURE__ */ jsx726(
2352
+ /* @__PURE__ */ jsx727(
2244
2353
  MultiSelectControl,
2245
2354
  {
2246
2355
  ref: controlRef,
@@ -2265,88 +2374,11 @@ var MultiSelect = forwardRef4(
2265
2374
  extraClear
2266
2375
  }
2267
2376
  ),
2268
- dropdownMenu && isOpen && !isDisable && /* @__PURE__ */ jsxs4(Fragment, { children: [
2269
- /* @__PURE__ */ jsx726(
2270
- Box,
2271
- {
2272
- style: {
2273
- position: "fixed",
2274
- top: 0,
2275
- left: 0,
2276
- right: 0,
2277
- bottom: 0,
2278
- zIndex: 999,
2279
- cursor: "default"
2280
- },
2281
- onPress: onClose
2282
- }
2283
- ),
2284
- /* @__PURE__ */ jsx726(
2285
- Box,
2286
- {
2287
- ref: menuRef,
2288
- backgroundColor: theme.colors.background.secondary,
2289
- borderColor: theme.colors.border.secondary,
2290
- borderWidth: 1,
2291
- borderRadius: theme.shape.input[size].borderRadius,
2292
- paddingVertical: 4,
2293
- style: {
2294
- position: "absolute",
2295
- top: "100%",
2296
- left: 0,
2297
- right: 0,
2298
- marginTop: 4,
2299
- zIndex: 1001,
2300
- // Above control (1000) and backdrop (999)
2301
- boxShadow: theme.shadow.popover,
2302
- maxHeight,
2303
- overflowY: "auto"
2304
- },
2305
- children: menuItems.map((item, _index) => {
2306
- const brandColors = theme.colors.control.brand.primary;
2307
- const contentColors = theme.colors.content;
2308
- return /* @__PURE__ */ jsx726(
2309
- Box,
2310
- {
2311
- testID,
2312
- paddingHorizontal: sizeStyles.paddingHorizontal,
2313
- paddingVertical: 8,
2314
- onPress: () => {
2315
- if (!item.disabled) {
2316
- handleItemToggle(item.id, !item.checked);
2317
- }
2318
- },
2319
- flexDirection: "row",
2320
- alignItems: "center",
2321
- justifyContent: "space-between",
2322
- backgroundColor: item.checked ? brandColors.bg : "transparent",
2323
- hoverStyle: !item.disabled && !item.checked ? {
2324
- backgroundColor: theme.colors.control.input.bgHover
2325
- } : void 0,
2326
- style: {
2327
- cursor: item.disabled ? "not-allowed" : "pointer",
2328
- opacity: item.disabled ? 0.5 : 1
2329
- },
2330
- children: /* @__PURE__ */ jsx726(
2331
- Text,
2332
- {
2333
- color: item.checked ? contentColors.on.brand : theme.colors.content.secondary,
2334
- fontSize: sizeStyles.fontSize,
2335
- fontWeight: "400",
2336
- children: item.children
2337
- }
2338
- )
2339
- },
2340
- item.id
2341
- );
2342
- })
2343
- }
2344
- )
2345
- ] })
2377
+ isWeb ? /* @__PURE__ */ jsx727(Portal, { children: dropdown }) : dropdown
2346
2378
  ]
2347
2379
  }
2348
2380
  ),
2349
- errorMessage && /* @__PURE__ */ jsx726(
2381
+ errorMessage && /* @__PURE__ */ jsx727(
2350
2382
  Text,
2351
2383
  {
2352
2384
  color: theme.colors.content.alert.primary,