@fluid-app/cart-ui 0.1.0 → 0.1.1
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/dist/index.cjs +31 -18
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +18 -7
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +18 -7
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +31 -17
- package/dist/index.mjs.map +1 -1
- package/package.json +7 -6
package/dist/index.cjs
CHANGED
|
@@ -23,32 +23,48 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
23
23
|
//#endregion
|
|
24
24
|
let react = require("react");
|
|
25
25
|
react = __toESM(react);
|
|
26
|
-
let
|
|
27
|
-
next_script = __toESM(next_script);
|
|
28
|
-
let react_jsx_runtime = require("react/jsx-runtime");
|
|
26
|
+
let react_dom = require("react-dom");
|
|
29
27
|
let _fluid_app_ui_primitives = require("@fluid-app/ui-primitives");
|
|
30
28
|
let lucide_react = require("lucide-react");
|
|
31
|
-
let
|
|
29
|
+
let react_jsx_runtime = require("react/jsx-runtime");
|
|
32
30
|
//#region src/components/cart-script.tsx
|
|
31
|
+
const SCRIPT_ID = "fluid-cdn-script";
|
|
32
|
+
const SCRIPT_SRC = "https://assets.fluid.app/scripts/fluid-sdk/latest/web-widgets/index.js";
|
|
33
33
|
function CartScript({ subdomain, authJwt }) {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
34
|
+
const authJwtRef = (0, react.useRef)(authJwt);
|
|
35
|
+
authJwtRef.current = authJwt;
|
|
36
|
+
(0, react.useEffect)(() => {
|
|
37
|
+
if (!subdomain) return;
|
|
38
|
+
if (document.getElementById(SCRIPT_ID)) return;
|
|
39
|
+
const script = document.createElement("script");
|
|
40
|
+
script.id = SCRIPT_ID;
|
|
41
|
+
script.src = SCRIPT_SRC;
|
|
42
|
+
script.type = "module";
|
|
43
|
+
script.crossOrigin = "anonymous";
|
|
44
|
+
script.dataset.fluidShop = subdomain;
|
|
45
|
+
if (authJwtRef.current) script.dataset.authJwt = authJwtRef.current;
|
|
46
|
+
document.head.appendChild(script);
|
|
47
|
+
return () => {
|
|
48
|
+
const existing = document.getElementById(SCRIPT_ID);
|
|
49
|
+
if (existing) existing.remove();
|
|
50
|
+
};
|
|
51
|
+
}, [subdomain]);
|
|
52
|
+
return null;
|
|
43
53
|
}
|
|
44
54
|
//#endregion
|
|
45
55
|
//#region src/components/cart-widget.tsx
|
|
46
56
|
function CartWidget() {
|
|
47
|
-
|
|
57
|
+
const [mounted, setMounted] = (0, react.useState)(false);
|
|
58
|
+
(0, react.useEffect)(() => {
|
|
59
|
+
setMounted(true);
|
|
60
|
+
}, []);
|
|
61
|
+
const widget = react.default.createElement("fluid-cart-widget", {
|
|
48
62
|
"data-fluid-widget": "true",
|
|
49
63
|
"hide-widget": "true",
|
|
50
64
|
"is-primary": "true"
|
|
51
65
|
});
|
|
66
|
+
if (mounted) return (0, react_dom.createPortal)(widget, document.body);
|
|
67
|
+
return null;
|
|
52
68
|
}
|
|
53
69
|
//#endregion
|
|
54
70
|
//#region src/components/cart-button.tsx
|
|
@@ -100,10 +116,7 @@ function CartButton({ onCheckout }) {
|
|
|
100
116
|
className: "bg-primary-foreground text-primary absolute -top-1 -right-2 flex h-4 w-4 items-center justify-center rounded-full text-[8px] font-bold",
|
|
101
117
|
children: "0"
|
|
102
118
|
})]
|
|
103
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
104
|
-
className: "",
|
|
105
|
-
children: "Cart"
|
|
106
|
-
})]
|
|
119
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "Cart" })]
|
|
107
120
|
});
|
|
108
121
|
}
|
|
109
122
|
//#endregion
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["React","Button","ShoppingCart"],"sources":["../src/components/cart-script.tsx","../src/components/cart-widget.tsx","../src/components/cart-button.tsx","../src/components/shop-container.tsx"],"sourcesContent":["import { useEffect, useRef } from \"react\";\n\ninterface CartScriptProps {\n subdomain: string;\n authJwt?: string;\n}\n\nconst SCRIPT_ID = \"fluid-cdn-script\";\nconst SCRIPT_SRC =\n \"https://assets.fluid.app/scripts/fluid-sdk/latest/web-widgets/index.js\";\n\nexport default function CartScript({\n subdomain,\n authJwt,\n}: CartScriptProps): React.ReactNode {\n // Use a ref so the script is injected once with the initial JWT value.\n // ES modules are cached by URL — re-inserting the same script won't\n // re-execute it, so changing authJwt after the first load has no effect.\n const authJwtRef = useRef(authJwt);\n authJwtRef.current = authJwt;\n\n useEffect(() => {\n if (!subdomain) return;\n\n // Don't add a duplicate script\n if (document.getElementById(SCRIPT_ID)) return;\n\n const script = document.createElement(\"script\");\n script.id = SCRIPT_ID;\n script.src = SCRIPT_SRC;\n script.type = \"module\";\n script.crossOrigin = \"anonymous\";\n script.dataset.fluidShop = subdomain;\n if (authJwtRef.current) {\n script.dataset.authJwt = authJwtRef.current;\n }\n document.head.appendChild(script);\n\n return () => {\n const existing = document.getElementById(SCRIPT_ID);\n if (existing) existing.remove();\n };\n }, [subdomain]);\n\n return null;\n}\n","import React, { useState, useEffect } from \"react\";\nimport { createPortal } from \"react-dom\";\n\nexport default function CartWidget(): React.ReactNode {\n const [mounted, setMounted] = useState(false);\n\n useEffect(() => {\n setMounted(true);\n }, []);\n\n const widget = React.createElement(\"fluid-cart-widget\", {\n \"data-fluid-widget\": \"true\",\n \"hide-widget\": \"true\",\n \"is-primary\": \"true\",\n });\n\n // Portal to document.body so the cart drawer escapes any\n // overflow-hidden / isolation stacking contexts in the layout.\n if (mounted) {\n return createPortal(widget, document.body);\n }\n\n return null;\n}\n","\"use client\";\n\nimport { Button } from \"@fluid-app/ui-primitives\";\nimport { ShoppingCart } from \"lucide-react\";\nimport React, { useEffect, useCallback } from \"react\";\n\ndeclare global {\n interface Window {\n FluidCommerceSDK?: {\n getCheckoutUrl: () => string;\n setOnCheckout: (callback: () => void) => void;\n };\n fluidCart?: {\n open: () => void;\n };\n }\n}\n\ninterface CartButtonProps {\n onCheckout?: (checkoutUrl: string) => void;\n}\n\nconst MAX_SDK_POLL_ATTEMPTS = 50; // 5 seconds at 100ms intervals\n\nexport function CartButton({ onCheckout }: CartButtonProps): React.ReactNode {\n const navigateToCheckout = useCallback(() => {\n if (!window.FluidCommerceSDK) {\n console.error(\"FluidCommerceSDK not available\");\n return;\n }\n\n try {\n const checkoutUrl = window.FluidCommerceSDK.getCheckoutUrl();\n if (!checkoutUrl) {\n console.error(\"No checkout URL available\");\n return;\n }\n onCheckout?.(checkoutUrl);\n } catch (error) {\n console.error(\"Error getting checkout URL:\", error);\n }\n }, [onCheckout]);\n\n useEffect(() => {\n let timeoutId: ReturnType<typeof setTimeout> | null = null;\n let attempts = 0;\n let cancelled = false;\n\n const setupSDK = () => {\n if (cancelled) return;\n if (window.FluidCommerceSDK) {\n window.FluidCommerceSDK.setOnCheckout(navigateToCheckout);\n } else if (attempts < MAX_SDK_POLL_ATTEMPTS) {\n attempts++;\n timeoutId = setTimeout(setupSDK, 100);\n }\n };\n\n setupSDK();\n return () => {\n cancelled = true;\n if (timeoutId) clearTimeout(timeoutId);\n };\n }, [navigateToCheckout]);\n\n return (\n <Button\n className=\"bg-primary text-primary-foreground hover:bg-primary-700 relative flex items-center gap-4 rounded-sm px-4 py-1.5\"\n onClick={() => {\n window.fluidCart?.open();\n }}\n >\n <div className=\"relative\">\n <ShoppingCart className=\"size-5\" />\n <span\n id=\"fluid-cart-count\"\n className=\"bg-primary-foreground text-primary absolute -top-1 -right-2 flex h-4 w-4 items-center justify-center rounded-full text-[8px] font-bold\"\n >\n 0\n </span>\n </div>\n <span>Cart</span>\n </Button>\n );\n}\n","import React, { useEffect, useRef, useState } from \"react\";\nimport { createPortal } from \"react-dom\";\n\ninterface ShopContainerProps {\n children: React.ReactNode;\n className?: string;\n cartScript?: React.ReactNode;\n cartWidget?: React.ReactNode;\n}\n\nexport default function ShopContainer({\n children,\n className = \"\",\n cartScript,\n cartWidget,\n}: ShopContainerProps): React.ReactNode {\n const containerRef = useRef<HTMLDivElement>(null);\n const [portalContainer, setPortalContainer] = useState<HTMLDivElement | null>(\n null,\n );\n\n useEffect(() => {\n const currentContainer = containerRef.current;\n if (!currentContainer) return;\n\n const reactContentWrapper = document.createElement(\"div\");\n reactContentWrapper.id = \"react-content-wrapper\";\n reactContentWrapper.style.cssText = `\n position: relative;\n `;\n reactContentWrapper.className = \"min-h-full\";\n\n currentContainer.appendChild(reactContentWrapper);\n\n setPortalContainer(reactContentWrapper);\n\n return () => {\n if (currentContainer && reactContentWrapper) {\n try {\n currentContainer.removeChild(reactContentWrapper);\n } catch (e) {\n console.warn(\"Failed to cleanup isolated container:\", e);\n }\n }\n setPortalContainer(null);\n };\n }, []);\n\n return (\n <>\n <div\n ref={containerRef}\n className={`isolated-shop-wrapper ${className} h-full`}\n >\n {portalContainer &&\n createPortal(\n <>\n {cartScript}\n {cartWidget}\n {children}\n </>,\n portalContainer,\n )}\n </div>\n </>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAOA,MAAM,YAAY;AAClB,MAAM,aACJ;AAEF,SAAwB,WAAW,EACjC,WACA,WACmC;CAInC,MAAM,cAAA,GAAA,MAAA,QAAoB,QAAQ;AAClC,YAAW,UAAU;AAErB,EAAA,GAAA,MAAA,iBAAgB;AACd,MAAI,CAAC,UAAW;AAGhB,MAAI,SAAS,eAAe,UAAU,CAAE;EAExC,MAAM,SAAS,SAAS,cAAc,SAAS;AAC/C,SAAO,KAAK;AACZ,SAAO,MAAM;AACb,SAAO,OAAO;AACd,SAAO,cAAc;AACrB,SAAO,QAAQ,YAAY;AAC3B,MAAI,WAAW,QACb,QAAO,QAAQ,UAAU,WAAW;AAEtC,WAAS,KAAK,YAAY,OAAO;AAEjC,eAAa;GACX,MAAM,WAAW,SAAS,eAAe,UAAU;AACnD,OAAI,SAAU,UAAS,QAAQ;;IAEhC,CAAC,UAAU,CAAC;AAEf,QAAO;;;;ACzCT,SAAwB,aAA8B;CACpD,MAAM,CAAC,SAAS,eAAA,GAAA,MAAA,UAAuB,MAAM;AAE7C,EAAA,GAAA,MAAA,iBAAgB;AACd,aAAW,KAAK;IACf,EAAE,CAAC;CAEN,MAAM,SAASA,MAAAA,QAAM,cAAc,qBAAqB;EACtD,qBAAqB;EACrB,eAAe;EACf,cAAc;EACf,CAAC;AAIF,KAAI,QACF,SAAA,GAAA,UAAA,cAAoB,QAAQ,SAAS,KAAK;AAG5C,QAAO;;;;ACAT,MAAM,wBAAwB;AAE9B,SAAgB,WAAW,EAAE,cAAgD;CAC3E,MAAM,sBAAA,GAAA,MAAA,mBAAuC;AAC3C,MAAI,CAAC,OAAO,kBAAkB;AAC5B,WAAQ,MAAM,iCAAiC;AAC/C;;AAGF,MAAI;GACF,MAAM,cAAc,OAAO,iBAAiB,gBAAgB;AAC5D,OAAI,CAAC,aAAa;AAChB,YAAQ,MAAM,4BAA4B;AAC1C;;AAEF,gBAAa,YAAY;WAClB,OAAO;AACd,WAAQ,MAAM,+BAA+B,MAAM;;IAEpD,CAAC,WAAW,CAAC;AAEhB,EAAA,GAAA,MAAA,iBAAgB;EACd,IAAI,YAAkD;EACtD,IAAI,WAAW;EACf,IAAI,YAAY;EAEhB,MAAM,iBAAiB;AACrB,OAAI,UAAW;AACf,OAAI,OAAO,iBACT,QAAO,iBAAiB,cAAc,mBAAmB;YAChD,WAAW,uBAAuB;AAC3C;AACA,gBAAY,WAAW,UAAU,IAAI;;;AAIzC,YAAU;AACV,eAAa;AACX,eAAY;AACZ,OAAI,UAAW,cAAa,UAAU;;IAEvC,CAAC,mBAAmB,CAAC;AAExB,QACE,iBAAA,GAAA,kBAAA,MAACC,yBAAAA,QAAD;EACE,WAAU;EACV,eAAe;AACb,UAAO,WAAW,MAAM;;YAH5B,CAME,iBAAA,GAAA,kBAAA,MAAC,OAAD;GAAK,WAAU;aAAf,CACE,iBAAA,GAAA,kBAAA,KAACC,aAAAA,cAAD,EAAc,WAAU,UAAW,CAAA,EACnC,iBAAA,GAAA,kBAAA,KAAC,QAAD;IACE,IAAG;IACH,WAAU;cACX;IAEM,CAAA,CACH;MACN,iBAAA,GAAA,kBAAA,KAAC,QAAD,EAAA,UAAM,QAAW,CAAA,CACV;;;;;ACxEb,SAAwB,cAAc,EACpC,UACA,YAAY,IACZ,YACA,cACsC;CACtC,MAAM,gBAAA,GAAA,MAAA,QAAsC,KAAK;CACjD,MAAM,CAAC,iBAAiB,uBAAA,GAAA,MAAA,UACtB,KACD;AAED,EAAA,GAAA,MAAA,iBAAgB;EACd,MAAM,mBAAmB,aAAa;AACtC,MAAI,CAAC,iBAAkB;EAEvB,MAAM,sBAAsB,SAAS,cAAc,MAAM;AACzD,sBAAoB,KAAK;AACzB,sBAAoB,MAAM,UAAU;;;AAGpC,sBAAoB,YAAY;AAEhC,mBAAiB,YAAY,oBAAoB;AAEjD,qBAAmB,oBAAoB;AAEvC,eAAa;AACX,OAAI,oBAAoB,oBACtB,KAAI;AACF,qBAAiB,YAAY,oBAAoB;YAC1C,GAAG;AACV,YAAQ,KAAK,yCAAyC,EAAE;;AAG5D,sBAAmB,KAAK;;IAEzB,EAAE,CAAC;AAEN,QACE,iBAAA,GAAA,kBAAA,KAAA,kBAAA,UAAA,EAAA,UACE,iBAAA,GAAA,kBAAA,KAAC,OAAD;EACE,KAAK;EACL,WAAW,yBAAyB,UAAU;YAE7C,oBAAA,GAAA,UAAA,cAEG,iBAAA,GAAA,kBAAA,MAAA,kBAAA,UAAA,EAAA,UAAA;GACG;GACA;GACA;GACA,EAAA,CAAA,EACH,gBACD;EACC,CAAA,EACL,CAAA"}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React from "react";
|
|
1
|
+
import React$1 from "react";
|
|
2
2
|
|
|
3
3
|
//#region src/components/cart-script.d.ts
|
|
4
4
|
interface CartScriptProps {
|
|
@@ -11,29 +11,40 @@ declare function CartScript({
|
|
|
11
11
|
}: CartScriptProps): React.ReactNode;
|
|
12
12
|
//#endregion
|
|
13
13
|
//#region src/components/cart-widget.d.ts
|
|
14
|
-
declare function CartWidget(): React.ReactNode;
|
|
14
|
+
declare function CartWidget(): React$1.ReactNode;
|
|
15
15
|
//#endregion
|
|
16
16
|
//#region src/components/cart-button.d.ts
|
|
17
|
+
declare global {
|
|
18
|
+
interface Window {
|
|
19
|
+
FluidCommerceSDK?: {
|
|
20
|
+
getCheckoutUrl: () => string;
|
|
21
|
+
setOnCheckout: (callback: () => void) => void;
|
|
22
|
+
};
|
|
23
|
+
fluidCart?: {
|
|
24
|
+
open: () => void;
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
}
|
|
17
28
|
interface CartButtonProps {
|
|
18
29
|
onCheckout?: (checkoutUrl: string) => void;
|
|
19
30
|
}
|
|
20
31
|
declare function CartButton({
|
|
21
32
|
onCheckout
|
|
22
|
-
}: CartButtonProps): React.ReactNode;
|
|
33
|
+
}: CartButtonProps): React$1.ReactNode;
|
|
23
34
|
//#endregion
|
|
24
35
|
//#region src/components/shop-container.d.ts
|
|
25
36
|
interface ShopContainerProps {
|
|
26
|
-
children: React.ReactNode;
|
|
37
|
+
children: React$1.ReactNode;
|
|
27
38
|
className?: string;
|
|
28
|
-
cartScript?: React.ReactNode;
|
|
29
|
-
cartWidget?: React.ReactNode;
|
|
39
|
+
cartScript?: React$1.ReactNode;
|
|
40
|
+
cartWidget?: React$1.ReactNode;
|
|
30
41
|
}
|
|
31
42
|
declare function ShopContainer({
|
|
32
43
|
children,
|
|
33
44
|
className,
|
|
34
45
|
cartScript,
|
|
35
46
|
cartWidget
|
|
36
|
-
}: ShopContainerProps): React.ReactNode;
|
|
47
|
+
}: ShopContainerProps): React$1.ReactNode;
|
|
37
48
|
//#endregion
|
|
38
49
|
export { CartButton, CartScript, CartWidget, ShopContainer };
|
|
39
50
|
//# sourceMappingURL=index.d.cts.map
|
package/dist/index.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.cts","names":[],"sources":["../src/components/cart-script.tsx","../src/components/cart-widget.tsx","../src/components/cart-button.tsx","../src/components/shop-container.tsx"],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"index.d.cts","names":[],"sources":["../src/components/cart-script.tsx","../src/components/cart-widget.tsx","../src/components/cart-button.tsx","../src/components/shop-container.tsx"],"mappings":";;;UAEU,eAAA;EACR,SAAA;EACA,OAAA;AAAA;AAAA,iBAOsB,UAAA,CAAA;EACtB,SAAA;EACA;AAAA,GACC,eAAA,GAAkB,KAAA,CAAM,SAAA;;;iBCXH,UAAA,CAAA,GAAc,OAAA,CAAM,SAAA;;;;YCIhC,MAAA;IACR,gBAAA;MACE,cAAA;MACA,aAAA,GAAgB,QAAA;IAAA;IAElB,SAAA;MACE,IAAA;IAAA;EAAA;AAAA;AAAA,UAKI,eAAA;EACR,UAAA,IAAc,WAAA;AAAA;AAAA,iBAKA,UAAA,CAAA;EAAa;AAAA,GAAc,eAAA,GAAkB,OAAA,CAAM,SAAA;;;UCrBzD,kBAAA;EACR,QAAA,EAAU,OAAA,CAAM,SAAA;EAChB,SAAA;EACA,UAAA,GAAa,OAAA,CAAM,SAAA;EACnB,UAAA,GAAa,OAAA,CAAM,SAAA;AAAA;AAAA,iBAGG,aAAA,CAAA;EACtB,QAAA;EACA,SAAA;EACA,UAAA;EACA;AAAA,GACC,kBAAA,GAAqB,OAAA,CAAM,SAAA"}
|
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React from "react";
|
|
1
|
+
import React$1 from "react";
|
|
2
2
|
|
|
3
3
|
//#region src/components/cart-script.d.ts
|
|
4
4
|
interface CartScriptProps {
|
|
@@ -11,29 +11,40 @@ declare function CartScript({
|
|
|
11
11
|
}: CartScriptProps): React.ReactNode;
|
|
12
12
|
//#endregion
|
|
13
13
|
//#region src/components/cart-widget.d.ts
|
|
14
|
-
declare function CartWidget(): React.ReactNode;
|
|
14
|
+
declare function CartWidget(): React$1.ReactNode;
|
|
15
15
|
//#endregion
|
|
16
16
|
//#region src/components/cart-button.d.ts
|
|
17
|
+
declare global {
|
|
18
|
+
interface Window {
|
|
19
|
+
FluidCommerceSDK?: {
|
|
20
|
+
getCheckoutUrl: () => string;
|
|
21
|
+
setOnCheckout: (callback: () => void) => void;
|
|
22
|
+
};
|
|
23
|
+
fluidCart?: {
|
|
24
|
+
open: () => void;
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
}
|
|
17
28
|
interface CartButtonProps {
|
|
18
29
|
onCheckout?: (checkoutUrl: string) => void;
|
|
19
30
|
}
|
|
20
31
|
declare function CartButton({
|
|
21
32
|
onCheckout
|
|
22
|
-
}: CartButtonProps): React.ReactNode;
|
|
33
|
+
}: CartButtonProps): React$1.ReactNode;
|
|
23
34
|
//#endregion
|
|
24
35
|
//#region src/components/shop-container.d.ts
|
|
25
36
|
interface ShopContainerProps {
|
|
26
|
-
children: React.ReactNode;
|
|
37
|
+
children: React$1.ReactNode;
|
|
27
38
|
className?: string;
|
|
28
|
-
cartScript?: React.ReactNode;
|
|
29
|
-
cartWidget?: React.ReactNode;
|
|
39
|
+
cartScript?: React$1.ReactNode;
|
|
40
|
+
cartWidget?: React$1.ReactNode;
|
|
30
41
|
}
|
|
31
42
|
declare function ShopContainer({
|
|
32
43
|
children,
|
|
33
44
|
className,
|
|
34
45
|
cartScript,
|
|
35
46
|
cartWidget
|
|
36
|
-
}: ShopContainerProps): React.ReactNode;
|
|
47
|
+
}: ShopContainerProps): React$1.ReactNode;
|
|
37
48
|
//#endregion
|
|
38
49
|
export { CartButton, CartScript, CartWidget, ShopContainer };
|
|
39
50
|
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/components/cart-script.tsx","../src/components/cart-widget.tsx","../src/components/cart-button.tsx","../src/components/shop-container.tsx"],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/components/cart-script.tsx","../src/components/cart-widget.tsx","../src/components/cart-button.tsx","../src/components/shop-container.tsx"],"mappings":";;;UAEU,eAAA;EACR,SAAA;EACA,OAAA;AAAA;AAAA,iBAOsB,UAAA,CAAA;EACtB,SAAA;EACA;AAAA,GACC,eAAA,GAAkB,KAAA,CAAM,SAAA;;;iBCXH,UAAA,CAAA,GAAc,OAAA,CAAM,SAAA;;;;YCIhC,MAAA;IACR,gBAAA;MACE,cAAA;MACA,aAAA,GAAgB,QAAA;IAAA;IAElB,SAAA;MACE,IAAA;IAAA;EAAA;AAAA;AAAA,UAKI,eAAA;EACR,UAAA,IAAc,WAAA;AAAA;AAAA,iBAKA,UAAA,CAAA;EAAa;AAAA,GAAc,eAAA,GAAkB,OAAA,CAAM,SAAA;;;UCrBzD,kBAAA;EACR,QAAA,EAAU,OAAA,CAAM,SAAA;EAChB,SAAA;EACA,UAAA,GAAa,OAAA,CAAM,SAAA;EACnB,UAAA,GAAa,OAAA,CAAM,SAAA;AAAA;AAAA,iBAGG,aAAA,CAAA;EACtB,QAAA;EACA,SAAA;EACA,UAAA;EACA;AAAA,GACC,kBAAA,GAAqB,OAAA,CAAM,SAAA"}
|
package/dist/index.mjs
CHANGED
|
@@ -1,29 +1,46 @@
|
|
|
1
1
|
import React, { useCallback, useEffect, useRef, useState } from "react";
|
|
2
|
-
import
|
|
3
|
-
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { createPortal } from "react-dom";
|
|
4
3
|
import { Button } from "@fluid-app/ui-primitives";
|
|
5
4
|
import { ShoppingCart } from "lucide-react";
|
|
6
|
-
import {
|
|
5
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
7
6
|
//#region src/components/cart-script.tsx
|
|
7
|
+
const SCRIPT_ID = "fluid-cdn-script";
|
|
8
|
+
const SCRIPT_SRC = "https://assets.fluid.app/scripts/fluid-sdk/latest/web-widgets/index.js";
|
|
8
9
|
function CartScript({ subdomain, authJwt }) {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
10
|
+
const authJwtRef = useRef(authJwt);
|
|
11
|
+
authJwtRef.current = authJwt;
|
|
12
|
+
useEffect(() => {
|
|
13
|
+
if (!subdomain) return;
|
|
14
|
+
if (document.getElementById(SCRIPT_ID)) return;
|
|
15
|
+
const script = document.createElement("script");
|
|
16
|
+
script.id = SCRIPT_ID;
|
|
17
|
+
script.src = SCRIPT_SRC;
|
|
18
|
+
script.type = "module";
|
|
19
|
+
script.crossOrigin = "anonymous";
|
|
20
|
+
script.dataset.fluidShop = subdomain;
|
|
21
|
+
if (authJwtRef.current) script.dataset.authJwt = authJwtRef.current;
|
|
22
|
+
document.head.appendChild(script);
|
|
23
|
+
return () => {
|
|
24
|
+
const existing = document.getElementById(SCRIPT_ID);
|
|
25
|
+
if (existing) existing.remove();
|
|
26
|
+
};
|
|
27
|
+
}, [subdomain]);
|
|
28
|
+
return null;
|
|
18
29
|
}
|
|
19
30
|
//#endregion
|
|
20
31
|
//#region src/components/cart-widget.tsx
|
|
21
32
|
function CartWidget() {
|
|
22
|
-
|
|
33
|
+
const [mounted, setMounted] = useState(false);
|
|
34
|
+
useEffect(() => {
|
|
35
|
+
setMounted(true);
|
|
36
|
+
}, []);
|
|
37
|
+
const widget = React.createElement("fluid-cart-widget", {
|
|
23
38
|
"data-fluid-widget": "true",
|
|
24
39
|
"hide-widget": "true",
|
|
25
40
|
"is-primary": "true"
|
|
26
41
|
});
|
|
42
|
+
if (mounted) return createPortal(widget, document.body);
|
|
43
|
+
return null;
|
|
27
44
|
}
|
|
28
45
|
//#endregion
|
|
29
46
|
//#region src/components/cart-button.tsx
|
|
@@ -75,10 +92,7 @@ function CartButton({ onCheckout }) {
|
|
|
75
92
|
className: "bg-primary-foreground text-primary absolute -top-1 -right-2 flex h-4 w-4 items-center justify-center rounded-full text-[8px] font-bold",
|
|
76
93
|
children: "0"
|
|
77
94
|
})]
|
|
78
|
-
}), /* @__PURE__ */ jsx("span", {
|
|
79
|
-
className: "",
|
|
80
|
-
children: "Cart"
|
|
81
|
-
})]
|
|
95
|
+
}), /* @__PURE__ */ jsx("span", { children: "Cart" })]
|
|
82
96
|
});
|
|
83
97
|
}
|
|
84
98
|
//#endregion
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../src/components/cart-script.tsx","../src/components/cart-widget.tsx","../src/components/cart-button.tsx","../src/components/shop-container.tsx"],"sourcesContent":["
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../src/components/cart-script.tsx","../src/components/cart-widget.tsx","../src/components/cart-button.tsx","../src/components/shop-container.tsx"],"sourcesContent":["import { useEffect, useRef } from \"react\";\n\ninterface CartScriptProps {\n subdomain: string;\n authJwt?: string;\n}\n\nconst SCRIPT_ID = \"fluid-cdn-script\";\nconst SCRIPT_SRC =\n \"https://assets.fluid.app/scripts/fluid-sdk/latest/web-widgets/index.js\";\n\nexport default function CartScript({\n subdomain,\n authJwt,\n}: CartScriptProps): React.ReactNode {\n // Use a ref so the script is injected once with the initial JWT value.\n // ES modules are cached by URL — re-inserting the same script won't\n // re-execute it, so changing authJwt after the first load has no effect.\n const authJwtRef = useRef(authJwt);\n authJwtRef.current = authJwt;\n\n useEffect(() => {\n if (!subdomain) return;\n\n // Don't add a duplicate script\n if (document.getElementById(SCRIPT_ID)) return;\n\n const script = document.createElement(\"script\");\n script.id = SCRIPT_ID;\n script.src = SCRIPT_SRC;\n script.type = \"module\";\n script.crossOrigin = \"anonymous\";\n script.dataset.fluidShop = subdomain;\n if (authJwtRef.current) {\n script.dataset.authJwt = authJwtRef.current;\n }\n document.head.appendChild(script);\n\n return () => {\n const existing = document.getElementById(SCRIPT_ID);\n if (existing) existing.remove();\n };\n }, [subdomain]);\n\n return null;\n}\n","import React, { useState, useEffect } from \"react\";\nimport { createPortal } from \"react-dom\";\n\nexport default function CartWidget(): React.ReactNode {\n const [mounted, setMounted] = useState(false);\n\n useEffect(() => {\n setMounted(true);\n }, []);\n\n const widget = React.createElement(\"fluid-cart-widget\", {\n \"data-fluid-widget\": \"true\",\n \"hide-widget\": \"true\",\n \"is-primary\": \"true\",\n });\n\n // Portal to document.body so the cart drawer escapes any\n // overflow-hidden / isolation stacking contexts in the layout.\n if (mounted) {\n return createPortal(widget, document.body);\n }\n\n return null;\n}\n","\"use client\";\n\nimport { Button } from \"@fluid-app/ui-primitives\";\nimport { ShoppingCart } from \"lucide-react\";\nimport React, { useEffect, useCallback } from \"react\";\n\ndeclare global {\n interface Window {\n FluidCommerceSDK?: {\n getCheckoutUrl: () => string;\n setOnCheckout: (callback: () => void) => void;\n };\n fluidCart?: {\n open: () => void;\n };\n }\n}\n\ninterface CartButtonProps {\n onCheckout?: (checkoutUrl: string) => void;\n}\n\nconst MAX_SDK_POLL_ATTEMPTS = 50; // 5 seconds at 100ms intervals\n\nexport function CartButton({ onCheckout }: CartButtonProps): React.ReactNode {\n const navigateToCheckout = useCallback(() => {\n if (!window.FluidCommerceSDK) {\n console.error(\"FluidCommerceSDK not available\");\n return;\n }\n\n try {\n const checkoutUrl = window.FluidCommerceSDK.getCheckoutUrl();\n if (!checkoutUrl) {\n console.error(\"No checkout URL available\");\n return;\n }\n onCheckout?.(checkoutUrl);\n } catch (error) {\n console.error(\"Error getting checkout URL:\", error);\n }\n }, [onCheckout]);\n\n useEffect(() => {\n let timeoutId: ReturnType<typeof setTimeout> | null = null;\n let attempts = 0;\n let cancelled = false;\n\n const setupSDK = () => {\n if (cancelled) return;\n if (window.FluidCommerceSDK) {\n window.FluidCommerceSDK.setOnCheckout(navigateToCheckout);\n } else if (attempts < MAX_SDK_POLL_ATTEMPTS) {\n attempts++;\n timeoutId = setTimeout(setupSDK, 100);\n }\n };\n\n setupSDK();\n return () => {\n cancelled = true;\n if (timeoutId) clearTimeout(timeoutId);\n };\n }, [navigateToCheckout]);\n\n return (\n <Button\n className=\"bg-primary text-primary-foreground hover:bg-primary-700 relative flex items-center gap-4 rounded-sm px-4 py-1.5\"\n onClick={() => {\n window.fluidCart?.open();\n }}\n >\n <div className=\"relative\">\n <ShoppingCart className=\"size-5\" />\n <span\n id=\"fluid-cart-count\"\n className=\"bg-primary-foreground text-primary absolute -top-1 -right-2 flex h-4 w-4 items-center justify-center rounded-full text-[8px] font-bold\"\n >\n 0\n </span>\n </div>\n <span>Cart</span>\n </Button>\n );\n}\n","import React, { useEffect, useRef, useState } from \"react\";\nimport { createPortal } from \"react-dom\";\n\ninterface ShopContainerProps {\n children: React.ReactNode;\n className?: string;\n cartScript?: React.ReactNode;\n cartWidget?: React.ReactNode;\n}\n\nexport default function ShopContainer({\n children,\n className = \"\",\n cartScript,\n cartWidget,\n}: ShopContainerProps): React.ReactNode {\n const containerRef = useRef<HTMLDivElement>(null);\n const [portalContainer, setPortalContainer] = useState<HTMLDivElement | null>(\n null,\n );\n\n useEffect(() => {\n const currentContainer = containerRef.current;\n if (!currentContainer) return;\n\n const reactContentWrapper = document.createElement(\"div\");\n reactContentWrapper.id = \"react-content-wrapper\";\n reactContentWrapper.style.cssText = `\n position: relative;\n `;\n reactContentWrapper.className = \"min-h-full\";\n\n currentContainer.appendChild(reactContentWrapper);\n\n setPortalContainer(reactContentWrapper);\n\n return () => {\n if (currentContainer && reactContentWrapper) {\n try {\n currentContainer.removeChild(reactContentWrapper);\n } catch (e) {\n console.warn(\"Failed to cleanup isolated container:\", e);\n }\n }\n setPortalContainer(null);\n };\n }, []);\n\n return (\n <>\n <div\n ref={containerRef}\n className={`isolated-shop-wrapper ${className} h-full`}\n >\n {portalContainer &&\n createPortal(\n <>\n {cartScript}\n {cartWidget}\n {children}\n </>,\n portalContainer,\n )}\n </div>\n </>\n );\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fluid-app/cart-ui",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"files": [
|
|
5
5
|
"dist",
|
|
6
6
|
"src/styles"
|
|
@@ -14,6 +14,10 @@
|
|
|
14
14
|
},
|
|
15
15
|
"./styles/cart.css": "./src/styles/cart.css"
|
|
16
16
|
},
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"lucide-react": "^0.475.0",
|
|
19
|
+
"@fluid-app/ui-primitives": "0.1.10"
|
|
20
|
+
},
|
|
17
21
|
"devDependencies": {
|
|
18
22
|
"@types/node": "^24",
|
|
19
23
|
"@types/react": "^19.2.13",
|
|
@@ -25,11 +29,8 @@
|
|
|
25
29
|
"@fluid-app/typescript-config": "0.0.0"
|
|
26
30
|
},
|
|
27
31
|
"peerDependencies": {
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
"react": ">=18.0.0",
|
|
31
|
-
"react-dom": ">=18.0.0",
|
|
32
|
-
"@fluid-app/ui-primitives": "^0.1.10"
|
|
32
|
+
"react": "^19.2.4",
|
|
33
|
+
"react-dom": "^19.2.4"
|
|
33
34
|
},
|
|
34
35
|
"scripts": {
|
|
35
36
|
"transit": "tsgo --emitDeclarationOnly",
|