axokit-react 0.0.3 → 0.0.5
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/README.md +2 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.js +28 -1
- package/dist/index.mjs +29 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -34,6 +34,7 @@ function SaveButton() {
|
|
|
34
34
|
loadingText="Saving..."
|
|
35
35
|
successText="Saved ✓"
|
|
36
36
|
errorText="Try again"
|
|
37
|
+
showSpinner // built‑in loader
|
|
37
38
|
disableOnSuccess={false} // optional
|
|
38
39
|
className="px-4 py-2 rounded bg-blue-600 text-white"
|
|
39
40
|
>
|
|
@@ -74,6 +75,7 @@ function HookExample() {
|
|
|
74
75
|
- `successDuration?: number` — default: `1200` ms.
|
|
75
76
|
- `errorDuration?: number` — default: `3000` ms.
|
|
76
77
|
- `disableOnSuccess?: boolean` — default: `true`.
|
|
78
|
+
- `showSpinner?: boolean` — default: `false`. When `true`, a tiny built‑in SVG spinner appears to the left of the label during loading.
|
|
77
79
|
- `onSuccess?: () => void`.
|
|
78
80
|
- `onActionError?: (error: Error) => void`.
|
|
79
81
|
- All other native `button` props are forwarded.
|
package/dist/index.d.ts
CHANGED
|
@@ -25,8 +25,10 @@ interface AsyncButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>
|
|
|
25
25
|
onSuccess?: () => void;
|
|
26
26
|
onActionError?: (error: Error) => void;
|
|
27
27
|
disableOnSuccess?: boolean;
|
|
28
|
+
/** automatically render a small spinner next to the label when loading */
|
|
29
|
+
showSpinner?: boolean;
|
|
28
30
|
children: React.ReactNode;
|
|
29
31
|
}
|
|
30
|
-
declare function AsyncButton({ onAction, loadingText, successText, errorText, successDuration, errorDuration, onSuccess, onActionError, disableOnSuccess, children, disabled, className, ...props }: AsyncButtonProps): react_jsx_runtime.JSX.Element;
|
|
32
|
+
declare function AsyncButton({ onAction, loadingText, successText, errorText, successDuration, errorDuration, onSuccess, onActionError, disableOnSuccess, showSpinner, children, disabled, className, ...props }: AsyncButtonProps): react_jsx_runtime.JSX.Element;
|
|
31
33
|
|
|
32
34
|
export { AsyncButton, useAsyncAction };
|
package/dist/index.js
CHANGED
|
@@ -45,6 +45,7 @@ function useAsyncAction(action, options = {}) {
|
|
|
45
45
|
const timeoutRef = React.useRef(null);
|
|
46
46
|
const mountedRef = React.useRef(true);
|
|
47
47
|
React.useEffect(() => {
|
|
48
|
+
mountedRef.current = true;
|
|
48
49
|
return () => {
|
|
49
50
|
mountedRef.current = false;
|
|
50
51
|
if (timeoutRef.current) {
|
|
@@ -109,6 +110,7 @@ function AsyncButton({
|
|
|
109
110
|
onSuccess,
|
|
110
111
|
onActionError,
|
|
111
112
|
disableOnSuccess = true,
|
|
113
|
+
showSpinner = false,
|
|
112
114
|
children,
|
|
113
115
|
disabled,
|
|
114
116
|
className = "",
|
|
@@ -132,6 +134,31 @@ function AsyncButton({
|
|
|
132
134
|
return children;
|
|
133
135
|
}
|
|
134
136
|
};
|
|
137
|
+
const renderContent = () => {
|
|
138
|
+
const label = getLabel();
|
|
139
|
+
if (state === "loading" && showSpinner) {
|
|
140
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { display: "flex", gap: "0.5em", alignItems: "center" }, children: [
|
|
141
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
142
|
+
"svg",
|
|
143
|
+
{
|
|
144
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
145
|
+
width: "24",
|
|
146
|
+
height: "24",
|
|
147
|
+
viewBox: "0 0 24 24",
|
|
148
|
+
fill: "none",
|
|
149
|
+
stroke: "currentColor",
|
|
150
|
+
"stroke-width": "2",
|
|
151
|
+
"stroke-linecap": "round",
|
|
152
|
+
"stroke-linejoin": "round",
|
|
153
|
+
className: "lucide lucide-loader-circle-icon lucide-loader-circle",
|
|
154
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M21 12a9 9 0 1 1-6.219-8.56" })
|
|
155
|
+
}
|
|
156
|
+
),
|
|
157
|
+
label
|
|
158
|
+
] }) });
|
|
159
|
+
}
|
|
160
|
+
return label;
|
|
161
|
+
};
|
|
135
162
|
const isDisabled = disabled || state === "loading" || state === "success" && disableOnSuccess;
|
|
136
163
|
const { onClick: _nativeOnClick, type: buttonType = "button", ...rest } = props;
|
|
137
164
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
@@ -144,7 +171,7 @@ function AsyncButton({
|
|
|
144
171
|
disabled: isDisabled,
|
|
145
172
|
"aria-busy": state === "loading",
|
|
146
173
|
"data-state": state,
|
|
147
|
-
children:
|
|
174
|
+
children: renderContent()
|
|
148
175
|
}
|
|
149
176
|
);
|
|
150
177
|
}
|
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// src/AsyncButton.tsx
|
|
2
2
|
import * as React from "react";
|
|
3
|
-
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
4
4
|
function useAsyncAction(action, options = {}) {
|
|
5
5
|
const { successDuration = 1200, errorDuration = 3e3, onSuccess, onActionError } = options;
|
|
6
6
|
const [state, setState] = React.useState("idle");
|
|
@@ -8,6 +8,7 @@ function useAsyncAction(action, options = {}) {
|
|
|
8
8
|
const timeoutRef = React.useRef(null);
|
|
9
9
|
const mountedRef = React.useRef(true);
|
|
10
10
|
React.useEffect(() => {
|
|
11
|
+
mountedRef.current = true;
|
|
11
12
|
return () => {
|
|
12
13
|
mountedRef.current = false;
|
|
13
14
|
if (timeoutRef.current) {
|
|
@@ -72,6 +73,7 @@ function AsyncButton({
|
|
|
72
73
|
onSuccess,
|
|
73
74
|
onActionError,
|
|
74
75
|
disableOnSuccess = true,
|
|
76
|
+
showSpinner = false,
|
|
75
77
|
children,
|
|
76
78
|
disabled,
|
|
77
79
|
className = "",
|
|
@@ -95,6 +97,31 @@ function AsyncButton({
|
|
|
95
97
|
return children;
|
|
96
98
|
}
|
|
97
99
|
};
|
|
100
|
+
const renderContent = () => {
|
|
101
|
+
const label = getLabel();
|
|
102
|
+
if (state === "loading" && showSpinner) {
|
|
103
|
+
return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: "0.5em", alignItems: "center" }, children: [
|
|
104
|
+
/* @__PURE__ */ jsx(
|
|
105
|
+
"svg",
|
|
106
|
+
{
|
|
107
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
108
|
+
width: "24",
|
|
109
|
+
height: "24",
|
|
110
|
+
viewBox: "0 0 24 24",
|
|
111
|
+
fill: "none",
|
|
112
|
+
stroke: "currentColor",
|
|
113
|
+
"stroke-width": "2",
|
|
114
|
+
"stroke-linecap": "round",
|
|
115
|
+
"stroke-linejoin": "round",
|
|
116
|
+
className: "lucide lucide-loader-circle-icon lucide-loader-circle",
|
|
117
|
+
children: /* @__PURE__ */ jsx("path", { d: "M21 12a9 9 0 1 1-6.219-8.56" })
|
|
118
|
+
}
|
|
119
|
+
),
|
|
120
|
+
label
|
|
121
|
+
] }) });
|
|
122
|
+
}
|
|
123
|
+
return label;
|
|
124
|
+
};
|
|
98
125
|
const isDisabled = disabled || state === "loading" || state === "success" && disableOnSuccess;
|
|
99
126
|
const { onClick: _nativeOnClick, type: buttonType = "button", ...rest } = props;
|
|
100
127
|
return /* @__PURE__ */ jsx(
|
|
@@ -107,7 +134,7 @@ function AsyncButton({
|
|
|
107
134
|
disabled: isDisabled,
|
|
108
135
|
"aria-busy": state === "loading",
|
|
109
136
|
"data-state": state,
|
|
110
|
-
children:
|
|
137
|
+
children: renderContent()
|
|
111
138
|
}
|
|
112
139
|
);
|
|
113
140
|
}
|