@xsolla/xui-button 0.112.0 → 0.113.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
@@ -172,7 +172,10 @@ var Box = ({
172
172
  };
173
173
 
174
174
  // ../primitives-native/src/Text.tsx
175
- import { Text as RNText } from "react-native";
175
+ import {
176
+ Text as RNText,
177
+ StyleSheet
178
+ } from "react-native";
176
179
  import { jsx as jsx2 } from "react/jsx-runtime";
177
180
  var roleMap = {
178
181
  alert: "alert",
@@ -181,29 +184,57 @@ var roleMap = {
181
184
  link: "link",
182
185
  text: "text"
183
186
  };
187
+ var parseNumericValue = (value) => {
188
+ if (value === void 0) return void 0;
189
+ if (typeof value === "number") return value;
190
+ const parsed = parseFloat(value);
191
+ return isNaN(parsed) ? void 0 : parsed;
192
+ };
184
193
  var Text = ({
185
194
  children,
186
195
  color,
187
196
  fontSize,
188
197
  fontWeight,
189
198
  fontFamily,
199
+ textAlign,
200
+ lineHeight,
201
+ numberOfLines,
190
202
  id,
191
203
  role,
204
+ style: styleProp,
192
205
  ...props
193
206
  }) => {
194
207
  let resolvedFontFamily = fontFamily ? fontFamily.split(",")[0].replace(/['"]/g, "").trim() : void 0;
195
208
  if (resolvedFontFamily === "Pilat Wide" || resolvedFontFamily === "Pilat Wide Bold" || resolvedFontFamily === "Aktiv Grotesk") {
196
209
  resolvedFontFamily = void 0;
197
210
  }
198
- const style = {
211
+ const incomingStyle = StyleSheet.flatten(styleProp);
212
+ const baseStyle = {
199
213
  color,
200
214
  fontSize: typeof fontSize === "number" ? fontSize : void 0,
201
215
  fontWeight,
202
216
  fontFamily: resolvedFontFamily,
203
- textDecorationLine: props.textDecoration
217
+ textDecorationLine: props.textDecoration,
218
+ textAlign: textAlign ?? incomingStyle?.textAlign,
219
+ lineHeight: parseNumericValue(lineHeight ?? incomingStyle?.lineHeight),
220
+ marginTop: parseNumericValue(
221
+ incomingStyle?.marginTop
222
+ ),
223
+ marginBottom: parseNumericValue(
224
+ incomingStyle?.marginBottom
225
+ )
204
226
  };
205
227
  const accessibilityRole = role ? roleMap[role] : void 0;
206
- return /* @__PURE__ */ jsx2(RNText, { style, testID: id, accessibilityRole, children });
228
+ return /* @__PURE__ */ jsx2(
229
+ RNText,
230
+ {
231
+ style: baseStyle,
232
+ numberOfLines,
233
+ testID: id,
234
+ accessibilityRole,
235
+ children
236
+ }
237
+ );
207
238
  };
208
239
 
209
240
  // ../primitives-native/src/Spinner.tsx
@@ -997,10 +1028,231 @@ var FlexButton = ({
997
1028
  };
998
1029
  FlexButton.displayName = "FlexButton";
999
1030
 
1000
- // src/ButtonGroup.tsx
1001
- import React5 from "react";
1031
+ // src/AppButton.tsx
1032
+ import React5, { useState as useState4 } from "react";
1002
1033
  import { useDesignSystem as useDesignSystem4 } from "@xsolla/xui-core";
1003
- import { Fragment as Fragment2, jsx as jsx8, jsxs as jsxs4 } from "react/jsx-runtime";
1034
+ import { jsx as jsx8, jsxs as jsxs4 } from "react/jsx-runtime";
1035
+ var cloneIconWithDefaults3 = (icon, defaultSize, defaultColor) => {
1036
+ if (!React5.isValidElement(icon)) return icon;
1037
+ const iconElement = icon;
1038
+ const existingProps = iconElement.props || {};
1039
+ return React5.cloneElement(iconElement, {
1040
+ ...existingProps,
1041
+ size: existingProps.size ?? defaultSize,
1042
+ color: existingProps.color ?? defaultColor
1043
+ });
1044
+ };
1045
+ var AppButton = ({
1046
+ size = "md",
1047
+ disabled = false,
1048
+ loading = false,
1049
+ children,
1050
+ onPress,
1051
+ iconLeft,
1052
+ iconRight,
1053
+ sublabel,
1054
+ labelAlignment = "center",
1055
+ labelIcon,
1056
+ customContent,
1057
+ "aria-label": ariaLabel,
1058
+ "aria-describedby": ariaDescribedBy,
1059
+ "aria-expanded": ariaExpanded,
1060
+ "aria-haspopup": ariaHasPopup,
1061
+ "aria-pressed": ariaPressed,
1062
+ "aria-controls": ariaControls,
1063
+ testID,
1064
+ id,
1065
+ type = "button",
1066
+ fullWidth = false
1067
+ }) => {
1068
+ const { theme } = useDesignSystem4();
1069
+ const [isKeyboardPressed, setIsKeyboardPressed] = useState4(false);
1070
+ const isDisabled = disabled || loading;
1071
+ const sizeStyles = theme.sizing.button(size);
1072
+ const tokens = theme?.colors?.control?.appButton || {
1073
+ bg: "#34474b",
1074
+ bgHover: "#3d5256",
1075
+ bgPress: "#2b3b3e",
1076
+ border: "rgba(255, 255, 255, 0.12)",
1077
+ borderHover: "rgba(255, 255, 255, 0.18)",
1078
+ borderPress: "rgba(255, 255, 255, 0.12)",
1079
+ text: "#b7c5c8",
1080
+ textDisable: "#b3b3b3"
1081
+ };
1082
+ const handlePress = () => {
1083
+ if (!isDisabled && onPress) {
1084
+ onPress();
1085
+ }
1086
+ };
1087
+ const handleKeyDown = (e) => {
1088
+ if (isDisabled) return;
1089
+ if (e.key === "Enter" || e.key === " ") {
1090
+ e.preventDefault();
1091
+ setIsKeyboardPressed(true);
1092
+ }
1093
+ };
1094
+ const handleKeyUp = (e) => {
1095
+ if (isDisabled) return;
1096
+ if (e.key === "Enter" || e.key === " ") {
1097
+ e.preventDefault();
1098
+ setIsKeyboardPressed(false);
1099
+ if (onPress) {
1100
+ onPress();
1101
+ }
1102
+ }
1103
+ };
1104
+ let backgroundColor = tokens.bg;
1105
+ if (disabled) {
1106
+ backgroundColor = tokens.bg;
1107
+ } else if (isKeyboardPressed) {
1108
+ backgroundColor = tokens.bgPress;
1109
+ }
1110
+ const borderColor = tokens.border;
1111
+ const textColor = disabled ? tokens.textDisable : tokens.text;
1112
+ return /* @__PURE__ */ jsxs4(
1113
+ Box,
1114
+ {
1115
+ as: "button",
1116
+ type,
1117
+ id,
1118
+ onPress: handlePress,
1119
+ onKeyDown: handleKeyDown,
1120
+ onKeyUp: handleKeyUp,
1121
+ disabled: isDisabled,
1122
+ "aria-label": ariaLabel,
1123
+ "aria-disabled": isDisabled || void 0,
1124
+ "aria-busy": loading || void 0,
1125
+ "aria-describedby": ariaDescribedBy,
1126
+ "aria-expanded": ariaExpanded,
1127
+ "aria-haspopup": ariaHasPopup,
1128
+ "aria-pressed": ariaPressed,
1129
+ "aria-controls": ariaControls,
1130
+ testID,
1131
+ backgroundColor,
1132
+ borderColor,
1133
+ borderWidth: borderColor !== "transparent" && borderColor !== "rgba(255, 255, 255, 0)" && borderColor !== "rgba(0, 0, 0, 0)" && !borderColor.endsWith(", 0)") ? 1 : 0,
1134
+ borderRadius: sizeStyles.borderRadius,
1135
+ height: sizeStyles.height,
1136
+ width: fullWidth ? "100%" : void 0,
1137
+ padding: 0,
1138
+ flexDirection: "row",
1139
+ alignItems: "center",
1140
+ justifyContent: "center",
1141
+ position: "relative",
1142
+ cursor: disabled ? "not-allowed" : loading ? "wait" : "pointer",
1143
+ opacity: disabled ? 0.6 : 1,
1144
+ hoverStyle: !isDisabled ? {
1145
+ backgroundColor: tokens.bgHover,
1146
+ borderColor: tokens.borderHover
1147
+ } : void 0,
1148
+ pressStyle: !isDisabled ? {
1149
+ backgroundColor: tokens.bgPress,
1150
+ borderColor: tokens.borderPress
1151
+ } : void 0,
1152
+ focusStyle: {
1153
+ outlineColor: theme.colors.border.brand,
1154
+ outlineWidth: 2,
1155
+ outlineOffset: 2,
1156
+ outlineStyle: "solid"
1157
+ },
1158
+ children: [
1159
+ loading && /* @__PURE__ */ jsx8(
1160
+ Box,
1161
+ {
1162
+ position: "absolute",
1163
+ top: 0,
1164
+ left: 0,
1165
+ right: 0,
1166
+ bottom: 0,
1167
+ alignItems: "center",
1168
+ justifyContent: "center",
1169
+ zIndex: 1,
1170
+ children: /* @__PURE__ */ jsx8(
1171
+ Spinner,
1172
+ {
1173
+ color: textColor,
1174
+ size: sizeStyles.spinnerSize,
1175
+ "aria-hidden": true
1176
+ }
1177
+ )
1178
+ }
1179
+ ),
1180
+ iconLeft && /* @__PURE__ */ jsx8(
1181
+ Box,
1182
+ {
1183
+ width: sizeStyles.iconContainerSize,
1184
+ height: sizeStyles.iconContainerSize,
1185
+ alignItems: "center",
1186
+ justifyContent: "center",
1187
+ "aria-hidden": true,
1188
+ style: {
1189
+ opacity: loading ? 0 : 1,
1190
+ pointerEvents: loading ? "none" : "auto"
1191
+ },
1192
+ children: cloneIconWithDefaults3(iconLeft, sizeStyles.iconSize, textColor)
1193
+ }
1194
+ ),
1195
+ /* @__PURE__ */ jsxs4(
1196
+ Box,
1197
+ {
1198
+ flex: fullWidth ? 1 : void 0,
1199
+ flexDirection: "row",
1200
+ alignItems: "center",
1201
+ justifyContent: labelAlignment === "left" ? "flex-start" : "center",
1202
+ paddingHorizontal: sizeStyles.padding,
1203
+ height: "100%",
1204
+ gap: sizeStyles.labelIconGap,
1205
+ style: {
1206
+ opacity: loading ? 0 : 1,
1207
+ pointerEvents: loading ? "none" : "auto"
1208
+ },
1209
+ "aria-hidden": loading ? true : void 0,
1210
+ children: [
1211
+ labelIcon && /* @__PURE__ */ jsx8(Box, { "aria-hidden": true, children: cloneIconWithDefaults3(
1212
+ labelIcon,
1213
+ sizeStyles.labelIconSize,
1214
+ textColor
1215
+ ) }),
1216
+ /* @__PURE__ */ jsx8(Text, { color: textColor, fontSize: sizeStyles.fontSize, fontWeight: "500", children }),
1217
+ sublabel && /* @__PURE__ */ jsx8(
1218
+ Text,
1219
+ {
1220
+ color: textColor,
1221
+ fontSize: sizeStyles.fontSize,
1222
+ fontWeight: "500",
1223
+ style: { opacity: 0.4 },
1224
+ children: sublabel
1225
+ }
1226
+ ),
1227
+ customContent && /* @__PURE__ */ jsx8(Box, { "aria-hidden": true, children: customContent })
1228
+ ]
1229
+ }
1230
+ ),
1231
+ iconRight && /* @__PURE__ */ jsx8(
1232
+ Box,
1233
+ {
1234
+ width: sizeStyles.iconContainerSize,
1235
+ height: sizeStyles.iconContainerSize,
1236
+ alignItems: "center",
1237
+ justifyContent: "center",
1238
+ "aria-hidden": true,
1239
+ style: {
1240
+ opacity: loading ? 0 : 1,
1241
+ pointerEvents: loading ? "none" : "auto"
1242
+ },
1243
+ children: cloneIconWithDefaults3(iconRight, sizeStyles.iconSize, textColor)
1244
+ }
1245
+ )
1246
+ ]
1247
+ }
1248
+ );
1249
+ };
1250
+ AppButton.displayName = "AppButton";
1251
+
1252
+ // src/ButtonGroup.tsx
1253
+ import React6 from "react";
1254
+ import { useDesignSystem as useDesignSystem5 } from "@xsolla/xui-core";
1255
+ import { Fragment as Fragment2, jsx as jsx9, jsxs as jsxs5 } from "react/jsx-runtime";
1004
1256
  var ButtonGroup = ({
1005
1257
  orientation = "horizontal",
1006
1258
  size = "md",
@@ -1014,11 +1266,11 @@ var ButtonGroup = ({
1014
1266
  id,
1015
1267
  testID
1016
1268
  }) => {
1017
- const { theme } = useDesignSystem4();
1269
+ const { theme } = useDesignSystem5();
1018
1270
  const flattenChildren = (children2) => {
1019
1271
  const result = [];
1020
- React5.Children.forEach(children2, (child) => {
1021
- if (React5.isValidElement(child) && child.type === React5.Fragment) {
1272
+ React6.Children.forEach(children2, (child) => {
1273
+ if (React6.isValidElement(child) && child.type === React6.Fragment) {
1022
1274
  result.push(...flattenChildren(child.props.children));
1023
1275
  } else if (child !== null && child !== void 0) {
1024
1276
  result.push(child);
@@ -1054,8 +1306,8 @@ var ButtonGroup = ({
1054
1306
  const processChildren = (childrenToProcess) => {
1055
1307
  if (orientation === "vertical") {
1056
1308
  return childrenToProcess.map((child, index) => {
1057
- if (React5.isValidElement(child)) {
1058
- return React5.cloneElement(child, {
1309
+ if (React6.isValidElement(child)) {
1310
+ return React6.cloneElement(child, {
1059
1311
  ...child.props,
1060
1312
  fullWidth: true,
1061
1313
  key: child.key ?? index
@@ -1071,9 +1323,9 @@ var ButtonGroup = ({
1071
1323
  if (useSpaceBetween) {
1072
1324
  const firstChild = processedChildren[0];
1073
1325
  const restChildren = processedChildren.slice(1);
1074
- return /* @__PURE__ */ jsxs4(Fragment2, { children: [
1326
+ return /* @__PURE__ */ jsxs5(Fragment2, { children: [
1075
1327
  firstChild,
1076
- /* @__PURE__ */ jsx8(Box, { flexDirection: "row", gap: computedGap, children: restChildren })
1328
+ /* @__PURE__ */ jsx9(Box, { flexDirection: "row", gap: computedGap, children: restChildren })
1077
1329
  ] });
1078
1330
  }
1079
1331
  if (orientation === "vertical") {
@@ -1081,8 +1333,8 @@ var ButtonGroup = ({
1081
1333
  }
1082
1334
  return children;
1083
1335
  };
1084
- return /* @__PURE__ */ jsxs4(Box, { flexDirection: "column", width: "100%", gap: 8, children: [
1085
- /* @__PURE__ */ jsx8(
1336
+ return /* @__PURE__ */ jsxs5(Box, { flexDirection: "column", width: "100%", gap: 8, children: [
1337
+ /* @__PURE__ */ jsx9(
1086
1338
  Box,
1087
1339
  {
1088
1340
  role: "group",
@@ -1099,7 +1351,7 @@ var ButtonGroup = ({
1099
1351
  children: renderChildren()
1100
1352
  }
1101
1353
  ),
1102
- error && /* @__PURE__ */ jsx8(Box, { marginTop: 4, children: /* @__PURE__ */ jsx8(
1354
+ error && /* @__PURE__ */ jsx9(Box, { marginTop: 4, children: /* @__PURE__ */ jsx9(
1103
1355
  Text,
1104
1356
  {
1105
1357
  id: errorId,
@@ -1112,7 +1364,7 @@ var ButtonGroup = ({
1112
1364
  children: error
1113
1365
  }
1114
1366
  ) }),
1115
- description && /* @__PURE__ */ jsx8(Box, { marginTop: 4, children: /* @__PURE__ */ jsx8(
1367
+ description && /* @__PURE__ */ jsx9(Box, { marginTop: 4, children: /* @__PURE__ */ jsx9(
1116
1368
  Text,
1117
1369
  {
1118
1370
  id: descriptionId,
@@ -1127,6 +1379,7 @@ var ButtonGroup = ({
1127
1379
  };
1128
1380
  ButtonGroup.displayName = "ButtonGroup";
1129
1381
  export {
1382
+ AppButton,
1130
1383
  Button,
1131
1384
  ButtonGroup,
1132
1385
  FlexButton,