@xsolla/xui-status-dropdown 0.170.2 → 0.170.4-pr334.1781156726

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.
@@ -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/native/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/native/index.js CHANGED
@@ -311,7 +311,7 @@ var isWeb = false;
311
311
 
312
312
  // src/StatusDropdown.tsx
313
313
  var import_xui_core = require("@xsolla/xui-core");
314
- var import_xui_dropdown = require("@xsolla/xui-dropdown");
314
+ var import_xui_context_menu = require("@xsolla/xui-context-menu");
315
315
 
316
316
  // ../../foundation/icons-base/dist/web/index.mjs
317
317
  var import_styled_components = __toESM(require("styled-components"), 1);
@@ -1085,44 +1085,48 @@ var ChevronDown = (props) => /* @__PURE__ */ (0, import_jsx_runtime130.jsx)(Base
1085
1085
 
1086
1086
  // src/StatusDropdown.tsx
1087
1087
  var import_jsx_runtime725 = require("react/jsx-runtime");
1088
+ var gapMap = {
1089
+ xl: 4,
1090
+ lg: 4,
1091
+ md: 2,
1092
+ sm: 2,
1093
+ xs: 2
1094
+ };
1095
+ var dotSizeMap = {
1096
+ xl: 8,
1097
+ lg: 8,
1098
+ md: 8,
1099
+ sm: 4,
1100
+ xs: 4
1101
+ };
1088
1102
  var getPaletteColors = (palette, theme) => {
1089
1103
  const colors = theme.colors;
1090
1104
  switch (palette) {
1091
1105
  case "Success":
1092
1106
  return {
1093
- background: colors.background.success.primary,
1094
- border: colors.border.success,
1095
- content: colors.content.on.success
1107
+ background: colors.background.success.secondary,
1108
+ border: colors.border.success
1096
1109
  };
1097
1110
  case "Warning":
1098
1111
  return {
1099
- background: colors.background.warning.primary,
1100
- border: colors.border.warning,
1101
- content: colors.content.on.warning
1112
+ background: colors.background.warning.secondary,
1113
+ border: colors.border.warning
1102
1114
  };
1103
1115
  case "Alert":
1104
1116
  return {
1105
- background: colors.background.alert.primary,
1106
- border: colors.border.alert,
1107
- content: colors.content.on.alert
1108
- };
1109
- case "Neutral":
1110
- return {
1111
- background: colors.background.neutral.primary,
1112
- border: colors.border.neutral,
1113
- content: colors.content.on.neutral
1117
+ background: colors.background.alert.secondary,
1118
+ border: colors.border.alert
1114
1119
  };
1115
1120
  case "Brand":
1116
1121
  return {
1117
- background: colors.background.brand.primary,
1118
- border: colors.border.brand,
1119
- content: colors.content.on.brand
1122
+ background: colors.background.brand.secondary,
1123
+ border: colors.border.brand
1120
1124
  };
1125
+ case "Neutral":
1121
1126
  default:
1122
1127
  return {
1123
- background: colors.background.neutral.primary,
1124
- border: colors.border.neutral,
1125
- content: colors.content.on.neutral
1128
+ background: colors.background.neutral.secondary,
1129
+ border: colors.border.neutral
1126
1130
  };
1127
1131
  }
1128
1132
  };
@@ -1130,9 +1134,9 @@ var StatusDropdown = (0, import_react2.forwardRef)(
1130
1134
  ({
1131
1135
  label,
1132
1136
  palette = "Neutral",
1137
+ size = "xs",
1133
1138
  dot = false,
1134
1139
  children,
1135
- onSelect,
1136
1140
  isOpen: propIsOpen,
1137
1141
  onOpenChange,
1138
1142
  "aria-label": ariaLabel,
@@ -1143,8 +1147,13 @@ var StatusDropdown = (0, import_react2.forwardRef)(
1143
1147
  }, ref) => {
1144
1148
  const { theme } = (0, import_xui_core.useResolvedTheme)({ themeMode, themeProductContext });
1145
1149
  const paletteColors = getPaletteColors(palette, theme);
1150
+ const contentColor = theme.colors.content.primary;
1151
+ const sizeStyles = theme.sizing.tag(size);
1152
+ const gap = gapMap[size];
1153
+ const dotSize = dotSizeMap[size];
1146
1154
  const [internalIsOpen, setInternalIsOpen] = (0, import_react2.useState)(false);
1147
1155
  const isOpen = propIsOpen !== void 0 ? propIsOpen : internalIsOpen;
1156
+ const [isFocusVisible, setIsFocusVisible] = (0, import_react2.useState)(false);
1148
1157
  const handleOpenChange = (open) => {
1149
1158
  if (onOpenChange) onOpenChange(open);
1150
1159
  if (propIsOpen === void 0) {
@@ -1154,26 +1163,64 @@ var StatusDropdown = (0, import_react2.forwardRef)(
1154
1163
  const trigger = /* @__PURE__ */ (0, import_jsx_runtime725.jsxs)(
1155
1164
  Box,
1156
1165
  {
1166
+ ref,
1167
+ id,
1157
1168
  role: "button",
1158
- "aria-haspopup": "listbox",
1169
+ tabIndex: 0,
1159
1170
  "aria-label": ariaLabel || `Status: ${label}`,
1160
1171
  testID: testID ? `${testID}-trigger` : void 0,
1172
+ onKeyDown: (event) => {
1173
+ if (event.key === "Enter" || event.key === " ") {
1174
+ event.preventDefault();
1175
+ handleOpenChange(!isOpen);
1176
+ } else if (event.key === "ArrowDown" && !isOpen) {
1177
+ event.preventDefault();
1178
+ handleOpenChange(true);
1179
+ }
1180
+ },
1181
+ position: "relative",
1161
1182
  flexDirection: "row",
1162
1183
  alignItems: "center",
1163
1184
  backgroundColor: paletteColors.background,
1164
1185
  borderColor: paletteColors.border,
1165
- borderWidth: 1,
1166
- borderRadius: 4,
1167
- height: 20,
1168
- paddingHorizontal: 3,
1169
- gap: 2,
1170
- style: isWeb ? { cursor: "pointer" } : void 0,
1186
+ borderWidth: sizeStyles.borderWidth,
1187
+ borderRadius: sizeStyles.radius,
1188
+ height: sizeStyles.height,
1189
+ paddingHorizontal: sizeStyles.padding,
1190
+ gap,
1191
+ ...isWeb ? {
1192
+ onFocus: (event) => {
1193
+ const target = event?.target;
1194
+ setIsFocusVisible(
1195
+ typeof target?.matches === "function" ? target.matches(":focus-visible") : true
1196
+ );
1197
+ },
1198
+ onBlur: () => setIsFocusVisible(false)
1199
+ } : {},
1200
+ style: isWeb ? {
1201
+ cursor: "pointer",
1202
+ outline: isFocusVisible ? `2px solid ${theme.colors.border.brand}` : "none",
1203
+ outlineOffset: isFocusVisible ? 2 : void 0
1204
+ } : void 0,
1171
1205
  children: [
1206
+ isWeb && /* @__PURE__ */ (0, import_jsx_runtime725.jsx)(
1207
+ Box,
1208
+ {
1209
+ "aria-hidden": true,
1210
+ position: "absolute",
1211
+ top: 0,
1212
+ left: 0,
1213
+ right: 0,
1214
+ bottom: 0,
1215
+ borderRadius: sizeStyles.radius,
1216
+ hoverStyle: { backgroundColor: theme.colors.overlay.mono }
1217
+ }
1218
+ ),
1172
1219
  dot && /* @__PURE__ */ (0, import_jsx_runtime725.jsx)(
1173
1220
  Box,
1174
1221
  {
1175
- width: 14,
1176
- height: 14,
1222
+ width: sizeStyles.iconSize,
1223
+ height: sizeStyles.iconSize,
1177
1224
  alignItems: "center",
1178
1225
  justifyContent: "center",
1179
1226
  flexShrink: 0,
@@ -1181,63 +1228,63 @@ var StatusDropdown = (0, import_react2.forwardRef)(
1181
1228
  Box,
1182
1229
  {
1183
1230
  testID: testID ? `${testID}-dot` : "status-dropdown-dot",
1184
- width: 4,
1185
- height: 4,
1231
+ width: dotSize,
1232
+ height: dotSize,
1186
1233
  borderRadius: 999,
1187
- backgroundColor: paletteColors.content
1234
+ backgroundColor: contentColor
1188
1235
  }
1189
1236
  )
1190
1237
  }
1191
1238
  ),
1192
- /* @__PURE__ */ (0, import_jsx_runtime725.jsx)(Box, { paddingHorizontal: 2, flexShrink: 0, children: /* @__PURE__ */ (0, import_jsx_runtime725.jsx)(
1239
+ /* @__PURE__ */ (0, import_jsx_runtime725.jsx)(Box, { paddingHorizontal: gap, flexShrink: 0, children: /* @__PURE__ */ (0, import_jsx_runtime725.jsx)(
1193
1240
  Text,
1194
1241
  {
1195
- color: paletteColors.content,
1196
- fontSize: 14,
1242
+ color: contentColor,
1243
+ fontSize: sizeStyles.fontSize,
1197
1244
  fontWeight: "500",
1198
1245
  numberOfLines: 1,
1199
1246
  style: {
1200
- lineHeight: "16px"
1247
+ lineHeight: `${sizeStyles.lineHeight}px`
1201
1248
  },
1202
1249
  children: label
1203
1250
  }
1204
1251
  ) }),
1205
- /* @__PURE__ */ (0, import_jsx_runtime725.jsx)(Box, { width: 14, height: 14, alignItems: "center", justifyContent: "center", children: /* @__PURE__ */ (0, import_jsx_runtime725.jsx)(
1206
- Icon,
1252
+ /* @__PURE__ */ (0, import_jsx_runtime725.jsx)(
1253
+ Box,
1207
1254
  {
1208
- size: 14,
1209
- color: paletteColors.content,
1210
- style: {
1211
- transform: isOpen ? "rotate(180deg)" : "rotate(0deg)",
1212
- ...isWeb ? { transition: "transform 0.2s ease-in-out" } : {}
1213
- },
1214
- children: /* @__PURE__ */ (0, import_jsx_runtime725.jsx)(ChevronDown, {})
1255
+ width: sizeStyles.iconSize,
1256
+ height: sizeStyles.iconSize,
1257
+ alignItems: "center",
1258
+ justifyContent: "center",
1259
+ children: /* @__PURE__ */ (0, import_jsx_runtime725.jsx)(
1260
+ Icon,
1261
+ {
1262
+ size: sizeStyles.iconSize,
1263
+ color: contentColor,
1264
+ style: {
1265
+ // Figma: chevron points up when closed, down when open
1266
+ transform: isOpen ? "rotate(0deg)" : "rotate(180deg)",
1267
+ ...isWeb ? { transition: "transform 0.2s ease-in-out" } : {}
1268
+ },
1269
+ children: /* @__PURE__ */ (0, import_jsx_runtime725.jsx)(ChevronDown, {})
1270
+ }
1271
+ )
1215
1272
  }
1216
- ) })
1273
+ )
1217
1274
  ]
1218
1275
  }
1219
1276
  );
1220
1277
  return /* @__PURE__ */ (0, import_jsx_runtime725.jsx)(
1221
- import_xui_dropdown.Dropdown,
1278
+ import_xui_context_menu.ContextMenu,
1222
1279
  {
1223
- ref,
1224
- id,
1225
1280
  trigger,
1226
1281
  isOpen,
1227
1282
  onOpenChange: handleOpenChange,
1283
+ "aria-label": "Change status",
1228
1284
  testID,
1229
1285
  themeMode,
1230
1286
  themeProductContext,
1231
- children: /* @__PURE__ */ (0, import_jsx_runtime725.jsx)(
1232
- Box,
1233
- {
1234
- onPress: (e) => {
1235
- if (onSelect) {
1236
- }
1237
- },
1238
- children
1239
- }
1240
- )
1287
+ children
1241
1288
  }
1242
1289
  );
1243
1290
  }