@sproutsocial/seeds-react-loader-button 1.0.34 → 1.0.45
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/.turbo/turbo-build.log +10 -10
- package/CHANGELOG.md +94 -0
- package/dist/esm/index.js +83 -10
- package/dist/esm/index.js.map +1 -1
- package/dist/index.d.mts +6 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.js +84 -11
- package/dist/index.js.map +1 -1
- package/package.json +6 -6
- package/src/LoaderButton.stories.tsx +32 -0
- package/src/LoaderButton.tsx +9 -51
- package/src/LoaderButtonHybrid.tsx +78 -0
- package/src/LoaderButtonTailwind.tsx +71 -0
- package/src/__tests__/tailwind.test.tsx +30 -0
- package/src/loader-button.css +52 -0
package/.turbo/turbo-build.log
CHANGED
|
@@ -8,14 +8,14 @@ $ tsup --dts
|
|
|
8
8
|
[34mCLI[39m Cleaning output folder
|
|
9
9
|
[34mCJS[39m Build start
|
|
10
10
|
[34mESM[39m Build start
|
|
11
|
-
[32mCJS[39m [1mdist/index.js [22m[
|
|
12
|
-
[32mCJS[39m [1mdist/index.js.map [22m[
|
|
13
|
-
[32mCJS[39m ⚡️ Build success in
|
|
14
|
-
[32mESM[39m [1mdist/esm/index.js [22m[
|
|
15
|
-
[32mESM[39m [1mdist/esm/index.js.map [22m[
|
|
16
|
-
[32mESM[39m ⚡️ Build success in
|
|
11
|
+
[32mCJS[39m [1mdist/index.js [22m[32m6.19 KB[39m
|
|
12
|
+
[32mCJS[39m [1mdist/index.js.map [22m[32m7.61 KB[39m
|
|
13
|
+
[32mCJS[39m ⚡️ Build success in 18ms
|
|
14
|
+
[32mESM[39m [1mdist/esm/index.js [22m[32m3.72 KB[39m
|
|
15
|
+
[32mESM[39m [1mdist/esm/index.js.map [22m[32m7.41 KB[39m
|
|
16
|
+
[32mESM[39m ⚡️ Build success in 18ms
|
|
17
17
|
[34mDTS[39m Build start
|
|
18
|
-
[32mDTS[39m ⚡️ Build success in
|
|
19
|
-
[32mDTS[39m [1mdist/index.d.ts [22m[
|
|
20
|
-
[32mDTS[39m [1mdist/index.d.mts [22m[
|
|
21
|
-
Done in 6.
|
|
18
|
+
[32mDTS[39m ⚡️ Build success in 4778ms
|
|
19
|
+
[32mDTS[39m [1mdist/index.d.ts [22m[32m619.00 B[39m
|
|
20
|
+
[32mDTS[39m [1mdist/index.d.mts [22m[32m619.00 B[39m
|
|
21
|
+
Done in 6.46s.
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,99 @@
|
|
|
1
1
|
# @sproutsocial/seeds-react-loader-button
|
|
2
2
|
|
|
3
|
+
## 1.0.45
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- @sproutsocial/seeds-react-button@2.2.1
|
|
8
|
+
|
|
9
|
+
## 1.0.44
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- Updated dependencies [8945c86]
|
|
14
|
+
- @sproutsocial/seeds-react-loader@1.0.22
|
|
15
|
+
|
|
16
|
+
## 1.0.43
|
|
17
|
+
|
|
18
|
+
### Patch Changes
|
|
19
|
+
|
|
20
|
+
- edc1819: Migrate link, text, banner, loader-button, and content-header to the Tailwind hybrid pattern (mirroring seeds-react-button). Each component gains a pure CSS-class `*Tailwind` implementation, a `*Hybrid` router that falls back to styled-components when system/styled props are present, and a component-scoped CSS file of `seeds-*` classes built on `var(--…)` tokens. Component CSS is wrapped in `@layer components` so consumer Tailwind utility overrides win the cascade, and the per-component CSS import is dropped from the `*Tailwind` files since the CSS is aggregated into `@sproutsocial/racine/css/components` at build time. Legacy `styles.ts` paths are unchanged.
|
|
21
|
+
|
|
22
|
+
## 1.0.42
|
|
23
|
+
|
|
24
|
+
### Patch Changes
|
|
25
|
+
|
|
26
|
+
- Updated dependencies [456a20f]
|
|
27
|
+
- Updated dependencies [5892f44]
|
|
28
|
+
- @sproutsocial/seeds-react-button@2.2.0
|
|
29
|
+
- @sproutsocial/seeds-react-system-props@3.1.1
|
|
30
|
+
- @sproutsocial/seeds-react-box@1.1.21
|
|
31
|
+
- @sproutsocial/seeds-react-loader@1.0.21
|
|
32
|
+
|
|
33
|
+
## 1.0.41
|
|
34
|
+
|
|
35
|
+
### Patch Changes
|
|
36
|
+
|
|
37
|
+
- Updated dependencies [5114a32]
|
|
38
|
+
- Updated dependencies [a0fe3d3]
|
|
39
|
+
- @sproutsocial/seeds-react-theme@4.1.0
|
|
40
|
+
- @sproutsocial/seeds-react-button@2.1.3
|
|
41
|
+
- @sproutsocial/seeds-react-box@1.1.20
|
|
42
|
+
- @sproutsocial/seeds-react-loader@1.0.20
|
|
43
|
+
|
|
44
|
+
## 1.0.40
|
|
45
|
+
|
|
46
|
+
### Patch Changes
|
|
47
|
+
|
|
48
|
+
- Updated dependencies [cb27f07]
|
|
49
|
+
- @sproutsocial/seeds-react-button@2.1.2
|
|
50
|
+
|
|
51
|
+
## 1.0.39
|
|
52
|
+
|
|
53
|
+
### Patch Changes
|
|
54
|
+
|
|
55
|
+
- Updated dependencies [40d2dfe]
|
|
56
|
+
- @sproutsocial/seeds-react-button@2.1.1
|
|
57
|
+
|
|
58
|
+
## 1.0.38
|
|
59
|
+
|
|
60
|
+
### Patch Changes
|
|
61
|
+
|
|
62
|
+
- Updated dependencies [132ef9d]
|
|
63
|
+
- Updated dependencies [132ef9d]
|
|
64
|
+
- Updated dependencies [132ef9d]
|
|
65
|
+
- @sproutsocial/seeds-react-button@2.1.0
|
|
66
|
+
- @sproutsocial/seeds-react-theme@4.0.0
|
|
67
|
+
- @sproutsocial/seeds-react-system-props@3.1.0
|
|
68
|
+
- @sproutsocial/seeds-react-box@1.1.19
|
|
69
|
+
- @sproutsocial/seeds-react-loader@1.0.19
|
|
70
|
+
|
|
71
|
+
## 1.0.37
|
|
72
|
+
|
|
73
|
+
### Patch Changes
|
|
74
|
+
|
|
75
|
+
- @sproutsocial/seeds-react-button@2.0.8
|
|
76
|
+
|
|
77
|
+
## 1.0.36
|
|
78
|
+
|
|
79
|
+
### Patch Changes
|
|
80
|
+
|
|
81
|
+
- Updated dependencies [47c62b3]
|
|
82
|
+
- @sproutsocial/seeds-react-theme@3.7.1
|
|
83
|
+
- @sproutsocial/seeds-react-box@1.1.18
|
|
84
|
+
- @sproutsocial/seeds-react-loader@1.0.18
|
|
85
|
+
- @sproutsocial/seeds-react-button@2.0.7
|
|
86
|
+
|
|
87
|
+
## 1.0.35
|
|
88
|
+
|
|
89
|
+
### Patch Changes
|
|
90
|
+
|
|
91
|
+
- Updated dependencies [06da9c2]
|
|
92
|
+
- @sproutsocial/seeds-react-theme@3.7.0
|
|
93
|
+
- @sproutsocial/seeds-react-box@1.1.17
|
|
94
|
+
- @sproutsocial/seeds-react-loader@1.0.17
|
|
95
|
+
- @sproutsocial/seeds-react-button@2.0.6
|
|
96
|
+
|
|
3
97
|
## 1.0.34
|
|
4
98
|
|
|
5
99
|
### Patch Changes
|
package/dist/esm/index.js
CHANGED
|
@@ -1,11 +1,66 @@
|
|
|
1
1
|
// src/LoaderButton.tsx
|
|
2
2
|
import "react";
|
|
3
|
+
|
|
4
|
+
// src/LoaderButtonHybrid.tsx
|
|
5
|
+
import "react";
|
|
3
6
|
import styled from "styled-components";
|
|
7
|
+
import Box2 from "@sproutsocial/seeds-react-box";
|
|
8
|
+
import Button2 from "@sproutsocial/seeds-react-button";
|
|
9
|
+
import Loader2 from "@sproutsocial/seeds-react-loader";
|
|
10
|
+
|
|
11
|
+
// src/LoaderButtonTailwind.tsx
|
|
12
|
+
import "react";
|
|
4
13
|
import Box from "@sproutsocial/seeds-react-box";
|
|
5
14
|
import Button from "@sproutsocial/seeds-react-button";
|
|
6
15
|
import Loader from "@sproutsocial/seeds-react-loader";
|
|
7
16
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
8
|
-
|
|
17
|
+
function cn(...inputs) {
|
|
18
|
+
const classes = [];
|
|
19
|
+
for (const input of inputs) {
|
|
20
|
+
if (!input) continue;
|
|
21
|
+
if (typeof input === "string") {
|
|
22
|
+
classes.push(input);
|
|
23
|
+
} else if (typeof input === "object") {
|
|
24
|
+
for (const [key, value] of Object.entries(input)) {
|
|
25
|
+
if (value) {
|
|
26
|
+
classes.push(key);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return classes.join(" ");
|
|
32
|
+
}
|
|
33
|
+
var LoaderButtonTailwind = ({
|
|
34
|
+
isLoading = false,
|
|
35
|
+
disabled,
|
|
36
|
+
loaderLabel,
|
|
37
|
+
children,
|
|
38
|
+
appearance = "unstyled",
|
|
39
|
+
className,
|
|
40
|
+
...rest
|
|
41
|
+
}) => {
|
|
42
|
+
const isDisabled = disabled || isLoading;
|
|
43
|
+
const classes = cn({ "seeds-loader-btn-disabled": !!isDisabled }, className) || void 0;
|
|
44
|
+
return /* @__PURE__ */ jsx(
|
|
45
|
+
Button,
|
|
46
|
+
{
|
|
47
|
+
disabled: isDisabled,
|
|
48
|
+
appearance,
|
|
49
|
+
"data-qa-button-isloading": isLoading === true,
|
|
50
|
+
className: classes,
|
|
51
|
+
...rest,
|
|
52
|
+
children: /* @__PURE__ */ jsxs(Box, { position: "relative", children: [
|
|
53
|
+
/* @__PURE__ */ jsx(Box, { opacity: isLoading ? 0 : 1, "aria-hidden": isLoading, children }),
|
|
54
|
+
isLoading && /* @__PURE__ */ jsx(Box, { position: "absolute", top: -2, left: 0, right: 0, bottom: 0, children: /* @__PURE__ */ jsx(Loader, { text: loaderLabel, size: "small", delay: false }) })
|
|
55
|
+
] })
|
|
56
|
+
}
|
|
57
|
+
);
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
// src/LoaderButtonHybrid.tsx
|
|
61
|
+
import { hasStyledProps } from "@sproutsocial/seeds-react-system-props";
|
|
62
|
+
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
63
|
+
var StyledLoaderButton = styled(Button2)`
|
|
9
64
|
background-color: ${({ theme, appearance, disabled }) => {
|
|
10
65
|
const buttonBackgroundColor = theme.colors.button[appearance]?.background?.base;
|
|
11
66
|
const isBackgroundColorTransparent = buttonBackgroundColor === "transparent";
|
|
@@ -13,7 +68,7 @@ var StyledLoaderButton = styled(Button)`
|
|
|
13
68
|
}};
|
|
14
69
|
${({ disabled }) => disabled && "opacity: 1;"}
|
|
15
70
|
`;
|
|
16
|
-
var
|
|
71
|
+
var LoaderButtonHybrid = ({
|
|
17
72
|
isLoading = false,
|
|
18
73
|
disabled,
|
|
19
74
|
loaderLabel,
|
|
@@ -21,20 +76,38 @@ var LoaderButton = ({
|
|
|
21
76
|
appearance = "unstyled",
|
|
22
77
|
...rest
|
|
23
78
|
}) => {
|
|
24
|
-
|
|
25
|
-
|
|
79
|
+
if (hasStyledProps(rest)) {
|
|
80
|
+
return /* @__PURE__ */ jsx2(
|
|
81
|
+
StyledLoaderButton,
|
|
82
|
+
{
|
|
83
|
+
disabled: disabled || isLoading,
|
|
84
|
+
appearance,
|
|
85
|
+
"data-qa-button-isloading": isLoading === true,
|
|
86
|
+
...rest,
|
|
87
|
+
children: /* @__PURE__ */ jsxs2(Box2, { position: "relative", children: [
|
|
88
|
+
/* @__PURE__ */ jsx2(Box2, { opacity: isLoading ? 0 : 1, "aria-hidden": isLoading, children }),
|
|
89
|
+
isLoading && /* @__PURE__ */ jsx2(Box2, { position: "absolute", top: -2, left: 0, right: 0, bottom: 0, children: /* @__PURE__ */ jsx2(Loader2, { text: loaderLabel, size: "small", delay: false }) })
|
|
90
|
+
] })
|
|
91
|
+
}
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
return /* @__PURE__ */ jsx2(
|
|
95
|
+
LoaderButtonTailwind,
|
|
26
96
|
{
|
|
27
|
-
|
|
97
|
+
isLoading,
|
|
98
|
+
disabled,
|
|
99
|
+
loaderLabel,
|
|
28
100
|
appearance,
|
|
29
|
-
"data-qa-button-isloading": isLoading === true,
|
|
30
101
|
...rest,
|
|
31
|
-
children
|
|
32
|
-
/* @__PURE__ */ jsx(Box, { opacity: isLoading ? 0 : 1, "aria-hidden": isLoading, children }),
|
|
33
|
-
isLoading && /* @__PURE__ */ jsx(Box, { position: "absolute", top: -2, left: 0, right: 0, bottom: 0, children: /* @__PURE__ */ jsx(Loader, { text: loaderLabel, size: "small", delay: false }) })
|
|
34
|
-
] })
|
|
102
|
+
children
|
|
35
103
|
}
|
|
36
104
|
);
|
|
37
105
|
};
|
|
106
|
+
var LoaderButtonHybrid_default = LoaderButtonHybrid;
|
|
107
|
+
|
|
108
|
+
// src/LoaderButton.tsx
|
|
109
|
+
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
110
|
+
var LoaderButton = (props) => /* @__PURE__ */ jsx3(LoaderButtonHybrid_default, { ...props });
|
|
38
111
|
var LoaderButton_default = LoaderButton;
|
|
39
112
|
|
|
40
113
|
// src/index.ts
|
package/dist/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/LoaderButton.tsx","../../src/index.ts"],"sourcesContent":["import * as React from \"react\";\nimport styled from \"styled-components\";\nimport Box from \"@sproutsocial/seeds-react-box\";\nimport Button from \"@sproutsocial/seeds-react-button\";\nimport Loader from \"@sproutsocial/seeds-react-loader\";\nimport type { TypeLoaderButtonProps } from \"./LoaderButtonTypes\";\n\nconst StyledLoaderButton = styled(Button)`\n background-color: ${({ theme, appearance, disabled }) => {\n const buttonBackgroundColor =\n theme.colors.button[appearance as keyof typeof theme.colors.button]\n ?.background?.base;\n\n const isBackgroundColorTransparent =\n buttonBackgroundColor === \"transparent\";\n\n // If the button is disabled we want to check what the buttonBackgroundColor is, if it is transparent we want to return transparent, otherwise we want to return the buttonBackgroundColor with an opacity of 0.4. If the button is not disabled we want to return the buttonBackgroundColor.\n return disabled\n ? isBackgroundColorTransparent\n ? \"transparent\"\n : `${buttonBackgroundColor}66`\n : buttonBackgroundColor;\n }};\n ${({ disabled }) => disabled && \"opacity: 1;\"}\n`;\n\nexport const
|
|
1
|
+
{"version":3,"sources":["../../src/LoaderButton.tsx","../../src/LoaderButtonHybrid.tsx","../../src/LoaderButtonTailwind.tsx","../../src/index.ts"],"sourcesContent":["import * as React from \"react\";\nimport LoaderButtonHybrid from \"./LoaderButtonHybrid\";\nimport type { TypeLoaderButtonProps } from \"./LoaderButtonTypes\";\n\n/**\n * LoaderButton component. Automatically routes between the Tailwind\n * implementation (preferred) and the styled-components implementation (for\n * consumers using system props or a styled() extension).\n */\nexport const LoaderButton = (props: TypeLoaderButtonProps) => (\n <LoaderButtonHybrid {...props} />\n);\n\nexport default LoaderButton;\n","/**\n * Hybrid LoaderButton Component\n * Automatically chooses between Tailwind and styled-components based on props.\n */\n\nimport * as React from \"react\";\nimport styled from \"styled-components\";\nimport Box from \"@sproutsocial/seeds-react-box\";\nimport Button from \"@sproutsocial/seeds-react-button\";\nimport Loader from \"@sproutsocial/seeds-react-loader\";\nimport { LoaderButtonTailwind } from \"./LoaderButtonTailwind\";\nimport { hasStyledProps } from \"@sproutsocial/seeds-react-system-props\";\nimport type { TypeLoaderButtonProps } from \"./LoaderButtonTypes\";\n\nconst StyledLoaderButton = styled(Button)`\n background-color: ${({ theme, appearance, disabled }) => {\n const buttonBackgroundColor =\n theme.colors.button[appearance as keyof typeof theme.colors.button]\n ?.background?.base;\n\n const isBackgroundColorTransparent =\n buttonBackgroundColor === \"transparent\";\n\n // If the button is disabled we want to check what the buttonBackgroundColor is, if it is transparent we want to return transparent, otherwise we want to return the buttonBackgroundColor with an opacity of 0.4. If the button is not disabled we want to return the buttonBackgroundColor.\n return disabled\n ? isBackgroundColorTransparent\n ? \"transparent\"\n : `${buttonBackgroundColor}66`\n : buttonBackgroundColor;\n }};\n ${({ disabled }) => disabled && \"opacity: 1;\"}\n`;\n\nexport const LoaderButtonHybrid = ({\n isLoading = false,\n disabled,\n loaderLabel,\n children,\n appearance = \"unstyled\",\n ...rest\n}: TypeLoaderButtonProps) => {\n if (hasStyledProps(rest)) {\n return (\n <StyledLoaderButton\n disabled={disabled || isLoading}\n appearance={appearance}\n data-qa-button-isloading={isLoading === true}\n {...rest}\n >\n <Box position=\"relative\">\n <Box opacity={isLoading ? 0 : 1} aria-hidden={isLoading}>\n {children}\n </Box>\n {isLoading && (\n <Box position=\"absolute\" top={-2} left={0} right={0} bottom={0}>\n <Loader text={loaderLabel} size=\"small\" delay={false} />\n </Box>\n )}\n </Box>\n </StyledLoaderButton>\n );\n }\n\n // Use Tailwind version (preferred - better performance)\n return (\n <LoaderButtonTailwind\n isLoading={isLoading}\n disabled={disabled}\n loaderLabel={loaderLabel}\n appearance={appearance}\n {...rest}\n >\n {children}\n </LoaderButtonTailwind>\n );\n};\n\nexport default LoaderButtonHybrid;\n","/**\n * Tailwind CSS implementation of LoaderButton component\n * Renders Button with its appearance classes plus a disabled-dimming layer\n * from loader-button.css.\n */\n\nimport * as React from \"react\";\nimport Box from \"@sproutsocial/seeds-react-box\";\nimport Button from \"@sproutsocial/seeds-react-button\";\nimport Loader from \"@sproutsocial/seeds-react-loader\";\nimport type { TypeLoaderButtonProps } from \"./LoaderButtonTypes\";\n\n// Utility for merging class names properly\nfunction cn(\n ...inputs: (string | undefined | null | false | Record<string, boolean>)[]\n): string {\n const classes: string[] = [];\n\n for (const input of inputs) {\n if (!input) continue;\n\n if (typeof input === \"string\") {\n classes.push(input);\n } else if (typeof input === \"object\") {\n for (const [key, value] of Object.entries(input)) {\n if (value) {\n classes.push(key);\n }\n }\n }\n }\n\n return classes.join(\" \");\n}\n\nexport const LoaderButtonTailwind = ({\n isLoading = false,\n disabled,\n loaderLabel,\n children,\n appearance = \"unstyled\",\n className,\n ...rest\n}: TypeLoaderButtonProps) => {\n const isDisabled = disabled || isLoading;\n const classes =\n cn({ \"seeds-loader-btn-disabled\": !!isDisabled }, className) || undefined;\n\n return (\n <Button\n disabled={isDisabled}\n appearance={appearance}\n data-qa-button-isloading={isLoading === true}\n className={classes}\n {...rest}\n >\n <Box position=\"relative\">\n <Box opacity={isLoading ? 0 : 1} aria-hidden={isLoading}>\n {children}\n </Box>\n {isLoading && (\n <Box position=\"absolute\" top={-2} left={0} right={0} bottom={0}>\n <Loader text={loaderLabel} size=\"small\" delay={false} />\n </Box>\n )}\n </Box>\n </Button>\n );\n};\n\nexport default LoaderButtonTailwind;\n","import LoaderButton from \"./LoaderButton\";\n\nexport default LoaderButton;\nexport { LoaderButton };\nexport * from \"./LoaderButtonTypes\";\n"],"mappings":"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","names":["Box","Button","Loader","jsx","jsxs","Button","Box","Loader","jsx"]}
|
package/dist/index.d.mts
CHANGED
|
@@ -6,6 +6,11 @@ interface TypeLoaderButtonProps extends TypeButtonProps {
|
|
|
6
6
|
loaderLabel: string;
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
/**
|
|
10
|
+
* LoaderButton component. Automatically routes between the Tailwind
|
|
11
|
+
* implementation (preferred) and the styled-components implementation (for
|
|
12
|
+
* consumers using system props or a styled() extension).
|
|
13
|
+
*/
|
|
14
|
+
declare const LoaderButton: (props: TypeLoaderButtonProps) => react_jsx_runtime.JSX.Element;
|
|
10
15
|
|
|
11
16
|
export { LoaderButton, type TypeLoaderButtonProps, LoaderButton as default };
|
package/dist/index.d.ts
CHANGED
|
@@ -6,6 +6,11 @@ interface TypeLoaderButtonProps extends TypeButtonProps {
|
|
|
6
6
|
loaderLabel: string;
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
/**
|
|
10
|
+
* LoaderButton component. Automatically routes between the Tailwind
|
|
11
|
+
* implementation (preferred) and the styled-components implementation (for
|
|
12
|
+
* consumers using system props or a styled() extension).
|
|
13
|
+
*/
|
|
14
|
+
declare const LoaderButton: (props: TypeLoaderButtonProps) => react_jsx_runtime.JSX.Element;
|
|
10
15
|
|
|
11
16
|
export { LoaderButton, type TypeLoaderButtonProps, LoaderButton as default };
|
package/dist/index.js
CHANGED
|
@@ -36,13 +36,68 @@ __export(index_exports, {
|
|
|
36
36
|
module.exports = __toCommonJS(index_exports);
|
|
37
37
|
|
|
38
38
|
// src/LoaderButton.tsx
|
|
39
|
-
var
|
|
39
|
+
var React3 = require("react");
|
|
40
|
+
|
|
41
|
+
// src/LoaderButtonHybrid.tsx
|
|
42
|
+
var React2 = require("react");
|
|
40
43
|
var import_styled_components = __toESM(require("styled-components"));
|
|
44
|
+
var import_seeds_react_box2 = __toESM(require("@sproutsocial/seeds-react-box"));
|
|
45
|
+
var import_seeds_react_button2 = __toESM(require("@sproutsocial/seeds-react-button"));
|
|
46
|
+
var import_seeds_react_loader2 = __toESM(require("@sproutsocial/seeds-react-loader"));
|
|
47
|
+
|
|
48
|
+
// src/LoaderButtonTailwind.tsx
|
|
49
|
+
var React = require("react");
|
|
41
50
|
var import_seeds_react_box = __toESM(require("@sproutsocial/seeds-react-box"));
|
|
42
51
|
var import_seeds_react_button = __toESM(require("@sproutsocial/seeds-react-button"));
|
|
43
52
|
var import_seeds_react_loader = __toESM(require("@sproutsocial/seeds-react-loader"));
|
|
44
53
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
45
|
-
|
|
54
|
+
function cn(...inputs) {
|
|
55
|
+
const classes = [];
|
|
56
|
+
for (const input of inputs) {
|
|
57
|
+
if (!input) continue;
|
|
58
|
+
if (typeof input === "string") {
|
|
59
|
+
classes.push(input);
|
|
60
|
+
} else if (typeof input === "object") {
|
|
61
|
+
for (const [key, value] of Object.entries(input)) {
|
|
62
|
+
if (value) {
|
|
63
|
+
classes.push(key);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return classes.join(" ");
|
|
69
|
+
}
|
|
70
|
+
var LoaderButtonTailwind = ({
|
|
71
|
+
isLoading = false,
|
|
72
|
+
disabled,
|
|
73
|
+
loaderLabel,
|
|
74
|
+
children,
|
|
75
|
+
appearance = "unstyled",
|
|
76
|
+
className,
|
|
77
|
+
...rest
|
|
78
|
+
}) => {
|
|
79
|
+
const isDisabled = disabled || isLoading;
|
|
80
|
+
const classes = cn({ "seeds-loader-btn-disabled": !!isDisabled }, className) || void 0;
|
|
81
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
82
|
+
import_seeds_react_button.default,
|
|
83
|
+
{
|
|
84
|
+
disabled: isDisabled,
|
|
85
|
+
appearance,
|
|
86
|
+
"data-qa-button-isloading": isLoading === true,
|
|
87
|
+
className: classes,
|
|
88
|
+
...rest,
|
|
89
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_seeds_react_box.default, { position: "relative", children: [
|
|
90
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_seeds_react_box.default, { opacity: isLoading ? 0 : 1, "aria-hidden": isLoading, children }),
|
|
91
|
+
isLoading && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_seeds_react_box.default, { position: "absolute", top: -2, left: 0, right: 0, bottom: 0, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_seeds_react_loader.default, { text: loaderLabel, size: "small", delay: false }) })
|
|
92
|
+
] })
|
|
93
|
+
}
|
|
94
|
+
);
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
// src/LoaderButtonHybrid.tsx
|
|
98
|
+
var import_seeds_react_system_props = require("@sproutsocial/seeds-react-system-props");
|
|
99
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
100
|
+
var StyledLoaderButton = (0, import_styled_components.default)(import_seeds_react_button2.default)`
|
|
46
101
|
background-color: ${({ theme, appearance, disabled }) => {
|
|
47
102
|
const buttonBackgroundColor = theme.colors.button[appearance]?.background?.base;
|
|
48
103
|
const isBackgroundColorTransparent = buttonBackgroundColor === "transparent";
|
|
@@ -50,7 +105,7 @@ var StyledLoaderButton = (0, import_styled_components.default)(import_seeds_reac
|
|
|
50
105
|
}};
|
|
51
106
|
${({ disabled }) => disabled && "opacity: 1;"}
|
|
52
107
|
`;
|
|
53
|
-
var
|
|
108
|
+
var LoaderButtonHybrid = ({
|
|
54
109
|
isLoading = false,
|
|
55
110
|
disabled,
|
|
56
111
|
loaderLabel,
|
|
@@ -58,20 +113,38 @@ var LoaderButton = ({
|
|
|
58
113
|
appearance = "unstyled",
|
|
59
114
|
...rest
|
|
60
115
|
}) => {
|
|
61
|
-
|
|
62
|
-
|
|
116
|
+
if ((0, import_seeds_react_system_props.hasStyledProps)(rest)) {
|
|
117
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
118
|
+
StyledLoaderButton,
|
|
119
|
+
{
|
|
120
|
+
disabled: disabled || isLoading,
|
|
121
|
+
appearance,
|
|
122
|
+
"data-qa-button-isloading": isLoading === true,
|
|
123
|
+
...rest,
|
|
124
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_seeds_react_box2.default, { position: "relative", children: [
|
|
125
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_seeds_react_box2.default, { opacity: isLoading ? 0 : 1, "aria-hidden": isLoading, children }),
|
|
126
|
+
isLoading && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_seeds_react_box2.default, { position: "absolute", top: -2, left: 0, right: 0, bottom: 0, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_seeds_react_loader2.default, { text: loaderLabel, size: "small", delay: false }) })
|
|
127
|
+
] })
|
|
128
|
+
}
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
132
|
+
LoaderButtonTailwind,
|
|
63
133
|
{
|
|
64
|
-
|
|
134
|
+
isLoading,
|
|
135
|
+
disabled,
|
|
136
|
+
loaderLabel,
|
|
65
137
|
appearance,
|
|
66
|
-
"data-qa-button-isloading": isLoading === true,
|
|
67
138
|
...rest,
|
|
68
|
-
children
|
|
69
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_seeds_react_box.default, { opacity: isLoading ? 0 : 1, "aria-hidden": isLoading, children }),
|
|
70
|
-
isLoading && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_seeds_react_box.default, { position: "absolute", top: -2, left: 0, right: 0, bottom: 0, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_seeds_react_loader.default, { text: loaderLabel, size: "small", delay: false }) })
|
|
71
|
-
] })
|
|
139
|
+
children
|
|
72
140
|
}
|
|
73
141
|
);
|
|
74
142
|
};
|
|
143
|
+
var LoaderButtonHybrid_default = LoaderButtonHybrid;
|
|
144
|
+
|
|
145
|
+
// src/LoaderButton.tsx
|
|
146
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
147
|
+
var LoaderButton = (props) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(LoaderButtonHybrid_default, { ...props });
|
|
75
148
|
var LoaderButton_default = LoaderButton;
|
|
76
149
|
|
|
77
150
|
// src/index.ts
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/LoaderButton.tsx"],"sourcesContent":["import LoaderButton from \"./LoaderButton\";\n\nexport default LoaderButton;\nexport { LoaderButton };\nexport * from \"./LoaderButtonTypes\";\n","import * as React from \"react\";\nimport styled from \"styled-components\";\nimport Box from \"@sproutsocial/seeds-react-box\";\nimport Button from \"@sproutsocial/seeds-react-button\";\nimport Loader from \"@sproutsocial/seeds-react-loader\";\nimport type { TypeLoaderButtonProps } from \"./LoaderButtonTypes\";\n\nconst StyledLoaderButton = styled(Button)`\n background-color: ${({ theme, appearance, disabled }) => {\n const buttonBackgroundColor =\n theme.colors.button[appearance as keyof typeof theme.colors.button]\n ?.background?.base;\n\n const isBackgroundColorTransparent =\n buttonBackgroundColor === \"transparent\";\n\n // If the button is disabled we want to check what the buttonBackgroundColor is, if it is transparent we want to return transparent, otherwise we want to return the buttonBackgroundColor with an opacity of 0.4. If the button is not disabled we want to return the buttonBackgroundColor.\n return disabled\n ? isBackgroundColorTransparent\n ? \"transparent\"\n : `${buttonBackgroundColor}66`\n : buttonBackgroundColor;\n }};\n ${({ disabled }) => disabled && \"opacity: 1;\"}\n`;\n\nexport const
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/LoaderButton.tsx","../src/LoaderButtonHybrid.tsx","../src/LoaderButtonTailwind.tsx"],"sourcesContent":["import LoaderButton from \"./LoaderButton\";\n\nexport default LoaderButton;\nexport { LoaderButton };\nexport * from \"./LoaderButtonTypes\";\n","import * as React from \"react\";\nimport LoaderButtonHybrid from \"./LoaderButtonHybrid\";\nimport type { TypeLoaderButtonProps } from \"./LoaderButtonTypes\";\n\n/**\n * LoaderButton component. Automatically routes between the Tailwind\n * implementation (preferred) and the styled-components implementation (for\n * consumers using system props or a styled() extension).\n */\nexport const LoaderButton = (props: TypeLoaderButtonProps) => (\n <LoaderButtonHybrid {...props} />\n);\n\nexport default LoaderButton;\n","/**\n * Hybrid LoaderButton Component\n * Automatically chooses between Tailwind and styled-components based on props.\n */\n\nimport * as React from \"react\";\nimport styled from \"styled-components\";\nimport Box from \"@sproutsocial/seeds-react-box\";\nimport Button from \"@sproutsocial/seeds-react-button\";\nimport Loader from \"@sproutsocial/seeds-react-loader\";\nimport { LoaderButtonTailwind } from \"./LoaderButtonTailwind\";\nimport { hasStyledProps } from \"@sproutsocial/seeds-react-system-props\";\nimport type { TypeLoaderButtonProps } from \"./LoaderButtonTypes\";\n\nconst StyledLoaderButton = styled(Button)`\n background-color: ${({ theme, appearance, disabled }) => {\n const buttonBackgroundColor =\n theme.colors.button[appearance as keyof typeof theme.colors.button]\n ?.background?.base;\n\n const isBackgroundColorTransparent =\n buttonBackgroundColor === \"transparent\";\n\n // If the button is disabled we want to check what the buttonBackgroundColor is, if it is transparent we want to return transparent, otherwise we want to return the buttonBackgroundColor with an opacity of 0.4. If the button is not disabled we want to return the buttonBackgroundColor.\n return disabled\n ? isBackgroundColorTransparent\n ? \"transparent\"\n : `${buttonBackgroundColor}66`\n : buttonBackgroundColor;\n }};\n ${({ disabled }) => disabled && \"opacity: 1;\"}\n`;\n\nexport const LoaderButtonHybrid = ({\n isLoading = false,\n disabled,\n loaderLabel,\n children,\n appearance = \"unstyled\",\n ...rest\n}: TypeLoaderButtonProps) => {\n if (hasStyledProps(rest)) {\n return (\n <StyledLoaderButton\n disabled={disabled || isLoading}\n appearance={appearance}\n data-qa-button-isloading={isLoading === true}\n {...rest}\n >\n <Box position=\"relative\">\n <Box opacity={isLoading ? 0 : 1} aria-hidden={isLoading}>\n {children}\n </Box>\n {isLoading && (\n <Box position=\"absolute\" top={-2} left={0} right={0} bottom={0}>\n <Loader text={loaderLabel} size=\"small\" delay={false} />\n </Box>\n )}\n </Box>\n </StyledLoaderButton>\n );\n }\n\n // Use Tailwind version (preferred - better performance)\n return (\n <LoaderButtonTailwind\n isLoading={isLoading}\n disabled={disabled}\n loaderLabel={loaderLabel}\n appearance={appearance}\n {...rest}\n >\n {children}\n </LoaderButtonTailwind>\n );\n};\n\nexport default LoaderButtonHybrid;\n","/**\n * Tailwind CSS implementation of LoaderButton component\n * Renders Button with its appearance classes plus a disabled-dimming layer\n * from loader-button.css.\n */\n\nimport * as React from \"react\";\nimport Box from \"@sproutsocial/seeds-react-box\";\nimport Button from \"@sproutsocial/seeds-react-button\";\nimport Loader from \"@sproutsocial/seeds-react-loader\";\nimport type { TypeLoaderButtonProps } from \"./LoaderButtonTypes\";\n\n// Utility for merging class names properly\nfunction cn(\n ...inputs: (string | undefined | null | false | Record<string, boolean>)[]\n): string {\n const classes: string[] = [];\n\n for (const input of inputs) {\n if (!input) continue;\n\n if (typeof input === \"string\") {\n classes.push(input);\n } else if (typeof input === \"object\") {\n for (const [key, value] of Object.entries(input)) {\n if (value) {\n classes.push(key);\n }\n }\n }\n }\n\n return classes.join(\" \");\n}\n\nexport const LoaderButtonTailwind = ({\n isLoading = false,\n disabled,\n loaderLabel,\n children,\n appearance = \"unstyled\",\n className,\n ...rest\n}: TypeLoaderButtonProps) => {\n const isDisabled = disabled || isLoading;\n const classes =\n cn({ \"seeds-loader-btn-disabled\": !!isDisabled }, className) || undefined;\n\n return (\n <Button\n disabled={isDisabled}\n appearance={appearance}\n data-qa-button-isloading={isLoading === true}\n className={classes}\n {...rest}\n >\n <Box position=\"relative\">\n <Box opacity={isLoading ? 0 : 1} aria-hidden={isLoading}>\n {children}\n </Box>\n {isLoading && (\n <Box position=\"absolute\" top={-2} left={0} right={0} bottom={0}>\n <Loader text={loaderLabel} size=\"small\" delay={false} />\n </Box>\n )}\n </Box>\n </Button>\n );\n};\n\nexport default LoaderButtonTailwind;\n"],"mappings":"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","names":["React","React","import_seeds_react_box","import_seeds_react_button","import_seeds_react_loader","Button","Box","Loader","import_jsx_runtime","styled","Button","Box","Loader","import_jsx_runtime"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sproutsocial/seeds-react-loader-button",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.45",
|
|
4
4
|
"description": "Seeds React LoaderButton",
|
|
5
5
|
"author": "Sprout Social, Inc.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -18,11 +18,11 @@
|
|
|
18
18
|
"test:watch": "jest --watch --coverage=false"
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"@sproutsocial/seeds-react-theme": "^
|
|
22
|
-
"@sproutsocial/seeds-react-system-props": "^3.
|
|
23
|
-
"@sproutsocial/seeds-react-box": "^1.1.
|
|
24
|
-
"@sproutsocial/seeds-react-button": "^2.
|
|
25
|
-
"@sproutsocial/seeds-react-loader": "^1.0.
|
|
21
|
+
"@sproutsocial/seeds-react-theme": "^4.1.0",
|
|
22
|
+
"@sproutsocial/seeds-react-system-props": "^3.1.1",
|
|
23
|
+
"@sproutsocial/seeds-react-box": "^1.1.21",
|
|
24
|
+
"@sproutsocial/seeds-react-button": "^2.2.1",
|
|
25
|
+
"@sproutsocial/seeds-react-loader": "^1.0.22"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
28
|
"@types/react": "^18.0.0",
|
|
@@ -77,3 +77,35 @@ export const AllLoaderButtons: Story = {
|
|
|
77
77
|
</Box>
|
|
78
78
|
),
|
|
79
79
|
};
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Demonstrates that Tailwind utility classes passed via `className` override the
|
|
83
|
+
* component's own CSS. Because `loader-button.css` lives in `@layer components`,
|
|
84
|
+
* the utilities below win the cascade: `bg-[#FF6B00]` paints a loud orange
|
|
85
|
+
* background over the button's own fill, `text-[#FFFFFF]` flips the label white
|
|
86
|
+
* for contrast, and `p-300` adds padding so the orange box is obvious. If the
|
|
87
|
+
* `@layer components` wrapper were missing, the unlayered component rules would
|
|
88
|
+
* beat these utilities and the orange background would never show.
|
|
89
|
+
*
|
|
90
|
+
* The story is interactive: clicking the button flips it into the loading state
|
|
91
|
+
* so the loader appears, then clears after a short timeout.
|
|
92
|
+
*/
|
|
93
|
+
export const TailwindOverrides: Story = {
|
|
94
|
+
render: () => {
|
|
95
|
+
const [isLoading, setIsLoading] = React.useState(false);
|
|
96
|
+
return (
|
|
97
|
+
<LoaderButton
|
|
98
|
+
loaderLabel="Loading..."
|
|
99
|
+
isLoading={isLoading}
|
|
100
|
+
className="bg-[#FF6B00] text-[#FFFFFF] p-300"
|
|
101
|
+
onClick={() => {
|
|
102
|
+
setIsLoading(true);
|
|
103
|
+
setTimeout(() => setIsLoading(false), 2000);
|
|
104
|
+
}}
|
|
105
|
+
>
|
|
106
|
+
Click to load
|
|
107
|
+
</LoaderButton>
|
|
108
|
+
);
|
|
109
|
+
},
|
|
110
|
+
name: "🚀 Tailwind class overrides",
|
|
111
|
+
};
|
package/src/LoaderButton.tsx
CHANGED
|
@@ -1,56 +1,14 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
import
|
|
3
|
-
import Box from "@sproutsocial/seeds-react-box";
|
|
4
|
-
import Button from "@sproutsocial/seeds-react-button";
|
|
5
|
-
import Loader from "@sproutsocial/seeds-react-loader";
|
|
2
|
+
import LoaderButtonHybrid from "./LoaderButtonHybrid";
|
|
6
3
|
import type { TypeLoaderButtonProps } from "./LoaderButtonTypes";
|
|
7
4
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
// If the button is disabled we want to check what the buttonBackgroundColor is, if it is transparent we want to return transparent, otherwise we want to return the buttonBackgroundColor with an opacity of 0.4. If the button is not disabled we want to return the buttonBackgroundColor.
|
|
18
|
-
return disabled
|
|
19
|
-
? isBackgroundColorTransparent
|
|
20
|
-
? "transparent"
|
|
21
|
-
: `${buttonBackgroundColor}66`
|
|
22
|
-
: buttonBackgroundColor;
|
|
23
|
-
}};
|
|
24
|
-
${({ disabled }) => disabled && "opacity: 1;"}
|
|
25
|
-
`;
|
|
26
|
-
|
|
27
|
-
export const LoaderButton = ({
|
|
28
|
-
isLoading = false,
|
|
29
|
-
disabled,
|
|
30
|
-
loaderLabel,
|
|
31
|
-
children,
|
|
32
|
-
appearance = "unstyled",
|
|
33
|
-
...rest
|
|
34
|
-
}: TypeLoaderButtonProps) => {
|
|
35
|
-
return (
|
|
36
|
-
<StyledLoaderButton
|
|
37
|
-
disabled={disabled || isLoading}
|
|
38
|
-
appearance={appearance}
|
|
39
|
-
data-qa-button-isloading={isLoading === true}
|
|
40
|
-
{...rest}
|
|
41
|
-
>
|
|
42
|
-
<Box position="relative">
|
|
43
|
-
<Box opacity={isLoading ? 0 : 1} aria-hidden={isLoading}>
|
|
44
|
-
{children}
|
|
45
|
-
</Box>
|
|
46
|
-
{isLoading && (
|
|
47
|
-
<Box position="absolute" top={-2} left={0} right={0} bottom={0}>
|
|
48
|
-
<Loader text={loaderLabel} size="small" delay={false} />
|
|
49
|
-
</Box>
|
|
50
|
-
)}
|
|
51
|
-
</Box>
|
|
52
|
-
</StyledLoaderButton>
|
|
53
|
-
);
|
|
54
|
-
};
|
|
5
|
+
/**
|
|
6
|
+
* LoaderButton component. Automatically routes between the Tailwind
|
|
7
|
+
* implementation (preferred) and the styled-components implementation (for
|
|
8
|
+
* consumers using system props or a styled() extension).
|
|
9
|
+
*/
|
|
10
|
+
export const LoaderButton = (props: TypeLoaderButtonProps) => (
|
|
11
|
+
<LoaderButtonHybrid {...props} />
|
|
12
|
+
);
|
|
55
13
|
|
|
56
14
|
export default LoaderButton;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hybrid LoaderButton Component
|
|
3
|
+
* Automatically chooses between Tailwind and styled-components based on props.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import * as React from "react";
|
|
7
|
+
import styled from "styled-components";
|
|
8
|
+
import Box from "@sproutsocial/seeds-react-box";
|
|
9
|
+
import Button from "@sproutsocial/seeds-react-button";
|
|
10
|
+
import Loader from "@sproutsocial/seeds-react-loader";
|
|
11
|
+
import { LoaderButtonTailwind } from "./LoaderButtonTailwind";
|
|
12
|
+
import { hasStyledProps } from "@sproutsocial/seeds-react-system-props";
|
|
13
|
+
import type { TypeLoaderButtonProps } from "./LoaderButtonTypes";
|
|
14
|
+
|
|
15
|
+
const StyledLoaderButton = styled(Button)`
|
|
16
|
+
background-color: ${({ theme, appearance, disabled }) => {
|
|
17
|
+
const buttonBackgroundColor =
|
|
18
|
+
theme.colors.button[appearance as keyof typeof theme.colors.button]
|
|
19
|
+
?.background?.base;
|
|
20
|
+
|
|
21
|
+
const isBackgroundColorTransparent =
|
|
22
|
+
buttonBackgroundColor === "transparent";
|
|
23
|
+
|
|
24
|
+
// If the button is disabled we want to check what the buttonBackgroundColor is, if it is transparent we want to return transparent, otherwise we want to return the buttonBackgroundColor with an opacity of 0.4. If the button is not disabled we want to return the buttonBackgroundColor.
|
|
25
|
+
return disabled
|
|
26
|
+
? isBackgroundColorTransparent
|
|
27
|
+
? "transparent"
|
|
28
|
+
: `${buttonBackgroundColor}66`
|
|
29
|
+
: buttonBackgroundColor;
|
|
30
|
+
}};
|
|
31
|
+
${({ disabled }) => disabled && "opacity: 1;"}
|
|
32
|
+
`;
|
|
33
|
+
|
|
34
|
+
export const LoaderButtonHybrid = ({
|
|
35
|
+
isLoading = false,
|
|
36
|
+
disabled,
|
|
37
|
+
loaderLabel,
|
|
38
|
+
children,
|
|
39
|
+
appearance = "unstyled",
|
|
40
|
+
...rest
|
|
41
|
+
}: TypeLoaderButtonProps) => {
|
|
42
|
+
if (hasStyledProps(rest)) {
|
|
43
|
+
return (
|
|
44
|
+
<StyledLoaderButton
|
|
45
|
+
disabled={disabled || isLoading}
|
|
46
|
+
appearance={appearance}
|
|
47
|
+
data-qa-button-isloading={isLoading === true}
|
|
48
|
+
{...rest}
|
|
49
|
+
>
|
|
50
|
+
<Box position="relative">
|
|
51
|
+
<Box opacity={isLoading ? 0 : 1} aria-hidden={isLoading}>
|
|
52
|
+
{children}
|
|
53
|
+
</Box>
|
|
54
|
+
{isLoading && (
|
|
55
|
+
<Box position="absolute" top={-2} left={0} right={0} bottom={0}>
|
|
56
|
+
<Loader text={loaderLabel} size="small" delay={false} />
|
|
57
|
+
</Box>
|
|
58
|
+
)}
|
|
59
|
+
</Box>
|
|
60
|
+
</StyledLoaderButton>
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Use Tailwind version (preferred - better performance)
|
|
65
|
+
return (
|
|
66
|
+
<LoaderButtonTailwind
|
|
67
|
+
isLoading={isLoading}
|
|
68
|
+
disabled={disabled}
|
|
69
|
+
loaderLabel={loaderLabel}
|
|
70
|
+
appearance={appearance}
|
|
71
|
+
{...rest}
|
|
72
|
+
>
|
|
73
|
+
{children}
|
|
74
|
+
</LoaderButtonTailwind>
|
|
75
|
+
);
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
export default LoaderButtonHybrid;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tailwind CSS implementation of LoaderButton component
|
|
3
|
+
* Renders Button with its appearance classes plus a disabled-dimming layer
|
|
4
|
+
* from loader-button.css.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import * as React from "react";
|
|
8
|
+
import Box from "@sproutsocial/seeds-react-box";
|
|
9
|
+
import Button from "@sproutsocial/seeds-react-button";
|
|
10
|
+
import Loader from "@sproutsocial/seeds-react-loader";
|
|
11
|
+
import type { TypeLoaderButtonProps } from "./LoaderButtonTypes";
|
|
12
|
+
|
|
13
|
+
// Utility for merging class names properly
|
|
14
|
+
function cn(
|
|
15
|
+
...inputs: (string | undefined | null | false | Record<string, boolean>)[]
|
|
16
|
+
): string {
|
|
17
|
+
const classes: string[] = [];
|
|
18
|
+
|
|
19
|
+
for (const input of inputs) {
|
|
20
|
+
if (!input) continue;
|
|
21
|
+
|
|
22
|
+
if (typeof input === "string") {
|
|
23
|
+
classes.push(input);
|
|
24
|
+
} else if (typeof input === "object") {
|
|
25
|
+
for (const [key, value] of Object.entries(input)) {
|
|
26
|
+
if (value) {
|
|
27
|
+
classes.push(key);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return classes.join(" ");
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export const LoaderButtonTailwind = ({
|
|
37
|
+
isLoading = false,
|
|
38
|
+
disabled,
|
|
39
|
+
loaderLabel,
|
|
40
|
+
children,
|
|
41
|
+
appearance = "unstyled",
|
|
42
|
+
className,
|
|
43
|
+
...rest
|
|
44
|
+
}: TypeLoaderButtonProps) => {
|
|
45
|
+
const isDisabled = disabled || isLoading;
|
|
46
|
+
const classes =
|
|
47
|
+
cn({ "seeds-loader-btn-disabled": !!isDisabled }, className) || undefined;
|
|
48
|
+
|
|
49
|
+
return (
|
|
50
|
+
<Button
|
|
51
|
+
disabled={isDisabled}
|
|
52
|
+
appearance={appearance}
|
|
53
|
+
data-qa-button-isloading={isLoading === true}
|
|
54
|
+
className={classes}
|
|
55
|
+
{...rest}
|
|
56
|
+
>
|
|
57
|
+
<Box position="relative">
|
|
58
|
+
<Box opacity={isLoading ? 0 : 1} aria-hidden={isLoading}>
|
|
59
|
+
{children}
|
|
60
|
+
</Box>
|
|
61
|
+
{isLoading && (
|
|
62
|
+
<Box position="absolute" top={-2} left={0} right={0} bottom={0}>
|
|
63
|
+
<Loader text={loaderLabel} size="small" delay={false} />
|
|
64
|
+
</Box>
|
|
65
|
+
)}
|
|
66
|
+
</Box>
|
|
67
|
+
</Button>
|
|
68
|
+
);
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
export default LoaderButtonTailwind;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { render, screen } from "@sproutsocial/seeds-react-testing-library";
|
|
3
|
+
import LoaderButton from "../LoaderButton";
|
|
4
|
+
|
|
5
|
+
describe("LoaderButton Tailwind path", () => {
|
|
6
|
+
it("renders Button with the seeds-btn class when no styled props are used", () => {
|
|
7
|
+
render(<LoaderButton loaderLabel="loading">Go</LoaderButton>);
|
|
8
|
+
expect(screen.getByRole("button")).toHaveClass("seeds-btn");
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
it("applies the loader disabled dimming class when disabled", () => {
|
|
12
|
+
render(
|
|
13
|
+
<LoaderButton loaderLabel="loading" disabled>
|
|
14
|
+
Go
|
|
15
|
+
</LoaderButton>
|
|
16
|
+
);
|
|
17
|
+
const button = screen.getByRole("button");
|
|
18
|
+
expect(button).toHaveClass("seeds-loader-btn-disabled");
|
|
19
|
+
expect(button).toHaveClass("seeds-btn-disabled");
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it("applies the loader disabled dimming class while loading", () => {
|
|
23
|
+
render(
|
|
24
|
+
<LoaderButton loaderLabel="loading" isLoading>
|
|
25
|
+
Go
|
|
26
|
+
</LoaderButton>
|
|
27
|
+
);
|
|
28
|
+
expect(screen.getByRole("button")).toHaveClass("seeds-loader-btn-disabled");
|
|
29
|
+
});
|
|
30
|
+
});
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Seeds LoaderButton component classes
|
|
3
|
+
* Layered on top of the Button (.seeds-btn*) classes to reproduce the disabled
|
|
4
|
+
* background dimming the styled-components LoaderButton applied.
|
|
5
|
+
*
|
|
6
|
+
* Requires @sproutsocial/seeds-react-theme/dist/theme-all.css imported for
|
|
7
|
+
* CSS variable definitions and dark mode support.
|
|
8
|
+
*
|
|
9
|
+
* Rules live in the Tailwind `components` layer so consumer utility classes
|
|
10
|
+
* (e.g. mx-200, p-300, inline-flex) win the cascade over these defaults.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
@layer components {
|
|
14
|
+
/* Keep the loader fully visible by overriding .seeds-btn-disabled opacity: 0.5 */
|
|
15
|
+
.seeds-loader-btn-disabled.seeds-btn-disabled {
|
|
16
|
+
opacity: 1;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/* Disabled background: the appearance's base color at 40% alpha. */
|
|
20
|
+
.seeds-loader-btn-disabled.seeds-btn-primary {
|
|
21
|
+
background-color: color-mix(
|
|
22
|
+
in srgb,
|
|
23
|
+
var(--color-button-primary-bg-base) 40%,
|
|
24
|
+
transparent
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.seeds-loader-btn-disabled.seeds-btn-destructive {
|
|
29
|
+
background-color: color-mix(
|
|
30
|
+
in srgb,
|
|
31
|
+
var(--color-button-destructive-bg-base) 40%,
|
|
32
|
+
transparent
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/* Appearances whose base background is transparent resolve to transparent. */
|
|
37
|
+
.seeds-loader-btn-disabled.seeds-btn-secondary {
|
|
38
|
+
background-color: transparent;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.seeds-loader-btn-disabled.seeds-btn-placeholder {
|
|
42
|
+
background-color: transparent;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.seeds-loader-btn-disabled.seeds-btn-unstyled {
|
|
46
|
+
background-color: transparent;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.seeds-loader-btn-disabled.seeds-btn-pill {
|
|
50
|
+
background-color: transparent;
|
|
51
|
+
}
|
|
52
|
+
}
|