@xsolla/xui-spinner 0.131.0 → 0.133.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 +3 -3
- package/web/index.js +106 -1
- package/web/index.js.map +1 -1
- package/web/index.mjs +106 -1
- package/web/index.mjs.map +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xsolla/xui-spinner",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.133.0",
|
|
4
4
|
"main": "./web/index.js",
|
|
5
5
|
"module": "./web/index.mjs",
|
|
6
6
|
"types": "./web/index.d.ts",
|
|
@@ -10,8 +10,8 @@
|
|
|
10
10
|
"build:native": "PLATFORM=native tsup"
|
|
11
11
|
},
|
|
12
12
|
"dependencies": {
|
|
13
|
-
"@xsolla/xui-core": "0.
|
|
14
|
-
"@xsolla/xui-primitives-core": "0.
|
|
13
|
+
"@xsolla/xui-core": "0.133.0",
|
|
14
|
+
"@xsolla/xui-primitives-core": "0.133.0"
|
|
15
15
|
},
|
|
16
16
|
"peerDependencies": {
|
|
17
17
|
"react": ">=16.8.0",
|
package/web/index.js
CHANGED
|
@@ -34,6 +34,110 @@ __export(index_exports, {
|
|
|
34
34
|
});
|
|
35
35
|
module.exports = __toCommonJS(index_exports);
|
|
36
36
|
|
|
37
|
+
// ../primitives-web/src/filterDOMProps.ts
|
|
38
|
+
var import_react = __toESM(require("react"));
|
|
39
|
+
var NON_HTML_PROPS = /* @__PURE__ */ new Set([
|
|
40
|
+
// BoxProps — layout & styling
|
|
41
|
+
"backgroundColor",
|
|
42
|
+
"borderColor",
|
|
43
|
+
"borderWidth",
|
|
44
|
+
"borderBottomWidth",
|
|
45
|
+
"borderBottomColor",
|
|
46
|
+
"borderTopWidth",
|
|
47
|
+
"borderTopColor",
|
|
48
|
+
"borderLeftWidth",
|
|
49
|
+
"borderLeftColor",
|
|
50
|
+
"borderRightWidth",
|
|
51
|
+
"borderRightColor",
|
|
52
|
+
"borderRadius",
|
|
53
|
+
"borderStyle",
|
|
54
|
+
"flexDirection",
|
|
55
|
+
"flexWrap",
|
|
56
|
+
"alignItems",
|
|
57
|
+
"justifyContent",
|
|
58
|
+
"alignSelf",
|
|
59
|
+
"flex",
|
|
60
|
+
"flexShrink",
|
|
61
|
+
"gap",
|
|
62
|
+
"position",
|
|
63
|
+
"top",
|
|
64
|
+
"bottom",
|
|
65
|
+
"left",
|
|
66
|
+
"right",
|
|
67
|
+
"outline",
|
|
68
|
+
"overflow",
|
|
69
|
+
"overflowX",
|
|
70
|
+
"overflowY",
|
|
71
|
+
"zIndex",
|
|
72
|
+
"cursor",
|
|
73
|
+
"padding",
|
|
74
|
+
"paddingHorizontal",
|
|
75
|
+
"paddingVertical",
|
|
76
|
+
"paddingTop",
|
|
77
|
+
"paddingBottom",
|
|
78
|
+
"paddingLeft",
|
|
79
|
+
"paddingRight",
|
|
80
|
+
"margin",
|
|
81
|
+
"marginTop",
|
|
82
|
+
"marginBottom",
|
|
83
|
+
"marginLeft",
|
|
84
|
+
"marginRight",
|
|
85
|
+
"minWidth",
|
|
86
|
+
"minHeight",
|
|
87
|
+
"maxWidth",
|
|
88
|
+
"maxHeight",
|
|
89
|
+
"hoverStyle",
|
|
90
|
+
"pressStyle",
|
|
91
|
+
"focusStyle",
|
|
92
|
+
"outlineColor",
|
|
93
|
+
"outlineWidth",
|
|
94
|
+
"outlineOffset",
|
|
95
|
+
"outlineStyle",
|
|
96
|
+
// BoxProps — RN-only
|
|
97
|
+
"onPress",
|
|
98
|
+
"onLayout",
|
|
99
|
+
"onMoveShouldSetResponder",
|
|
100
|
+
"onResponderGrant",
|
|
101
|
+
"onResponderMove",
|
|
102
|
+
"onResponderRelease",
|
|
103
|
+
"onResponderTerminate",
|
|
104
|
+
"testID",
|
|
105
|
+
// Box — custom element type
|
|
106
|
+
"elementType",
|
|
107
|
+
// TextProps
|
|
108
|
+
"fontSize",
|
|
109
|
+
"fontWeight",
|
|
110
|
+
"fontFamily",
|
|
111
|
+
"lineHeight",
|
|
112
|
+
"whiteSpace",
|
|
113
|
+
"textAlign",
|
|
114
|
+
"textDecoration",
|
|
115
|
+
"numberOfLines",
|
|
116
|
+
"letterSpacing",
|
|
117
|
+
"textTransform",
|
|
118
|
+
// SpinnerProps
|
|
119
|
+
"strokeWidth",
|
|
120
|
+
// DividerProps
|
|
121
|
+
"vertical",
|
|
122
|
+
"dashStroke"
|
|
123
|
+
]);
|
|
124
|
+
function createFilteredElement(defaultTag) {
|
|
125
|
+
const Component = import_react.default.forwardRef(
|
|
126
|
+
({ children, elementType, ...props }, ref) => {
|
|
127
|
+
const Tag = elementType || defaultTag;
|
|
128
|
+
const htmlProps = {};
|
|
129
|
+
for (const key of Object.keys(props)) {
|
|
130
|
+
if (!NON_HTML_PROPS.has(key)) {
|
|
131
|
+
htmlProps[key] = props[key];
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return import_react.default.createElement(Tag, { ref, ...htmlProps }, children);
|
|
135
|
+
}
|
|
136
|
+
);
|
|
137
|
+
Component.displayName = `Filtered(${defaultTag})`;
|
|
138
|
+
return Component;
|
|
139
|
+
}
|
|
140
|
+
|
|
37
141
|
// ../primitives-web/src/Spinner.tsx
|
|
38
142
|
var import_styled_components = __toESM(require("styled-components"));
|
|
39
143
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
@@ -45,7 +149,8 @@ var rotate = import_styled_components.keyframes`
|
|
|
45
149
|
transform: rotate(360deg);
|
|
46
150
|
}
|
|
47
151
|
`;
|
|
48
|
-
var
|
|
152
|
+
var FilteredDiv = createFilteredElement("div");
|
|
153
|
+
var StyledSpinner = (0, import_styled_components.default)(FilteredDiv)`
|
|
49
154
|
width: ${(props) => typeof props.size === "number" ? `${props.size}px` : props.size || "24px"};
|
|
50
155
|
height: ${(props) => typeof props.size === "number" ? `${props.size}px` : props.size || "24px"};
|
|
51
156
|
border: ${(props) => props.strokeWidth || 2}px solid
|
package/web/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/index.tsx","../../../primitives-web/src/Spinner.tsx","../../src/Spinner.tsx"],"sourcesContent":["export * from \"./Spinner\";\n","import React from \"react\";\nimport styled, { keyframes } from \"styled-components\";\nimport type { SpinnerProps } from \"@xsolla/xui-primitives-core\";\n\nconst rotate = keyframes`\n from {\n transform: rotate(0deg);\n }\n to {\n transform: rotate(360deg);\n }\n`;\n\nconst StyledSpinner = styled
|
|
1
|
+
{"version":3,"sources":["../../src/index.tsx","../../../primitives-web/src/filterDOMProps.ts","../../../primitives-web/src/Spinner.tsx","../../src/Spinner.tsx"],"sourcesContent":["export * from \"./Spinner\";\n","import React from \"react\";\n\n// Props from BoxProps, TextProps, SpinnerProps, IconProps, DividerProps\n// that are NOT valid HTML attributes and must not reach the DOM.\nexport const NON_HTML_PROPS = new Set([\n // BoxProps — layout & styling\n \"backgroundColor\",\n \"borderColor\",\n \"borderWidth\",\n \"borderBottomWidth\",\n \"borderBottomColor\",\n \"borderTopWidth\",\n \"borderTopColor\",\n \"borderLeftWidth\",\n \"borderLeftColor\",\n \"borderRightWidth\",\n \"borderRightColor\",\n \"borderRadius\",\n \"borderStyle\",\n \"flexDirection\",\n \"flexWrap\",\n \"alignItems\",\n \"justifyContent\",\n \"alignSelf\",\n \"flex\",\n \"flexShrink\",\n \"gap\",\n \"position\",\n \"top\",\n \"bottom\",\n \"left\",\n \"right\",\n \"outline\",\n \"overflow\",\n \"overflowX\",\n \"overflowY\",\n \"zIndex\",\n \"cursor\",\n \"padding\",\n \"paddingHorizontal\",\n \"paddingVertical\",\n \"paddingTop\",\n \"paddingBottom\",\n \"paddingLeft\",\n \"paddingRight\",\n \"margin\",\n \"marginTop\",\n \"marginBottom\",\n \"marginLeft\",\n \"marginRight\",\n \"minWidth\",\n \"minHeight\",\n \"maxWidth\",\n \"maxHeight\",\n \"hoverStyle\",\n \"pressStyle\",\n \"focusStyle\",\n \"outlineColor\",\n \"outlineWidth\",\n \"outlineOffset\",\n \"outlineStyle\",\n // BoxProps — RN-only\n \"onPress\",\n \"onLayout\",\n \"onMoveShouldSetResponder\",\n \"onResponderGrant\",\n \"onResponderMove\",\n \"onResponderRelease\",\n \"onResponderTerminate\",\n \"testID\",\n // Box — custom element type\n \"elementType\",\n // TextProps\n \"fontSize\",\n \"fontWeight\",\n \"fontFamily\",\n \"lineHeight\",\n \"whiteSpace\",\n \"textAlign\",\n \"textDecoration\",\n \"numberOfLines\",\n \"letterSpacing\",\n \"textTransform\",\n // SpinnerProps\n \"strokeWidth\",\n // DividerProps\n \"vertical\",\n \"dashStroke\",\n]);\n\n/**\n * Creates a React component that renders the given HTML tag\n * but filters out non-HTML props before they reach the DOM.\n *\n * Usage: `const FilteredDiv = createFilteredElement(\"div\");`\n * Then: `const StyledBox = styled(FilteredDiv)<BoxProps>\\`...\\`;`\n *\n * styled-components can still read ALL props for CSS interpolation,\n * but only valid HTML attributes are forwarded to the DOM element.\n */\nexport function createFilteredElement(defaultTag: string) {\n const Component = React.forwardRef<HTMLElement, any>(\n ({ children, elementType, ...props }, ref) => {\n const Tag = elementType || defaultTag;\n const htmlProps: Record<string, unknown> = {};\n for (const key of Object.keys(props)) {\n if (!NON_HTML_PROPS.has(key)) {\n htmlProps[key] = props[key];\n }\n }\n return React.createElement(Tag, { ref, ...htmlProps }, children);\n }\n );\n Component.displayName = `Filtered(${defaultTag})`;\n return Component;\n}\n","import React from \"react\";\nimport styled, { keyframes } from \"styled-components\";\nimport type { SpinnerProps } from \"@xsolla/xui-primitives-core\";\nimport { createFilteredElement } from \"./filterDOMProps\";\n\nconst rotate = keyframes`\n from {\n transform: rotate(0deg);\n }\n to {\n transform: rotate(360deg);\n }\n`;\n\nconst FilteredDiv = createFilteredElement(\"div\");\n\nconst StyledSpinner = styled(FilteredDiv)<SpinnerProps>`\n width: ${(props) =>\n typeof props.size === \"number\" ? `${props.size}px` : props.size || \"24px\"};\n height: ${(props) =>\n typeof props.size === \"number\" ? `${props.size}px` : props.size || \"24px\"};\n border: ${(props) => props.strokeWidth || 2}px solid\n ${(props) => props.color || \"currentColor\"};\n border-bottom-color: transparent;\n border-radius: 50%;\n display: inline-block;\n box-sizing: border-box;\n animation: ${rotate} 1s linear infinite;\n`;\n\nexport const Spinner: React.FC<SpinnerProps> = ({\n role = \"status\",\n \"aria-label\": ariaLabel,\n \"aria-live\": ariaLive = \"polite\",\n \"aria-describedby\": ariaDescribedBy,\n testID,\n ...props\n}) => {\n return (\n <StyledSpinner\n role={role}\n aria-label={ariaLabel}\n aria-live={ariaLive}\n aria-describedby={ariaDescribedBy}\n data-testid={testID}\n {...props}\n />\n );\n};\n\nSpinner.displayName = \"Spinner\";\n","import type React from \"react\";\n// @ts-expect-error - this will be resolved at build time\nimport { Spinner as SpinnerPrimitive } from \"@xsolla/xui-primitives\";\nimport { useResolvedTheme, type ThemeOverrideProps } from \"@xsolla/xui-core\";\n\nexport interface SpinnerProps extends ThemeOverrideProps {\n /**\n * The size of the spinner.\n * @default 'md'\n */\n size?: \"xl\" | \"lg\" | \"md\" | \"sm\" | \"xs\";\n /**\n * The color of the spinner.\n * If not provided, it will use the default text color from the theme.\n */\n color?: string;\n /**\n * Accessible label for screen readers.\n * @default 'Loading'\n */\n \"aria-label\"?: string;\n /**\n * ID of the element being loaded (for aria-describedby on the loading container).\n */\n \"aria-describedby\"?: string;\n /**\n * Test ID for testing frameworks.\n */\n testID?: string;\n}\n\n/**\n * Spinner - An accessible loading indicator component\n *\n * Displays a spinning animation to indicate loading state.\n *\n * ## Accessibility Features\n *\n * - **role=\"status\"**: Announces to screen readers that this is a status indicator\n * - **aria-live=\"polite\"**: Screen readers will announce when the spinner appears\n * - **aria-label**: Provides accessible name for the spinner (defaults to \"Loading\")\n *\n * ## Sizes\n *\n * - xl: 96px\n * - l: 48px\n * - m: 24px (default)\n * - s: 16px\n * - xs: 8px\n */\nexport const Spinner: React.FC<SpinnerProps> = ({\n size = \"md\",\n color,\n \"aria-label\": ariaLabel = \"Loading\",\n \"aria-describedby\": ariaDescribedBy,\n testID,\n themeMode,\n themeProductContext,\n}) => {\n const { theme } = useResolvedTheme({ themeMode, themeProductContext });\n\n const sizeConfig = theme.sizing.spinner(size);\n const defaultColor = theme.colors.content.primary;\n\n return (\n <SpinnerPrimitive\n size={sizeConfig.size}\n strokeWidth={sizeConfig.strokeWidth}\n color={color || defaultColor}\n role=\"status\"\n aria-live=\"polite\"\n aria-label={ariaLabel}\n aria-describedby={ariaDescribedBy}\n testID={testID}\n />\n );\n};\n\nSpinner.displayName = \"Spinner\";\n"],"mappings":"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","names":["Spinner","React","styled","import_jsx_runtime","Spinner"]}
|
package/web/index.mjs
CHANGED
|
@@ -1,3 +1,107 @@
|
|
|
1
|
+
// ../primitives-web/src/filterDOMProps.ts
|
|
2
|
+
import React from "react";
|
|
3
|
+
var NON_HTML_PROPS = /* @__PURE__ */ new Set([
|
|
4
|
+
// BoxProps — layout & styling
|
|
5
|
+
"backgroundColor",
|
|
6
|
+
"borderColor",
|
|
7
|
+
"borderWidth",
|
|
8
|
+
"borderBottomWidth",
|
|
9
|
+
"borderBottomColor",
|
|
10
|
+
"borderTopWidth",
|
|
11
|
+
"borderTopColor",
|
|
12
|
+
"borderLeftWidth",
|
|
13
|
+
"borderLeftColor",
|
|
14
|
+
"borderRightWidth",
|
|
15
|
+
"borderRightColor",
|
|
16
|
+
"borderRadius",
|
|
17
|
+
"borderStyle",
|
|
18
|
+
"flexDirection",
|
|
19
|
+
"flexWrap",
|
|
20
|
+
"alignItems",
|
|
21
|
+
"justifyContent",
|
|
22
|
+
"alignSelf",
|
|
23
|
+
"flex",
|
|
24
|
+
"flexShrink",
|
|
25
|
+
"gap",
|
|
26
|
+
"position",
|
|
27
|
+
"top",
|
|
28
|
+
"bottom",
|
|
29
|
+
"left",
|
|
30
|
+
"right",
|
|
31
|
+
"outline",
|
|
32
|
+
"overflow",
|
|
33
|
+
"overflowX",
|
|
34
|
+
"overflowY",
|
|
35
|
+
"zIndex",
|
|
36
|
+
"cursor",
|
|
37
|
+
"padding",
|
|
38
|
+
"paddingHorizontal",
|
|
39
|
+
"paddingVertical",
|
|
40
|
+
"paddingTop",
|
|
41
|
+
"paddingBottom",
|
|
42
|
+
"paddingLeft",
|
|
43
|
+
"paddingRight",
|
|
44
|
+
"margin",
|
|
45
|
+
"marginTop",
|
|
46
|
+
"marginBottom",
|
|
47
|
+
"marginLeft",
|
|
48
|
+
"marginRight",
|
|
49
|
+
"minWidth",
|
|
50
|
+
"minHeight",
|
|
51
|
+
"maxWidth",
|
|
52
|
+
"maxHeight",
|
|
53
|
+
"hoverStyle",
|
|
54
|
+
"pressStyle",
|
|
55
|
+
"focusStyle",
|
|
56
|
+
"outlineColor",
|
|
57
|
+
"outlineWidth",
|
|
58
|
+
"outlineOffset",
|
|
59
|
+
"outlineStyle",
|
|
60
|
+
// BoxProps — RN-only
|
|
61
|
+
"onPress",
|
|
62
|
+
"onLayout",
|
|
63
|
+
"onMoveShouldSetResponder",
|
|
64
|
+
"onResponderGrant",
|
|
65
|
+
"onResponderMove",
|
|
66
|
+
"onResponderRelease",
|
|
67
|
+
"onResponderTerminate",
|
|
68
|
+
"testID",
|
|
69
|
+
// Box — custom element type
|
|
70
|
+
"elementType",
|
|
71
|
+
// TextProps
|
|
72
|
+
"fontSize",
|
|
73
|
+
"fontWeight",
|
|
74
|
+
"fontFamily",
|
|
75
|
+
"lineHeight",
|
|
76
|
+
"whiteSpace",
|
|
77
|
+
"textAlign",
|
|
78
|
+
"textDecoration",
|
|
79
|
+
"numberOfLines",
|
|
80
|
+
"letterSpacing",
|
|
81
|
+
"textTransform",
|
|
82
|
+
// SpinnerProps
|
|
83
|
+
"strokeWidth",
|
|
84
|
+
// DividerProps
|
|
85
|
+
"vertical",
|
|
86
|
+
"dashStroke"
|
|
87
|
+
]);
|
|
88
|
+
function createFilteredElement(defaultTag) {
|
|
89
|
+
const Component = React.forwardRef(
|
|
90
|
+
({ children, elementType, ...props }, ref) => {
|
|
91
|
+
const Tag = elementType || defaultTag;
|
|
92
|
+
const htmlProps = {};
|
|
93
|
+
for (const key of Object.keys(props)) {
|
|
94
|
+
if (!NON_HTML_PROPS.has(key)) {
|
|
95
|
+
htmlProps[key] = props[key];
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return React.createElement(Tag, { ref, ...htmlProps }, children);
|
|
99
|
+
}
|
|
100
|
+
);
|
|
101
|
+
Component.displayName = `Filtered(${defaultTag})`;
|
|
102
|
+
return Component;
|
|
103
|
+
}
|
|
104
|
+
|
|
1
105
|
// ../primitives-web/src/Spinner.tsx
|
|
2
106
|
import styled, { keyframes } from "styled-components";
|
|
3
107
|
import { jsx } from "react/jsx-runtime";
|
|
@@ -9,7 +113,8 @@ var rotate = keyframes`
|
|
|
9
113
|
transform: rotate(360deg);
|
|
10
114
|
}
|
|
11
115
|
`;
|
|
12
|
-
var
|
|
116
|
+
var FilteredDiv = createFilteredElement("div");
|
|
117
|
+
var StyledSpinner = styled(FilteredDiv)`
|
|
13
118
|
width: ${(props) => typeof props.size === "number" ? `${props.size}px` : props.size || "24px"};
|
|
14
119
|
height: ${(props) => typeof props.size === "number" ? `${props.size}px` : props.size || "24px"};
|
|
15
120
|
border: ${(props) => props.strokeWidth || 2}px solid
|
package/web/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../primitives-web/src/Spinner.tsx","../../src/Spinner.tsx"],"sourcesContent":["import React from \"react\";\nimport styled, { keyframes } from \"styled-components\";\nimport type { SpinnerProps } from \"@xsolla/xui-primitives-core\";\n\nconst rotate = keyframes`\n from {\n transform: rotate(0deg);\n }\n to {\n transform: rotate(360deg);\n }\n`;\n\nconst StyledSpinner = styled
|
|
1
|
+
{"version":3,"sources":["../../../primitives-web/src/filterDOMProps.ts","../../../primitives-web/src/Spinner.tsx","../../src/Spinner.tsx"],"sourcesContent":["import React from \"react\";\n\n// Props from BoxProps, TextProps, SpinnerProps, IconProps, DividerProps\n// that are NOT valid HTML attributes and must not reach the DOM.\nexport const NON_HTML_PROPS = new Set([\n // BoxProps — layout & styling\n \"backgroundColor\",\n \"borderColor\",\n \"borderWidth\",\n \"borderBottomWidth\",\n \"borderBottomColor\",\n \"borderTopWidth\",\n \"borderTopColor\",\n \"borderLeftWidth\",\n \"borderLeftColor\",\n \"borderRightWidth\",\n \"borderRightColor\",\n \"borderRadius\",\n \"borderStyle\",\n \"flexDirection\",\n \"flexWrap\",\n \"alignItems\",\n \"justifyContent\",\n \"alignSelf\",\n \"flex\",\n \"flexShrink\",\n \"gap\",\n \"position\",\n \"top\",\n \"bottom\",\n \"left\",\n \"right\",\n \"outline\",\n \"overflow\",\n \"overflowX\",\n \"overflowY\",\n \"zIndex\",\n \"cursor\",\n \"padding\",\n \"paddingHorizontal\",\n \"paddingVertical\",\n \"paddingTop\",\n \"paddingBottom\",\n \"paddingLeft\",\n \"paddingRight\",\n \"margin\",\n \"marginTop\",\n \"marginBottom\",\n \"marginLeft\",\n \"marginRight\",\n \"minWidth\",\n \"minHeight\",\n \"maxWidth\",\n \"maxHeight\",\n \"hoverStyle\",\n \"pressStyle\",\n \"focusStyle\",\n \"outlineColor\",\n \"outlineWidth\",\n \"outlineOffset\",\n \"outlineStyle\",\n // BoxProps — RN-only\n \"onPress\",\n \"onLayout\",\n \"onMoveShouldSetResponder\",\n \"onResponderGrant\",\n \"onResponderMove\",\n \"onResponderRelease\",\n \"onResponderTerminate\",\n \"testID\",\n // Box — custom element type\n \"elementType\",\n // TextProps\n \"fontSize\",\n \"fontWeight\",\n \"fontFamily\",\n \"lineHeight\",\n \"whiteSpace\",\n \"textAlign\",\n \"textDecoration\",\n \"numberOfLines\",\n \"letterSpacing\",\n \"textTransform\",\n // SpinnerProps\n \"strokeWidth\",\n // DividerProps\n \"vertical\",\n \"dashStroke\",\n]);\n\n/**\n * Creates a React component that renders the given HTML tag\n * but filters out non-HTML props before they reach the DOM.\n *\n * Usage: `const FilteredDiv = createFilteredElement(\"div\");`\n * Then: `const StyledBox = styled(FilteredDiv)<BoxProps>\\`...\\`;`\n *\n * styled-components can still read ALL props for CSS interpolation,\n * but only valid HTML attributes are forwarded to the DOM element.\n */\nexport function createFilteredElement(defaultTag: string) {\n const Component = React.forwardRef<HTMLElement, any>(\n ({ children, elementType, ...props }, ref) => {\n const Tag = elementType || defaultTag;\n const htmlProps: Record<string, unknown> = {};\n for (const key of Object.keys(props)) {\n if (!NON_HTML_PROPS.has(key)) {\n htmlProps[key] = props[key];\n }\n }\n return React.createElement(Tag, { ref, ...htmlProps }, children);\n }\n );\n Component.displayName = `Filtered(${defaultTag})`;\n return Component;\n}\n","import React from \"react\";\nimport styled, { keyframes } from \"styled-components\";\nimport type { SpinnerProps } from \"@xsolla/xui-primitives-core\";\nimport { createFilteredElement } from \"./filterDOMProps\";\n\nconst rotate = keyframes`\n from {\n transform: rotate(0deg);\n }\n to {\n transform: rotate(360deg);\n }\n`;\n\nconst FilteredDiv = createFilteredElement(\"div\");\n\nconst StyledSpinner = styled(FilteredDiv)<SpinnerProps>`\n width: ${(props) =>\n typeof props.size === \"number\" ? `${props.size}px` : props.size || \"24px\"};\n height: ${(props) =>\n typeof props.size === \"number\" ? `${props.size}px` : props.size || \"24px\"};\n border: ${(props) => props.strokeWidth || 2}px solid\n ${(props) => props.color || \"currentColor\"};\n border-bottom-color: transparent;\n border-radius: 50%;\n display: inline-block;\n box-sizing: border-box;\n animation: ${rotate} 1s linear infinite;\n`;\n\nexport const Spinner: React.FC<SpinnerProps> = ({\n role = \"status\",\n \"aria-label\": ariaLabel,\n \"aria-live\": ariaLive = \"polite\",\n \"aria-describedby\": ariaDescribedBy,\n testID,\n ...props\n}) => {\n return (\n <StyledSpinner\n role={role}\n aria-label={ariaLabel}\n aria-live={ariaLive}\n aria-describedby={ariaDescribedBy}\n data-testid={testID}\n {...props}\n />\n );\n};\n\nSpinner.displayName = \"Spinner\";\n","import type React from \"react\";\n// @ts-expect-error - this will be resolved at build time\nimport { Spinner as SpinnerPrimitive } from \"@xsolla/xui-primitives\";\nimport { useResolvedTheme, type ThemeOverrideProps } from \"@xsolla/xui-core\";\n\nexport interface SpinnerProps extends ThemeOverrideProps {\n /**\n * The size of the spinner.\n * @default 'md'\n */\n size?: \"xl\" | \"lg\" | \"md\" | \"sm\" | \"xs\";\n /**\n * The color of the spinner.\n * If not provided, it will use the default text color from the theme.\n */\n color?: string;\n /**\n * Accessible label for screen readers.\n * @default 'Loading'\n */\n \"aria-label\"?: string;\n /**\n * ID of the element being loaded (for aria-describedby on the loading container).\n */\n \"aria-describedby\"?: string;\n /**\n * Test ID for testing frameworks.\n */\n testID?: string;\n}\n\n/**\n * Spinner - An accessible loading indicator component\n *\n * Displays a spinning animation to indicate loading state.\n *\n * ## Accessibility Features\n *\n * - **role=\"status\"**: Announces to screen readers that this is a status indicator\n * - **aria-live=\"polite\"**: Screen readers will announce when the spinner appears\n * - **aria-label**: Provides accessible name for the spinner (defaults to \"Loading\")\n *\n * ## Sizes\n *\n * - xl: 96px\n * - l: 48px\n * - m: 24px (default)\n * - s: 16px\n * - xs: 8px\n */\nexport const Spinner: React.FC<SpinnerProps> = ({\n size = \"md\",\n color,\n \"aria-label\": ariaLabel = \"Loading\",\n \"aria-describedby\": ariaDescribedBy,\n testID,\n themeMode,\n themeProductContext,\n}) => {\n const { theme } = useResolvedTheme({ themeMode, themeProductContext });\n\n const sizeConfig = theme.sizing.spinner(size);\n const defaultColor = theme.colors.content.primary;\n\n return (\n <SpinnerPrimitive\n size={sizeConfig.size}\n strokeWidth={sizeConfig.strokeWidth}\n color={color || defaultColor}\n role=\"status\"\n aria-live=\"polite\"\n aria-label={ariaLabel}\n aria-describedby={ariaDescribedBy}\n testID={testID}\n />\n );\n};\n\nSpinner.displayName = \"Spinner\";\n"],"mappings":"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","names":["jsx","Spinner"]}
|