@xsolla/xui-status-dropdown 0.170.6 → 0.171.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xsolla/xui-status-dropdown",
3
- "version": "0.170.6",
3
+ "version": "0.171.0",
4
4
  "main": "./web/index.js",
5
5
  "module": "./web/index.mjs",
6
6
  "types": "./web/index.d.ts",
@@ -13,11 +13,10 @@
13
13
  "test:coverage": "vitest run --coverage"
14
14
  },
15
15
  "dependencies": {
16
- "@xsolla/xui-context-menu": "0.170.6",
17
- "@xsolla/xui-core": "0.170.6",
18
- "@xsolla/xui-dropdown": "0.170.6",
19
- "@xsolla/xui-primitives-core": "0.170.6",
20
- "@xsolla/xui-status": "0.170.6"
16
+ "@xsolla/xui-context-menu": "0.171.0",
17
+ "@xsolla/xui-core": "0.171.0",
18
+ "@xsolla/xui-primitives-core": "0.171.0",
19
+ "@xsolla/xui-status": "0.171.0"
21
20
  },
22
21
  "peerDependencies": {
23
22
  "react": ">=16.8.0",
package/web/index.d.mts CHANGED
@@ -2,17 +2,18 @@ import React, { ReactNode } from 'react';
2
2
  import { ThemeOverrideProps } from '@xsolla/xui-core';
3
3
 
4
4
  type StatusDropdownPalette = "Neutral" | "Success" | "Warning" | "Alert" | "Brand";
5
+ type StatusDropdownSize = "xl" | "lg" | "md" | "sm" | "xs";
5
6
  interface StatusDropdownProps extends ThemeOverrideProps {
6
7
  /** The current status label to display */
7
8
  label: string;
8
9
  /** Color palette for the status indicator */
9
10
  palette?: StatusDropdownPalette;
11
+ /** Size of the trigger */
12
+ size?: StatusDropdownSize;
10
13
  /** Whether to show the status dot */
11
14
  dot?: boolean;
12
15
  /** Dropdown menu content (usually ContextMenuItem components) */
13
16
  children: ReactNode;
14
- /** Callback when a menu item is selected. Value comes from child ContextMenuItem. */
15
- onSelect?: (value: any) => void;
16
17
  /** Whether the dropdown is open (controlled) */
17
18
  isOpen?: boolean;
18
19
  /** Callback when the open state changes */
@@ -32,4 +33,4 @@ interface StatusDropdownProps extends ThemeOverrideProps {
32
33
  */
33
34
  declare const StatusDropdown: React.ForwardRefExoticComponent<StatusDropdownProps & React.RefAttributes<any>>;
34
35
 
35
- export { StatusDropdown, type StatusDropdownPalette, type StatusDropdownProps };
36
+ export { StatusDropdown, type StatusDropdownPalette, type StatusDropdownProps, type StatusDropdownSize };
package/web/index.d.ts CHANGED
@@ -2,17 +2,18 @@ import React, { ReactNode } from 'react';
2
2
  import { ThemeOverrideProps } from '@xsolla/xui-core';
3
3
 
4
4
  type StatusDropdownPalette = "Neutral" | "Success" | "Warning" | "Alert" | "Brand";
5
+ type StatusDropdownSize = "xl" | "lg" | "md" | "sm" | "xs";
5
6
  interface StatusDropdownProps extends ThemeOverrideProps {
6
7
  /** The current status label to display */
7
8
  label: string;
8
9
  /** Color palette for the status indicator */
9
10
  palette?: StatusDropdownPalette;
11
+ /** Size of the trigger */
12
+ size?: StatusDropdownSize;
10
13
  /** Whether to show the status dot */
11
14
  dot?: boolean;
12
15
  /** Dropdown menu content (usually ContextMenuItem components) */
13
16
  children: ReactNode;
14
- /** Callback when a menu item is selected. Value comes from child ContextMenuItem. */
15
- onSelect?: (value: any) => void;
16
17
  /** Whether the dropdown is open (controlled) */
17
18
  isOpen?: boolean;
18
19
  /** Callback when the open state changes */
@@ -32,4 +33,4 @@ interface StatusDropdownProps extends ThemeOverrideProps {
32
33
  */
33
34
  declare const StatusDropdown: React.ForwardRefExoticComponent<StatusDropdownProps & React.RefAttributes<any>>;
34
35
 
35
- export { StatusDropdown, type StatusDropdownPalette, type StatusDropdownProps };
36
+ export { StatusDropdown, type StatusDropdownPalette, type StatusDropdownProps, type StatusDropdownSize };
package/web/index.js CHANGED
@@ -358,7 +358,7 @@ var isWeb = true;
358
358
 
359
359
  // src/StatusDropdown.tsx
360
360
  var import_xui_core = require("@xsolla/xui-core");
361
- var import_xui_dropdown = require("@xsolla/xui-dropdown");
361
+ var import_xui_context_menu = require("@xsolla/xui-context-menu");
362
362
 
363
363
  // ../../foundation/icons-base/dist/web/index.mjs
364
364
  var import_styled_components4 = __toESM(require("styled-components"), 1);
@@ -1132,44 +1132,48 @@ var ChevronDown = (props) => /* @__PURE__ */ (0, import_jsx_runtime130.jsx)(Base
1132
1132
 
1133
1133
  // src/StatusDropdown.tsx
1134
1134
  var import_jsx_runtime725 = require("react/jsx-runtime");
1135
+ var gapMap = {
1136
+ xl: 4,
1137
+ lg: 4,
1138
+ md: 2,
1139
+ sm: 2,
1140
+ xs: 2
1141
+ };
1142
+ var dotSizeMap = {
1143
+ xl: 8,
1144
+ lg: 8,
1145
+ md: 8,
1146
+ sm: 4,
1147
+ xs: 4
1148
+ };
1135
1149
  var getPaletteColors = (palette, theme) => {
1136
1150
  const colors = theme.colors;
1137
1151
  switch (palette) {
1138
1152
  case "Success":
1139
1153
  return {
1140
- background: colors.background.success.primary,
1141
- border: colors.border.success,
1142
- content: colors.content.on.success
1154
+ background: colors.background.success.secondary,
1155
+ border: colors.border.success
1143
1156
  };
1144
1157
  case "Warning":
1145
1158
  return {
1146
- background: colors.background.warning.primary,
1147
- border: colors.border.warning,
1148
- content: colors.content.on.warning
1159
+ background: colors.background.warning.secondary,
1160
+ border: colors.border.warning
1149
1161
  };
1150
1162
  case "Alert":
1151
1163
  return {
1152
- background: colors.background.alert.primary,
1153
- border: colors.border.alert,
1154
- content: colors.content.on.alert
1155
- };
1156
- case "Neutral":
1157
- return {
1158
- background: colors.background.neutral.primary,
1159
- border: colors.border.neutral,
1160
- content: colors.content.on.neutral
1164
+ background: colors.background.alert.secondary,
1165
+ border: colors.border.alert
1161
1166
  };
1162
1167
  case "Brand":
1163
1168
  return {
1164
- background: colors.background.brand.primary,
1165
- border: colors.border.brand,
1166
- content: colors.content.on.brand
1169
+ background: colors.background.brand.secondary,
1170
+ border: colors.border.brand
1167
1171
  };
1172
+ case "Neutral":
1168
1173
  default:
1169
1174
  return {
1170
- background: colors.background.neutral.primary,
1171
- border: colors.border.neutral,
1172
- content: colors.content.on.neutral
1175
+ background: colors.background.neutral.secondary,
1176
+ border: colors.border.neutral
1173
1177
  };
1174
1178
  }
1175
1179
  };
@@ -1177,9 +1181,9 @@ var StatusDropdown = (0, import_react3.forwardRef)(
1177
1181
  ({
1178
1182
  label,
1179
1183
  palette = "Neutral",
1184
+ size = "xs",
1180
1185
  dot = false,
1181
1186
  children,
1182
- onSelect,
1183
1187
  isOpen: propIsOpen,
1184
1188
  onOpenChange,
1185
1189
  "aria-label": ariaLabel,
@@ -1190,8 +1194,13 @@ var StatusDropdown = (0, import_react3.forwardRef)(
1190
1194
  }, ref) => {
1191
1195
  const { theme } = (0, import_xui_core.useResolvedTheme)({ themeMode, themeProductContext });
1192
1196
  const paletteColors = getPaletteColors(palette, theme);
1197
+ const contentColor = theme.colors.content.primary;
1198
+ const sizeStyles = theme.sizing.tag(size);
1199
+ const gap = gapMap[size];
1200
+ const dotSize = dotSizeMap[size];
1193
1201
  const [internalIsOpen, setInternalIsOpen] = (0, import_react3.useState)(false);
1194
1202
  const isOpen = propIsOpen !== void 0 ? propIsOpen : internalIsOpen;
1203
+ const [isFocusVisible, setIsFocusVisible] = (0, import_react3.useState)(false);
1195
1204
  const handleOpenChange = (open) => {
1196
1205
  if (onOpenChange) onOpenChange(open);
1197
1206
  if (propIsOpen === void 0) {
@@ -1201,26 +1210,64 @@ var StatusDropdown = (0, import_react3.forwardRef)(
1201
1210
  const trigger = /* @__PURE__ */ (0, import_jsx_runtime725.jsxs)(
1202
1211
  Box,
1203
1212
  {
1213
+ ref,
1214
+ id,
1204
1215
  role: "button",
1205
- "aria-haspopup": "listbox",
1216
+ tabIndex: 0,
1206
1217
  "aria-label": ariaLabel || `Status: ${label}`,
1207
1218
  testID: testID ? `${testID}-trigger` : void 0,
1219
+ onKeyDown: (event) => {
1220
+ if (event.key === "Enter" || event.key === " ") {
1221
+ event.preventDefault();
1222
+ handleOpenChange(!isOpen);
1223
+ } else if (event.key === "ArrowDown" && !isOpen) {
1224
+ event.preventDefault();
1225
+ handleOpenChange(true);
1226
+ }
1227
+ },
1228
+ position: "relative",
1208
1229
  flexDirection: "row",
1209
1230
  alignItems: "center",
1210
1231
  backgroundColor: paletteColors.background,
1211
1232
  borderColor: paletteColors.border,
1212
- borderWidth: 1,
1213
- borderRadius: 4,
1214
- height: 20,
1215
- paddingHorizontal: 3,
1216
- gap: 2,
1217
- style: isWeb ? { cursor: "pointer" } : void 0,
1233
+ borderWidth: sizeStyles.borderWidth,
1234
+ borderRadius: sizeStyles.radius,
1235
+ height: sizeStyles.height,
1236
+ paddingHorizontal: sizeStyles.padding,
1237
+ gap,
1238
+ ...isWeb ? {
1239
+ onFocus: (event) => {
1240
+ const target = event?.target;
1241
+ setIsFocusVisible(
1242
+ typeof target?.matches === "function" ? target.matches(":focus-visible") : true
1243
+ );
1244
+ },
1245
+ onBlur: () => setIsFocusVisible(false)
1246
+ } : {},
1247
+ style: isWeb ? {
1248
+ cursor: "pointer",
1249
+ outline: isFocusVisible ? `2px solid ${theme.colors.border.brand}` : "none",
1250
+ outlineOffset: isFocusVisible ? 2 : void 0
1251
+ } : void 0,
1218
1252
  children: [
1253
+ isWeb && /* @__PURE__ */ (0, import_jsx_runtime725.jsx)(
1254
+ Box,
1255
+ {
1256
+ "aria-hidden": true,
1257
+ position: "absolute",
1258
+ top: 0,
1259
+ left: 0,
1260
+ right: 0,
1261
+ bottom: 0,
1262
+ borderRadius: sizeStyles.radius,
1263
+ hoverStyle: { backgroundColor: theme.colors.overlay.mono }
1264
+ }
1265
+ ),
1219
1266
  dot && /* @__PURE__ */ (0, import_jsx_runtime725.jsx)(
1220
1267
  Box,
1221
1268
  {
1222
- width: 14,
1223
- height: 14,
1269
+ width: sizeStyles.iconSize,
1270
+ height: sizeStyles.iconSize,
1224
1271
  alignItems: "center",
1225
1272
  justifyContent: "center",
1226
1273
  flexShrink: 0,
@@ -1228,63 +1275,62 @@ var StatusDropdown = (0, import_react3.forwardRef)(
1228
1275
  Box,
1229
1276
  {
1230
1277
  testID: testID ? `${testID}-dot` : "status-dropdown-dot",
1231
- width: 4,
1232
- height: 4,
1278
+ width: dotSize,
1279
+ height: dotSize,
1233
1280
  borderRadius: 999,
1234
- backgroundColor: paletteColors.content
1281
+ backgroundColor: contentColor
1235
1282
  }
1236
1283
  )
1237
1284
  }
1238
1285
  ),
1239
- /* @__PURE__ */ (0, import_jsx_runtime725.jsx)(Box, { paddingHorizontal: 2, flexShrink: 0, children: /* @__PURE__ */ (0, import_jsx_runtime725.jsx)(
1286
+ /* @__PURE__ */ (0, import_jsx_runtime725.jsx)(Box, { paddingHorizontal: gap, flexShrink: 0, children: /* @__PURE__ */ (0, import_jsx_runtime725.jsx)(
1240
1287
  Text,
1241
1288
  {
1242
- color: paletteColors.content,
1243
- fontSize: 14,
1289
+ color: contentColor,
1290
+ fontSize: sizeStyles.fontSize,
1244
1291
  fontWeight: "500",
1245
1292
  numberOfLines: 1,
1246
1293
  style: {
1247
- lineHeight: "16px"
1294
+ lineHeight: `${sizeStyles.lineHeight}px`
1248
1295
  },
1249
1296
  children: label
1250
1297
  }
1251
1298
  ) }),
1252
- /* @__PURE__ */ (0, import_jsx_runtime725.jsx)(Box, { width: 14, height: 14, alignItems: "center", justifyContent: "center", children: /* @__PURE__ */ (0, import_jsx_runtime725.jsx)(
1253
- Icon,
1299
+ /* @__PURE__ */ (0, import_jsx_runtime725.jsx)(
1300
+ Box,
1254
1301
  {
1255
- size: 14,
1256
- color: paletteColors.content,
1257
- style: {
1258
- transform: isOpen ? "rotate(180deg)" : "rotate(0deg)",
1259
- ...isWeb ? { transition: "transform 0.2s ease-in-out" } : {}
1260
- },
1261
- children: /* @__PURE__ */ (0, import_jsx_runtime725.jsx)(ChevronDown, {})
1302
+ width: sizeStyles.iconSize,
1303
+ height: sizeStyles.iconSize,
1304
+ alignItems: "center",
1305
+ justifyContent: "center",
1306
+ children: /* @__PURE__ */ (0, import_jsx_runtime725.jsx)(
1307
+ Icon,
1308
+ {
1309
+ size: sizeStyles.iconSize,
1310
+ color: contentColor,
1311
+ style: {
1312
+ transform: isOpen ? "rotate(180deg)" : "rotate(0deg)",
1313
+ ...isWeb ? { transition: "transform 0.2s ease-in-out" } : {}
1314
+ },
1315
+ children: /* @__PURE__ */ (0, import_jsx_runtime725.jsx)(ChevronDown, {})
1316
+ }
1317
+ )
1262
1318
  }
1263
- ) })
1319
+ )
1264
1320
  ]
1265
1321
  }
1266
1322
  );
1267
1323
  return /* @__PURE__ */ (0, import_jsx_runtime725.jsx)(
1268
- import_xui_dropdown.Dropdown,
1324
+ import_xui_context_menu.ContextMenu,
1269
1325
  {
1270
- ref,
1271
- id,
1272
1326
  trigger,
1273
1327
  isOpen,
1274
1328
  onOpenChange: handleOpenChange,
1329
+ "aria-label": "Change status",
1275
1330
  testID,
1276
1331
  themeMode,
1277
1332
  themeProductContext,
1278
- children: /* @__PURE__ */ (0, import_jsx_runtime725.jsx)(
1279
- Box,
1280
- {
1281
- onPress: (e) => {
1282
- if (onSelect) {
1283
- }
1284
- },
1285
- children
1286
- }
1287
- )
1333
+ children
1288
1334
  }
1289
1335
  );
1290
1336
  }