@xsolla/xui-button 0.111.0 → 0.112.0-pr178.1773103324
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.d.mts +53 -1
- package/native/index.d.ts +53 -1
- package/native/index.js +266 -15
- package/native/index.js.flow +121 -2
- package/native/index.js.map +1 -1
- package/native/index.mjs +271 -18
- package/native/index.mjs.map +1 -1
- package/package.json +4 -4
- package/web/index.d.mts +53 -1
- package/web/index.d.ts +53 -1
- package/web/index.js +236 -12
- package/web/index.js.flow +121 -2
- package/web/index.js.map +1 -1
- package/web/index.mjs +237 -14
- package/web/index.mjs.map +1 -1
package/native/index.d.mts
CHANGED
|
@@ -207,6 +207,58 @@ interface FlexButtonProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElem
|
|
|
207
207
|
*/
|
|
208
208
|
declare const FlexButton: React.FC<FlexButtonProps>;
|
|
209
209
|
|
|
210
|
+
interface AppButtonProps {
|
|
211
|
+
/** Size of the button */
|
|
212
|
+
size?: "xl" | "lg" | "md" | "sm" | "xs";
|
|
213
|
+
/** Whether the button is disabled */
|
|
214
|
+
disabled?: boolean;
|
|
215
|
+
/** Whether the button is in a loading state */
|
|
216
|
+
loading?: boolean;
|
|
217
|
+
/** Button content */
|
|
218
|
+
children: React.ReactNode;
|
|
219
|
+
/** Click handler */
|
|
220
|
+
onPress?: () => void;
|
|
221
|
+
/** Icon to display on the left side */
|
|
222
|
+
iconLeft?: React.ReactNode;
|
|
223
|
+
/** Icon to display on the right side */
|
|
224
|
+
iconRight?: React.ReactNode;
|
|
225
|
+
/** Secondary text displayed inline with the main label */
|
|
226
|
+
sublabel?: string;
|
|
227
|
+
/** Alignment of the label text */
|
|
228
|
+
labelAlignment?: "left" | "center";
|
|
229
|
+
/** Small icon displayed directly next to the label text */
|
|
230
|
+
labelIcon?: React.ReactNode;
|
|
231
|
+
/** Custom content slot for badges, tags, or other elements */
|
|
232
|
+
customContent?: React.ReactNode;
|
|
233
|
+
/** Accessible label for screen readers */
|
|
234
|
+
"aria-label"?: string;
|
|
235
|
+
/** ID of element that describes this button */
|
|
236
|
+
"aria-describedby"?: string;
|
|
237
|
+
/** Indicates the button controls an expandable element */
|
|
238
|
+
"aria-expanded"?: boolean;
|
|
239
|
+
/** Indicates the type of popup triggered by the button */
|
|
240
|
+
"aria-haspopup"?: boolean | "menu" | "listbox" | "tree" | "grid" | "dialog";
|
|
241
|
+
/** Indicates the button is pressed (for toggle buttons) */
|
|
242
|
+
"aria-pressed"?: boolean | "mixed";
|
|
243
|
+
/** ID of the element this button controls */
|
|
244
|
+
"aria-controls"?: string;
|
|
245
|
+
/** Test ID for testing frameworks */
|
|
246
|
+
testID?: string;
|
|
247
|
+
/** HTML id attribute */
|
|
248
|
+
id?: string;
|
|
249
|
+
/** HTML type attribute for the button */
|
|
250
|
+
type?: "button" | "submit" | "reset";
|
|
251
|
+
/** Whether the button should stretch to fill the full width of its container */
|
|
252
|
+
fullWidth?: boolean;
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* AppButton - A prominent filled button for app-level actions.
|
|
256
|
+
*
|
|
257
|
+
* Uses the `control.appButton` theme tokens for styling.
|
|
258
|
+
* Supports all the same layout features as Button (icons, sublabels, etc.).
|
|
259
|
+
*/
|
|
260
|
+
declare const AppButton: React.FC<AppButtonProps>;
|
|
261
|
+
|
|
210
262
|
interface ButtonGroupProps {
|
|
211
263
|
/**
|
|
212
264
|
* Layout orientation of the buttons
|
|
@@ -270,4 +322,4 @@ interface ButtonGroupProps {
|
|
|
270
322
|
*/
|
|
271
323
|
declare const ButtonGroup: React.FC<ButtonGroupProps>;
|
|
272
324
|
|
|
273
|
-
export { Button, ButtonGroup, type ButtonGroupProps, type ButtonProps, FlexButton, type FlexButtonProps, IconButton, type IconButtonProps };
|
|
325
|
+
export { AppButton, type AppButtonProps, Button, ButtonGroup, type ButtonGroupProps, type ButtonProps, FlexButton, type FlexButtonProps, IconButton, type IconButtonProps };
|
package/native/index.d.ts
CHANGED
|
@@ -207,6 +207,58 @@ interface FlexButtonProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElem
|
|
|
207
207
|
*/
|
|
208
208
|
declare const FlexButton: React.FC<FlexButtonProps>;
|
|
209
209
|
|
|
210
|
+
interface AppButtonProps {
|
|
211
|
+
/** Size of the button */
|
|
212
|
+
size?: "xl" | "lg" | "md" | "sm" | "xs";
|
|
213
|
+
/** Whether the button is disabled */
|
|
214
|
+
disabled?: boolean;
|
|
215
|
+
/** Whether the button is in a loading state */
|
|
216
|
+
loading?: boolean;
|
|
217
|
+
/** Button content */
|
|
218
|
+
children: React.ReactNode;
|
|
219
|
+
/** Click handler */
|
|
220
|
+
onPress?: () => void;
|
|
221
|
+
/** Icon to display on the left side */
|
|
222
|
+
iconLeft?: React.ReactNode;
|
|
223
|
+
/** Icon to display on the right side */
|
|
224
|
+
iconRight?: React.ReactNode;
|
|
225
|
+
/** Secondary text displayed inline with the main label */
|
|
226
|
+
sublabel?: string;
|
|
227
|
+
/** Alignment of the label text */
|
|
228
|
+
labelAlignment?: "left" | "center";
|
|
229
|
+
/** Small icon displayed directly next to the label text */
|
|
230
|
+
labelIcon?: React.ReactNode;
|
|
231
|
+
/** Custom content slot for badges, tags, or other elements */
|
|
232
|
+
customContent?: React.ReactNode;
|
|
233
|
+
/** Accessible label for screen readers */
|
|
234
|
+
"aria-label"?: string;
|
|
235
|
+
/** ID of element that describes this button */
|
|
236
|
+
"aria-describedby"?: string;
|
|
237
|
+
/** Indicates the button controls an expandable element */
|
|
238
|
+
"aria-expanded"?: boolean;
|
|
239
|
+
/** Indicates the type of popup triggered by the button */
|
|
240
|
+
"aria-haspopup"?: boolean | "menu" | "listbox" | "tree" | "grid" | "dialog";
|
|
241
|
+
/** Indicates the button is pressed (for toggle buttons) */
|
|
242
|
+
"aria-pressed"?: boolean | "mixed";
|
|
243
|
+
/** ID of the element this button controls */
|
|
244
|
+
"aria-controls"?: string;
|
|
245
|
+
/** Test ID for testing frameworks */
|
|
246
|
+
testID?: string;
|
|
247
|
+
/** HTML id attribute */
|
|
248
|
+
id?: string;
|
|
249
|
+
/** HTML type attribute for the button */
|
|
250
|
+
type?: "button" | "submit" | "reset";
|
|
251
|
+
/** Whether the button should stretch to fill the full width of its container */
|
|
252
|
+
fullWidth?: boolean;
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* AppButton - A prominent filled button for app-level actions.
|
|
256
|
+
*
|
|
257
|
+
* Uses the `control.appButton` theme tokens for styling.
|
|
258
|
+
* Supports all the same layout features as Button (icons, sublabels, etc.).
|
|
259
|
+
*/
|
|
260
|
+
declare const AppButton: React.FC<AppButtonProps>;
|
|
261
|
+
|
|
210
262
|
interface ButtonGroupProps {
|
|
211
263
|
/**
|
|
212
264
|
* Layout orientation of the buttons
|
|
@@ -270,4 +322,4 @@ interface ButtonGroupProps {
|
|
|
270
322
|
*/
|
|
271
323
|
declare const ButtonGroup: React.FC<ButtonGroupProps>;
|
|
272
324
|
|
|
273
|
-
export { Button, ButtonGroup, type ButtonGroupProps, type ButtonProps, FlexButton, type FlexButtonProps, IconButton, type IconButtonProps };
|
|
325
|
+
export { AppButton, type AppButtonProps, Button, ButtonGroup, type ButtonGroupProps, type ButtonProps, FlexButton, type FlexButtonProps, IconButton, type IconButtonProps };
|
package/native/index.js
CHANGED
|
@@ -30,6 +30,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/index.tsx
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
|
+
AppButton: () => AppButton,
|
|
33
34
|
Button: () => Button,
|
|
34
35
|
ButtonGroup: () => ButtonGroup,
|
|
35
36
|
FlexButton: () => FlexButton,
|
|
@@ -216,29 +217,57 @@ var roleMap = {
|
|
|
216
217
|
link: "link",
|
|
217
218
|
text: "text"
|
|
218
219
|
};
|
|
220
|
+
var parseNumericValue = (value) => {
|
|
221
|
+
if (value === void 0) return void 0;
|
|
222
|
+
if (typeof value === "number") return value;
|
|
223
|
+
const parsed = parseFloat(value);
|
|
224
|
+
return isNaN(parsed) ? void 0 : parsed;
|
|
225
|
+
};
|
|
219
226
|
var Text = ({
|
|
220
227
|
children,
|
|
221
228
|
color,
|
|
222
229
|
fontSize,
|
|
223
230
|
fontWeight,
|
|
224
231
|
fontFamily,
|
|
232
|
+
textAlign,
|
|
233
|
+
lineHeight,
|
|
234
|
+
numberOfLines,
|
|
225
235
|
id,
|
|
226
236
|
role,
|
|
237
|
+
style: styleProp,
|
|
227
238
|
...props
|
|
228
239
|
}) => {
|
|
229
240
|
let resolvedFontFamily = fontFamily ? fontFamily.split(",")[0].replace(/['"]/g, "").trim() : void 0;
|
|
230
241
|
if (resolvedFontFamily === "Pilat Wide" || resolvedFontFamily === "Pilat Wide Bold" || resolvedFontFamily === "Aktiv Grotesk") {
|
|
231
242
|
resolvedFontFamily = void 0;
|
|
232
243
|
}
|
|
233
|
-
const
|
|
244
|
+
const incomingStyle = import_react_native2.StyleSheet.flatten(styleProp);
|
|
245
|
+
const baseStyle = {
|
|
234
246
|
color,
|
|
235
247
|
fontSize: typeof fontSize === "number" ? fontSize : void 0,
|
|
236
248
|
fontWeight,
|
|
237
249
|
fontFamily: resolvedFontFamily,
|
|
238
|
-
textDecorationLine: props.textDecoration
|
|
250
|
+
textDecorationLine: props.textDecoration,
|
|
251
|
+
textAlign: textAlign ?? incomingStyle?.textAlign,
|
|
252
|
+
lineHeight: parseNumericValue(lineHeight ?? incomingStyle?.lineHeight),
|
|
253
|
+
marginTop: parseNumericValue(
|
|
254
|
+
incomingStyle?.marginTop
|
|
255
|
+
),
|
|
256
|
+
marginBottom: parseNumericValue(
|
|
257
|
+
incomingStyle?.marginBottom
|
|
258
|
+
)
|
|
239
259
|
};
|
|
240
260
|
const accessibilityRole = role ? roleMap[role] : void 0;
|
|
241
|
-
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
261
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
262
|
+
import_react_native2.Text,
|
|
263
|
+
{
|
|
264
|
+
style: baseStyle,
|
|
265
|
+
numberOfLines,
|
|
266
|
+
testID: id,
|
|
267
|
+
accessibilityRole,
|
|
268
|
+
children
|
|
269
|
+
}
|
|
270
|
+
);
|
|
242
271
|
};
|
|
243
272
|
|
|
244
273
|
// ../primitives-native/src/Spinner.tsx
|
|
@@ -1029,10 +1058,231 @@ var FlexButton = ({
|
|
|
1029
1058
|
};
|
|
1030
1059
|
FlexButton.displayName = "FlexButton";
|
|
1031
1060
|
|
|
1032
|
-
// src/
|
|
1061
|
+
// src/AppButton.tsx
|
|
1033
1062
|
var import_react5 = __toESM(require("react"));
|
|
1034
1063
|
var import_xui_core4 = require("@xsolla/xui-core");
|
|
1035
1064
|
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
1065
|
+
var cloneIconWithDefaults3 = (icon, defaultSize, defaultColor) => {
|
|
1066
|
+
if (!import_react5.default.isValidElement(icon)) return icon;
|
|
1067
|
+
const iconElement = icon;
|
|
1068
|
+
const existingProps = iconElement.props || {};
|
|
1069
|
+
return import_react5.default.cloneElement(iconElement, {
|
|
1070
|
+
...existingProps,
|
|
1071
|
+
size: existingProps.size ?? defaultSize,
|
|
1072
|
+
color: existingProps.color ?? defaultColor
|
|
1073
|
+
});
|
|
1074
|
+
};
|
|
1075
|
+
var AppButton = ({
|
|
1076
|
+
size = "md",
|
|
1077
|
+
disabled = false,
|
|
1078
|
+
loading = false,
|
|
1079
|
+
children,
|
|
1080
|
+
onPress,
|
|
1081
|
+
iconLeft,
|
|
1082
|
+
iconRight,
|
|
1083
|
+
sublabel,
|
|
1084
|
+
labelAlignment = "center",
|
|
1085
|
+
labelIcon,
|
|
1086
|
+
customContent,
|
|
1087
|
+
"aria-label": ariaLabel,
|
|
1088
|
+
"aria-describedby": ariaDescribedBy,
|
|
1089
|
+
"aria-expanded": ariaExpanded,
|
|
1090
|
+
"aria-haspopup": ariaHasPopup,
|
|
1091
|
+
"aria-pressed": ariaPressed,
|
|
1092
|
+
"aria-controls": ariaControls,
|
|
1093
|
+
testID,
|
|
1094
|
+
id,
|
|
1095
|
+
type = "button",
|
|
1096
|
+
fullWidth = false
|
|
1097
|
+
}) => {
|
|
1098
|
+
const { theme } = (0, import_xui_core4.useDesignSystem)();
|
|
1099
|
+
const [isKeyboardPressed, setIsKeyboardPressed] = (0, import_react5.useState)(false);
|
|
1100
|
+
const isDisabled = disabled || loading;
|
|
1101
|
+
const sizeStyles = theme.sizing.button(size);
|
|
1102
|
+
const tokens = theme?.colors?.control?.appButton || {
|
|
1103
|
+
bg: "#34474b",
|
|
1104
|
+
bgHover: "#3d5256",
|
|
1105
|
+
bgPress: "#2b3b3e",
|
|
1106
|
+
border: "rgba(255, 255, 255, 0.12)",
|
|
1107
|
+
borderHover: "rgba(255, 255, 255, 0.18)",
|
|
1108
|
+
borderPress: "rgba(255, 255, 255, 0.12)",
|
|
1109
|
+
text: "#b7c5c8",
|
|
1110
|
+
textDisable: "#b3b3b3"
|
|
1111
|
+
};
|
|
1112
|
+
const handlePress = () => {
|
|
1113
|
+
if (!isDisabled && onPress) {
|
|
1114
|
+
onPress();
|
|
1115
|
+
}
|
|
1116
|
+
};
|
|
1117
|
+
const handleKeyDown = (e) => {
|
|
1118
|
+
if (isDisabled) return;
|
|
1119
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
1120
|
+
e.preventDefault();
|
|
1121
|
+
setIsKeyboardPressed(true);
|
|
1122
|
+
}
|
|
1123
|
+
};
|
|
1124
|
+
const handleKeyUp = (e) => {
|
|
1125
|
+
if (isDisabled) return;
|
|
1126
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
1127
|
+
e.preventDefault();
|
|
1128
|
+
setIsKeyboardPressed(false);
|
|
1129
|
+
if (onPress) {
|
|
1130
|
+
onPress();
|
|
1131
|
+
}
|
|
1132
|
+
}
|
|
1133
|
+
};
|
|
1134
|
+
let backgroundColor = tokens.bg;
|
|
1135
|
+
if (disabled) {
|
|
1136
|
+
backgroundColor = tokens.bg;
|
|
1137
|
+
} else if (isKeyboardPressed) {
|
|
1138
|
+
backgroundColor = tokens.bgPress;
|
|
1139
|
+
}
|
|
1140
|
+
const borderColor = tokens.border;
|
|
1141
|
+
const textColor = disabled ? tokens.textDisable : tokens.text;
|
|
1142
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
1143
|
+
Box,
|
|
1144
|
+
{
|
|
1145
|
+
as: "button",
|
|
1146
|
+
type,
|
|
1147
|
+
id,
|
|
1148
|
+
onPress: handlePress,
|
|
1149
|
+
onKeyDown: handleKeyDown,
|
|
1150
|
+
onKeyUp: handleKeyUp,
|
|
1151
|
+
disabled: isDisabled,
|
|
1152
|
+
"aria-label": ariaLabel,
|
|
1153
|
+
"aria-disabled": isDisabled || void 0,
|
|
1154
|
+
"aria-busy": loading || void 0,
|
|
1155
|
+
"aria-describedby": ariaDescribedBy,
|
|
1156
|
+
"aria-expanded": ariaExpanded,
|
|
1157
|
+
"aria-haspopup": ariaHasPopup,
|
|
1158
|
+
"aria-pressed": ariaPressed,
|
|
1159
|
+
"aria-controls": ariaControls,
|
|
1160
|
+
testID,
|
|
1161
|
+
backgroundColor,
|
|
1162
|
+
borderColor,
|
|
1163
|
+
borderWidth: borderColor !== "transparent" && borderColor !== "rgba(255, 255, 255, 0)" && borderColor !== "rgba(0, 0, 0, 0)" && !borderColor.endsWith(", 0)") ? 1 : 0,
|
|
1164
|
+
borderRadius: sizeStyles.borderRadius,
|
|
1165
|
+
height: sizeStyles.height,
|
|
1166
|
+
width: fullWidth ? "100%" : void 0,
|
|
1167
|
+
padding: 0,
|
|
1168
|
+
flexDirection: "row",
|
|
1169
|
+
alignItems: "center",
|
|
1170
|
+
justifyContent: "center",
|
|
1171
|
+
position: "relative",
|
|
1172
|
+
cursor: disabled ? "not-allowed" : loading ? "wait" : "pointer",
|
|
1173
|
+
opacity: disabled ? 0.6 : 1,
|
|
1174
|
+
hoverStyle: !isDisabled ? {
|
|
1175
|
+
backgroundColor: tokens.bgHover,
|
|
1176
|
+
borderColor: tokens.borderHover
|
|
1177
|
+
} : void 0,
|
|
1178
|
+
pressStyle: !isDisabled ? {
|
|
1179
|
+
backgroundColor: tokens.bgPress,
|
|
1180
|
+
borderColor: tokens.borderPress
|
|
1181
|
+
} : void 0,
|
|
1182
|
+
focusStyle: {
|
|
1183
|
+
outlineColor: theme.colors.border.brand,
|
|
1184
|
+
outlineWidth: 2,
|
|
1185
|
+
outlineOffset: 2,
|
|
1186
|
+
outlineStyle: "solid"
|
|
1187
|
+
},
|
|
1188
|
+
children: [
|
|
1189
|
+
loading && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1190
|
+
Box,
|
|
1191
|
+
{
|
|
1192
|
+
position: "absolute",
|
|
1193
|
+
top: 0,
|
|
1194
|
+
left: 0,
|
|
1195
|
+
right: 0,
|
|
1196
|
+
bottom: 0,
|
|
1197
|
+
alignItems: "center",
|
|
1198
|
+
justifyContent: "center",
|
|
1199
|
+
zIndex: 1,
|
|
1200
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1201
|
+
Spinner,
|
|
1202
|
+
{
|
|
1203
|
+
color: textColor,
|
|
1204
|
+
size: sizeStyles.spinnerSize,
|
|
1205
|
+
"aria-hidden": true
|
|
1206
|
+
}
|
|
1207
|
+
)
|
|
1208
|
+
}
|
|
1209
|
+
),
|
|
1210
|
+
iconLeft && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1211
|
+
Box,
|
|
1212
|
+
{
|
|
1213
|
+
width: sizeStyles.iconContainerSize,
|
|
1214
|
+
height: sizeStyles.iconContainerSize,
|
|
1215
|
+
alignItems: "center",
|
|
1216
|
+
justifyContent: "center",
|
|
1217
|
+
"aria-hidden": true,
|
|
1218
|
+
style: {
|
|
1219
|
+
opacity: loading ? 0 : 1,
|
|
1220
|
+
pointerEvents: loading ? "none" : "auto"
|
|
1221
|
+
},
|
|
1222
|
+
children: cloneIconWithDefaults3(iconLeft, sizeStyles.iconSize, textColor)
|
|
1223
|
+
}
|
|
1224
|
+
),
|
|
1225
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
1226
|
+
Box,
|
|
1227
|
+
{
|
|
1228
|
+
flex: fullWidth ? 1 : void 0,
|
|
1229
|
+
flexDirection: "row",
|
|
1230
|
+
alignItems: "center",
|
|
1231
|
+
justifyContent: labelAlignment === "left" ? "flex-start" : "center",
|
|
1232
|
+
paddingHorizontal: sizeStyles.padding,
|
|
1233
|
+
height: "100%",
|
|
1234
|
+
gap: sizeStyles.labelIconGap,
|
|
1235
|
+
style: {
|
|
1236
|
+
opacity: loading ? 0 : 1,
|
|
1237
|
+
pointerEvents: loading ? "none" : "auto"
|
|
1238
|
+
},
|
|
1239
|
+
"aria-hidden": loading ? true : void 0,
|
|
1240
|
+
children: [
|
|
1241
|
+
labelIcon && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Box, { "aria-hidden": true, children: cloneIconWithDefaults3(
|
|
1242
|
+
labelIcon,
|
|
1243
|
+
sizeStyles.labelIconSize,
|
|
1244
|
+
textColor
|
|
1245
|
+
) }),
|
|
1246
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Text, { color: textColor, fontSize: sizeStyles.fontSize, fontWeight: "500", children }),
|
|
1247
|
+
sublabel && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1248
|
+
Text,
|
|
1249
|
+
{
|
|
1250
|
+
color: textColor,
|
|
1251
|
+
fontSize: sizeStyles.fontSize,
|
|
1252
|
+
fontWeight: "500",
|
|
1253
|
+
style: { opacity: 0.4 },
|
|
1254
|
+
children: sublabel
|
|
1255
|
+
}
|
|
1256
|
+
),
|
|
1257
|
+
customContent && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Box, { "aria-hidden": true, children: customContent })
|
|
1258
|
+
]
|
|
1259
|
+
}
|
|
1260
|
+
),
|
|
1261
|
+
iconRight && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1262
|
+
Box,
|
|
1263
|
+
{
|
|
1264
|
+
width: sizeStyles.iconContainerSize,
|
|
1265
|
+
height: sizeStyles.iconContainerSize,
|
|
1266
|
+
alignItems: "center",
|
|
1267
|
+
justifyContent: "center",
|
|
1268
|
+
"aria-hidden": true,
|
|
1269
|
+
style: {
|
|
1270
|
+
opacity: loading ? 0 : 1,
|
|
1271
|
+
pointerEvents: loading ? "none" : "auto"
|
|
1272
|
+
},
|
|
1273
|
+
children: cloneIconWithDefaults3(iconRight, sizeStyles.iconSize, textColor)
|
|
1274
|
+
}
|
|
1275
|
+
)
|
|
1276
|
+
]
|
|
1277
|
+
}
|
|
1278
|
+
);
|
|
1279
|
+
};
|
|
1280
|
+
AppButton.displayName = "AppButton";
|
|
1281
|
+
|
|
1282
|
+
// src/ButtonGroup.tsx
|
|
1283
|
+
var import_react6 = __toESM(require("react"));
|
|
1284
|
+
var import_xui_core5 = require("@xsolla/xui-core");
|
|
1285
|
+
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
1036
1286
|
var ButtonGroup = ({
|
|
1037
1287
|
orientation = "horizontal",
|
|
1038
1288
|
size = "md",
|
|
@@ -1046,11 +1296,11 @@ var ButtonGroup = ({
|
|
|
1046
1296
|
id,
|
|
1047
1297
|
testID
|
|
1048
1298
|
}) => {
|
|
1049
|
-
const { theme } = (0,
|
|
1299
|
+
const { theme } = (0, import_xui_core5.useDesignSystem)();
|
|
1050
1300
|
const flattenChildren = (children2) => {
|
|
1051
1301
|
const result = [];
|
|
1052
|
-
|
|
1053
|
-
if (
|
|
1302
|
+
import_react6.default.Children.forEach(children2, (child) => {
|
|
1303
|
+
if (import_react6.default.isValidElement(child) && child.type === import_react6.default.Fragment) {
|
|
1054
1304
|
result.push(...flattenChildren(child.props.children));
|
|
1055
1305
|
} else if (child !== null && child !== void 0) {
|
|
1056
1306
|
result.push(child);
|
|
@@ -1086,8 +1336,8 @@ var ButtonGroup = ({
|
|
|
1086
1336
|
const processChildren = (childrenToProcess) => {
|
|
1087
1337
|
if (orientation === "vertical") {
|
|
1088
1338
|
return childrenToProcess.map((child, index) => {
|
|
1089
|
-
if (
|
|
1090
|
-
return
|
|
1339
|
+
if (import_react6.default.isValidElement(child)) {
|
|
1340
|
+
return import_react6.default.cloneElement(child, {
|
|
1091
1341
|
...child.props,
|
|
1092
1342
|
fullWidth: true,
|
|
1093
1343
|
key: child.key ?? index
|
|
@@ -1103,9 +1353,9 @@ var ButtonGroup = ({
|
|
|
1103
1353
|
if (useSpaceBetween) {
|
|
1104
1354
|
const firstChild = processedChildren[0];
|
|
1105
1355
|
const restChildren = processedChildren.slice(1);
|
|
1106
|
-
return /* @__PURE__ */ (0,
|
|
1356
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(import_jsx_runtime9.Fragment, { children: [
|
|
1107
1357
|
firstChild,
|
|
1108
|
-
/* @__PURE__ */ (0,
|
|
1358
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Box, { flexDirection: "row", gap: computedGap, children: restChildren })
|
|
1109
1359
|
] });
|
|
1110
1360
|
}
|
|
1111
1361
|
if (orientation === "vertical") {
|
|
@@ -1113,8 +1363,8 @@ var ButtonGroup = ({
|
|
|
1113
1363
|
}
|
|
1114
1364
|
return children;
|
|
1115
1365
|
};
|
|
1116
|
-
return /* @__PURE__ */ (0,
|
|
1117
|
-
/* @__PURE__ */ (0,
|
|
1366
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(Box, { flexDirection: "column", width: "100%", gap: 8, children: [
|
|
1367
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1118
1368
|
Box,
|
|
1119
1369
|
{
|
|
1120
1370
|
role: "group",
|
|
@@ -1131,7 +1381,7 @@ var ButtonGroup = ({
|
|
|
1131
1381
|
children: renderChildren()
|
|
1132
1382
|
}
|
|
1133
1383
|
),
|
|
1134
|
-
error && /* @__PURE__ */ (0,
|
|
1384
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Box, { marginTop: 4, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1135
1385
|
Text,
|
|
1136
1386
|
{
|
|
1137
1387
|
id: errorId,
|
|
@@ -1144,7 +1394,7 @@ var ButtonGroup = ({
|
|
|
1144
1394
|
children: error
|
|
1145
1395
|
}
|
|
1146
1396
|
) }),
|
|
1147
|
-
description && /* @__PURE__ */ (0,
|
|
1397
|
+
description && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Box, { marginTop: 4, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
1148
1398
|
Text,
|
|
1149
1399
|
{
|
|
1150
1400
|
id: descriptionId,
|
|
@@ -1160,6 +1410,7 @@ var ButtonGroup = ({
|
|
|
1160
1410
|
ButtonGroup.displayName = "ButtonGroup";
|
|
1161
1411
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1162
1412
|
0 && (module.exports = {
|
|
1413
|
+
AppButton,
|
|
1163
1414
|
Button,
|
|
1164
1415
|
ButtonGroup,
|
|
1165
1416
|
FlexButton,
|
package/native/index.js.flow
CHANGED
|
@@ -372,6 +372,119 @@ declare type FlexButtonProps = {
|
|
|
372
372
|
* - **Screen Reader Support**: Announces button label, state, and any associated descriptions
|
|
373
373
|
*/
|
|
374
374
|
declare var FlexButton: React.FC<FlexButtonProps>;
|
|
375
|
+
declare interface AppButtonProps {
|
|
376
|
+
/**
|
|
377
|
+
* Size of the button
|
|
378
|
+
*/
|
|
379
|
+
size?: "xl" | "lg" | "md" | "sm" | "xs";
|
|
380
|
+
|
|
381
|
+
/**
|
|
382
|
+
* Whether the button is disabled
|
|
383
|
+
*/
|
|
384
|
+
disabled?: boolean;
|
|
385
|
+
|
|
386
|
+
/**
|
|
387
|
+
* Whether the button is in a loading state
|
|
388
|
+
*/
|
|
389
|
+
loading?: boolean;
|
|
390
|
+
|
|
391
|
+
/**
|
|
392
|
+
* Button content
|
|
393
|
+
*/
|
|
394
|
+
children: React.ReactNode;
|
|
395
|
+
|
|
396
|
+
/**
|
|
397
|
+
* Click handler
|
|
398
|
+
*/
|
|
399
|
+
onPress?: () => void;
|
|
400
|
+
|
|
401
|
+
/**
|
|
402
|
+
* Icon to display on the left side
|
|
403
|
+
*/
|
|
404
|
+
iconLeft?: React.ReactNode;
|
|
405
|
+
|
|
406
|
+
/**
|
|
407
|
+
* Icon to display on the right side
|
|
408
|
+
*/
|
|
409
|
+
iconRight?: React.ReactNode;
|
|
410
|
+
|
|
411
|
+
/**
|
|
412
|
+
* Secondary text displayed inline with the main label
|
|
413
|
+
*/
|
|
414
|
+
sublabel?: string;
|
|
415
|
+
|
|
416
|
+
/**
|
|
417
|
+
* Alignment of the label text
|
|
418
|
+
*/
|
|
419
|
+
labelAlignment?: "left" | "center";
|
|
420
|
+
|
|
421
|
+
/**
|
|
422
|
+
* Small icon displayed directly next to the label text
|
|
423
|
+
*/
|
|
424
|
+
labelIcon?: React.ReactNode;
|
|
425
|
+
|
|
426
|
+
/**
|
|
427
|
+
* Custom content slot for badges, tags, or other elements
|
|
428
|
+
*/
|
|
429
|
+
customContent?: React.ReactNode;
|
|
430
|
+
|
|
431
|
+
/**
|
|
432
|
+
* Accessible label for screen readers
|
|
433
|
+
*/
|
|
434
|
+
"aria-label"?: string;
|
|
435
|
+
|
|
436
|
+
/**
|
|
437
|
+
* ID of element that describes this button
|
|
438
|
+
*/
|
|
439
|
+
"aria-describedby"?: string;
|
|
440
|
+
|
|
441
|
+
/**
|
|
442
|
+
* Indicates the button controls an expandable element
|
|
443
|
+
*/
|
|
444
|
+
"aria-expanded"?: boolean;
|
|
445
|
+
|
|
446
|
+
/**
|
|
447
|
+
* Indicates the type of popup triggered by the button
|
|
448
|
+
*/
|
|
449
|
+
"aria-haspopup"?: boolean | "menu" | "listbox" | "tree" | "grid" | "dialog";
|
|
450
|
+
|
|
451
|
+
/**
|
|
452
|
+
* Indicates the button is pressed (for toggle buttons)
|
|
453
|
+
*/
|
|
454
|
+
"aria-pressed"?: boolean | "mixed";
|
|
455
|
+
|
|
456
|
+
/**
|
|
457
|
+
* ID of the element this button controls
|
|
458
|
+
*/
|
|
459
|
+
"aria-controls"?: string;
|
|
460
|
+
|
|
461
|
+
/**
|
|
462
|
+
* Test ID for testing frameworks
|
|
463
|
+
*/
|
|
464
|
+
testID?: string;
|
|
465
|
+
|
|
466
|
+
/**
|
|
467
|
+
* HTML id attribute
|
|
468
|
+
*/
|
|
469
|
+
id?: string;
|
|
470
|
+
|
|
471
|
+
/**
|
|
472
|
+
* HTML type attribute for the button
|
|
473
|
+
*/
|
|
474
|
+
type?: "button" | "submit" | "reset";
|
|
475
|
+
|
|
476
|
+
/**
|
|
477
|
+
* Whether the button should stretch to fill the full width of its container
|
|
478
|
+
*/
|
|
479
|
+
fullWidth?: boolean;
|
|
480
|
+
}
|
|
481
|
+
/**
|
|
482
|
+
* AppButton - A prominent filled button for app-level actions.
|
|
483
|
+
*
|
|
484
|
+
* Uses the `control.appButton` theme tokens for styling.
|
|
485
|
+
* Supports all the same layout features as Button (icons, sublabels, etc.).
|
|
486
|
+
*/
|
|
487
|
+
declare var AppButton: React.FC<AppButtonProps>;
|
|
375
488
|
declare interface ButtonGroupProps {
|
|
376
489
|
/**
|
|
377
490
|
* Layout orientation of the buttons
|
|
@@ -443,5 +556,11 @@ declare interface ButtonGroupProps {
|
|
|
443
556
|
* - **Description Support**: Optional description text for additional context
|
|
444
557
|
*/
|
|
445
558
|
declare var ButtonGroup: React.FC<ButtonGroupProps>;
|
|
446
|
-
export type {
|
|
447
|
-
|
|
559
|
+
export type {
|
|
560
|
+
AppButtonProps,
|
|
561
|
+
ButtonGroupProps,
|
|
562
|
+
ButtonProps,
|
|
563
|
+
FlexButtonProps,
|
|
564
|
+
IconButtonProps,
|
|
565
|
+
};
|
|
566
|
+
declare export { AppButton, Button, ButtonGroup, FlexButton, IconButton };
|