@snowcone-app/ui 0.8.3 → 0.9.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/CHANGELOG.md +11 -0
- package/dist/index.cjs +23 -13
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +25 -15
- package/dist/index.d.ts +25 -15
- package/dist/index.js +23 -13
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/composed/AddToCart.tsx +51 -31
- package/src/composed/__tests__/AddToCart.async.test.tsx +104 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.9.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#2936](https://github.com/snowcone-app/snowcone-monorepo/pull/2936) [`3c37e27`](https://github.com/snowcone-app/snowcone-monorepo/commit/3c37e27da40c8865b4c4bd71ec9454ec7e64bc4c) Thanks [@kevinsproles](https://github.com/kevinsproles)! - `AddToCart` waits for your add and never reports a failure as success. An async `onClick` is awaited: the button shows
|
|
8
|
+
"Added!" only after it resolves, and a rejection (or throw) shows `errorText` (new prop, default
|
|
9
|
+
"Couldn't add — try again"), announces the error's message in a `role="alert"`, calls `onError`, and leaves the button
|
|
10
|
+
enabled to retry. Previously `onClick` was called without awaiting after a fixed simulated delay, so a failed add still
|
|
11
|
+
said "Added!". The button exposes `data-add-to-cart="idle | adding | added | error"` (type `AddToCartStatus`) for tests.
|
|
12
|
+
`simulateDelay` now applies only when there is no `onClick` (demos).
|
|
13
|
+
|
|
3
14
|
## 0.8.3
|
|
4
15
|
|
|
5
16
|
### Patch Changes
|
package/dist/index.cjs
CHANGED
|
@@ -4921,6 +4921,7 @@ function AddToCart({
|
|
|
4921
4921
|
text = "Add to Bag",
|
|
4922
4922
|
loadingText = "Adding...",
|
|
4923
4923
|
successText = "Added!",
|
|
4924
|
+
errorText = "Couldn't add \u2014 try again",
|
|
4924
4925
|
disabled = false,
|
|
4925
4926
|
className = "",
|
|
4926
4927
|
quantity = 1,
|
|
@@ -4930,8 +4931,10 @@ function AddToCart({
|
|
|
4930
4931
|
}) {
|
|
4931
4932
|
const context = useProduct();
|
|
4932
4933
|
const shopContext = useShopOptional();
|
|
4933
|
-
const [
|
|
4934
|
-
const [
|
|
4934
|
+
const [status, setStatus] = (0, import_react15.useState)("idle");
|
|
4935
|
+
const [errorMessage, setErrorMessage] = (0, import_react15.useState)(null);
|
|
4936
|
+
const loading = status === "adding";
|
|
4937
|
+
const success = status === "added";
|
|
4935
4938
|
(0, import_react15.useEffect)(() => {
|
|
4936
4939
|
checkProviders(
|
|
4937
4940
|
"AddToCart",
|
|
@@ -4954,7 +4957,8 @@ function AddToCart({
|
|
|
4954
4957
|
const handleClick = async () => {
|
|
4955
4958
|
if (isDisabled || !product) return;
|
|
4956
4959
|
try {
|
|
4957
|
-
|
|
4960
|
+
setStatus("adding");
|
|
4961
|
+
setErrorMessage(null);
|
|
4958
4962
|
const cartDetail = (0, import_sdk7.createCartDetail)({
|
|
4959
4963
|
productId: product.id,
|
|
4960
4964
|
quantity,
|
|
@@ -4965,20 +4969,23 @@ function AddToCart({
|
|
|
4965
4969
|
if (!cartDetail) {
|
|
4966
4970
|
throw new Error("Invalid selection - unable to create cart detail");
|
|
4967
4971
|
}
|
|
4968
|
-
|
|
4969
|
-
|
|
4970
|
-
|
|
4972
|
+
if (onClick) {
|
|
4973
|
+
await onClick(cartDetail);
|
|
4974
|
+
} else {
|
|
4975
|
+
await (0, import_sdk7.simulateCartOperation)(simulateDelay);
|
|
4976
|
+
}
|
|
4977
|
+
setStatus("added");
|
|
4971
4978
|
setTimeout(() => {
|
|
4972
|
-
|
|
4979
|
+
setStatus((s) => s === "added" ? "idle" : s);
|
|
4973
4980
|
}, 2e3);
|
|
4974
4981
|
} catch (error) {
|
|
4975
|
-
|
|
4976
|
-
|
|
4977
|
-
|
|
4978
|
-
|
|
4982
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
4983
|
+
setStatus("error");
|
|
4984
|
+
setErrorMessage(err.message);
|
|
4985
|
+
onError?.(err);
|
|
4979
4986
|
}
|
|
4980
4987
|
};
|
|
4981
|
-
const buttonText = loading ? loadingText : success ? successText : text;
|
|
4988
|
+
const buttonText = loading ? loadingText : success ? successText : status === "error" ? errorText : text;
|
|
4982
4989
|
const defaultStyles = "w-full bg-primary text-primary-foreground hover:bg-primary/90 px-6 py-3 rounded-button font-medium transition-colors";
|
|
4983
4990
|
const buttonClasses = `
|
|
4984
4991
|
${defaultStyles}
|
|
@@ -4989,6 +4996,7 @@ function AddToCart({
|
|
|
4989
4996
|
const getAriaLabel = () => {
|
|
4990
4997
|
if (loading) return loadingText;
|
|
4991
4998
|
if (success) return successText;
|
|
4999
|
+
if (status === "error") return `${errorText} - ${product?.name || "product"}`;
|
|
4992
5000
|
if (!product) return text;
|
|
4993
5001
|
return `${text} - ${product.name || "product"}`;
|
|
4994
5002
|
};
|
|
@@ -5002,9 +5010,11 @@ function AddToCart({
|
|
|
5002
5010
|
onClick: handleClick,
|
|
5003
5011
|
"aria-label": getAriaLabel(),
|
|
5004
5012
|
"aria-busy": loading,
|
|
5013
|
+
"data-add-to-cart": status,
|
|
5005
5014
|
children: buttonText
|
|
5006
5015
|
}
|
|
5007
|
-
)
|
|
5016
|
+
),
|
|
5017
|
+
status === "error" && errorMessage && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("p", { role: "alert", className: "mt-2 text-sm text-destructive", children: errorMessage })
|
|
5008
5018
|
] });
|
|
5009
5019
|
}
|
|
5010
5020
|
|