UNPKG

ov25-ui

Version:

A UI configurator for OV25 product visualization

1,576 lines 458 kB
import './index.css'; import * as c from "react"; import h, { createContext as Gs, useContext as In, useState as ee, useRef as Ue, useEffect as Te, useCallback as so, useMemo as Xt, useLayoutEffect as Ys, forwardRef as Qo, createElement as an, isValidElement as $r } from "react"; import * as Qs from "react-dom"; import ai, { createPortal as tt, unstable_batchedUpdates as Xs } from "react-dom"; var to = {}, ra; function Ks() { if (ra) return to; ra = 1; var e = ai; if (process.env.NODE_ENV === "production") to.createRoot = e.createRoot, to.hydrateRoot = e.hydrateRoot; else { var t = e.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED; to.createRoot = function(o, r) { t.usingClientEntryPoint = !0; try { return e.createRoot(o, r); } finally { t.usingClientEntryPoint = !1; } }, to.hydrateRoot = function(o, r, n) { t.usingClientEntryPoint = !0; try { return e.hydrateRoot(o, r, n); } finally { t.usingClientEntryPoint = !1; } }; } return to; } var Zs = Ks(); const ii = () => document.getElementById("ov25-configurator-iframe"), lo = (e, t) => { const o = ii(); o != null && o.contentWindow && o.contentWindow.postMessage({ type: e, payload: JSON.stringify(t) }, "*"); }, Js = (e, t) => { lo("VIEW_DIMENSIONS", { dimensions: !e }), t((o) => !o); }, el = () => { lo("TOGGLE_ANIMATION", {}); }, tl = () => { lo("ENTER_AR", {}); }, ol = () => { const e = ii(), t = e == null ? void 0 : e.parentElement; t && (document.fullscreenElement ? document.exitFullscreen() : t.requestFullscreen().catch((o) => { console.error(`Error attempting to enable fullscreen: ${o.message}`); })); }, rl = (e, t) => e ? t === "open" || t === "loop" ? "Close" : "Open" : "", nl = (e, t) => { const o = "https://configurator.orbital.vision"; e || (e = ""), t || (t = ""); const r = t.startsWith("/") ? t.substring(1) : t, a = new URL(window.location.href).search, i = a ? `${r}${a}` : r; return `${o}/${e}/${i}`; }, si = 0.42, Io = 1 - si; var Br = {}, na; function al() { return na || (na = 1, function(e) { Object.defineProperty(e, "__esModule", { value: !0 }), e.stringSimilarity = void 0; var t = function(o, r, n, a) { if (n === void 0 && (n = 2), a === void 0 && (a = !1), a || (o = o.toLowerCase(), r = r.toLowerCase()), o.length < n || r.length < n) return 0; for (var i = /* @__PURE__ */ new Map(), s = 0; s < o.length - (n - 1); s++) { var l = o.substr(s, n); i.set(l, i.has(l) ? i.get(l) + 1 : 1); } for (var d = 0, v = 0; v < r.length - (n - 1); v++) { var p = r.substr(v, n), m = i.has(p) ? i.get(p) : 0; m > 0 && (i.set(p, m - 1), d++); } return d * 2 / (o.length + r.length - (n - 1) * 2); }; e.stringSimilarity = t, e.default = e.stringSimilarity; }(Br)), Br; } var il = al(); const li = Gs(void 0), sl = ({ children: e, productLink: t, apiKey: o, buyNowFunction: r, addToBasketFunction: n, addSwatchesToCartFunction: a, images: i, deferThreeD: s = !1, showOptional: l = !1, logoURL: d, isProductGalleryStacked: v, mobileLogoURL: p, shadowDOMs: m }) => { var me, de, Be, Ae; const [u, b] = ee([]), [f, y] = ee(), [g, x] = ee(), [E, S] = ee([]), [N, _] = ee(null), [C, k] = ee(1), [O, D] = ee(0), [P, j] = ee(0), [re, X] = ee({ percentage: 0, amount: 0, formattedAmount: "£0.00" }), [se, G] = ee("£0.00"), [oe, A] = ee("£0.00"), [B, ve] = ee(null), [pe, Z] = ee(null), [Y, H] = ee("closed"), [ke, Pe] = ee(!1), [U, Se] = ee(!1), [he, we] = ee(null), [ce, M] = ee(null), [z, te] = ee(!1), [ne, le] = ee("unavailable"), fe = Ue(null), [Ne, De] = ee(!1), [Ve, We] = ee(!1), [rt, He] = ee(null), [$e, xt] = ee({}), [je, Ke] = ee(!1), [lt, Et] = ee({}), [qe, kt] = ee([]), mt = Ue(!1), Ze = Ue(!1), nt = Ue(!1), zt = (R, W) => { const [Q, q] = ee(() => { try { const ge = window.localStorage.getItem(R); return ge ? JSON.parse(ge) : W; } catch (ge) { return console.error(`Error reading localStorage key "${R}":`, ge), W; } }), F = so((ge) => { q((Me) => { try { const Le = ge instanceof Function ? ge(Me) : ge; return window.localStorage.setItem(R, JSON.stringify(Le)), Le; } catch (Le) { return console.error(`Error setting localStorage key "${R}":`, Le), Me; } }); }, [R]); return [Q, F]; }, [Je, Dt] = zt("ov25-selected-swatches", []), [_t, St] = ee(!1), [at, pt] = ee({ freeSwatchLimit: 0, canExeedFreeLimit: !1, pricePerSwatch: 0, minSwatches: 0, maxSwatches: 0, enabled: !1 }); Te(() => { var R; g != null && g.selectedSelections && S(g.selectedSelections), (R = g == null ? void 0 : g.configuratorSettings) != null && R.swatchSettings && pt(g.configuratorSettings.swatchSettings); }, [g]), Te(() => { f && rt === f && (He(null), Ze.current = !1); }, [f, rt]), Te(() => { const R = () => { De(window.innerWidth < 768); }; return R(), window.addEventListener("resize", R), () => window.removeEventListener("resize", R); }, []); const ct = so((R, W) => { Et((Q) => ({ ...Q, [R]: W })); }, []), Ge = so((R) => { Dt((W) => W.findIndex((q) => q.manufacturerId === R.manufacturerId && q.name === R.name && q.option === R.option) === -1 ? [...W, R] : W.filter((q) => q.manufacturerId !== R.manufacturerId || q.name !== R.name || q.option !== R.option)); }, []), Ht = so((R) => Je.some((W) => W.manufacturerId === R.manufacturerId && W.name === R.name && W.option === R.option), [Je]), K = (R) => { lo("SELECT_CAMERA", R); }, ie = u == null ? void 0 : u.find((R) => R.id === f), xe = { id: "size", name: "size", groups: [{ id: "size-group", name: "Size Options", selections: (u == null ? void 0 : u.map((R) => { var W, Q, q, F, ge; return { id: R == null ? void 0 : R.id, name: R == null ? void 0 : R.name, price: R == null ? void 0 : R.price, discount: R == null ? void 0 : R.discount, thumbnail: ((Q = (W = R == null ? void 0 : R.metadata) == null ? void 0 : W.images) == null ? void 0 : Q.length) > 0 ? (ge = R == null ? void 0 : R.metadata) == null ? void 0 : ge.images[((F = (q = R == null ? void 0 : R.metadata) == null ? void 0 : q.images) == null ? void 0 : F.length) - 1] : null }; })) || [] }] }, _e = (me = g == null ? void 0 : g.options) == null ? void 0 : me.find((R) => R.id === N), Qe = Xt(() => { if (!_e) return; const R = (q) => { const F = lt[_e.id]; if (!F) return !0; const ge = il.stringSimilarity(q.toLowerCase(), F.toLowerCase()), Me = q.toLowerCase().includes(F.toLowerCase()); return ge > 0.4 || Me; }, W = (q) => { var Le; const F = $e == null ? void 0 : $e[_e.name]; if (!F) return !0; let ge = !1, Me = !1; for (const Ot in F) { if (Ot === "Collections") continue; const oa = F[Ot].filter((qt) => qt.checked).map((qt) => qt.value); if (oa.length > 0) { ge = !0; const qt = (Le = q.filter) == null ? void 0 : Le[Ot]; if (qt != null && qt.some((qs) => oa.includes(qs))) { Me = !0; break; } } } return !ge || Me; }, Q = (q) => { if (!lt[_e.id] || R(q.name)) return !0; for (const ge in q.filter) { const Me = q.filter[ge]; if (Me != null && Me.some((Le) => R(Le))) return !0; } return !1; }; return { ..._e, groups: _e.groups.filter((q) => { var ge, Me; const F = lt[_e.id]; return F && R(q.name) || F && q.selections.some((Ot) => Q(Ot)) ? !0 : (Me = (ge = $e == null ? void 0 : $e[_e.name]) == null ? void 0 : ge.Collections) != null && Me.some((Le) => Le.checked) ? $e == null ? void 0 : $e[_e.name].Collections.filter((Le) => Le.checked).map((Le) => Le.value).includes(q.name) : !F; }).map((q) => ({ ...q, selections: lt[_e.id] && !R(q.name) ? q.selections.filter((F) => { const ge = Q(F), Me = W(F); return ge && Me; }) : q.selections.filter((F) => W(F)) })) }; }, [_e, $e, lt]); if (!nt.current && g && g.options && g.options.length > 0) { const R = ((de = g.configuratorSettings) == null ? void 0 : de.availableProductFilters) || {}, W = {}; g.options.forEach((Q) => { if (Q.name && R[Q.name]) { const q = {}; R[Q.name].forEach((F) => { q[F] = /* @__PURE__ */ new Set(); }), Q.groups.forEach((F) => { F.selections.forEach((ge) => { Object.keys(ge.filter || {}).forEach((Me) => { var Ot; const Le = (Ot = ge.filter) == null ? void 0 : Ot[Me]; Array.isArray(Le) && q[Me] && Le.forEach((ta) => q[Me].add(ta)); }); }); }), W[Q.name] = {}, Object.keys(q).forEach((F) => { W[Q.name] || (W[Q.name] = {}), W[Q.name][F] = Array.from(q[F]).map((ge) => ({ value: ge, checked: !1 })); }); } Q.groups && Q.groups.length > 0 && (Q.groups.length > 1 || Q.groups[0].name !== "Default Group") && (W[Q.name] || (W[Q.name] = {}), W[Q.name].Collections = Q.groups.map((q) => ({ value: q.name, checked: !1 }))); }), xt(W), Ke(Object.keys(W).length > 0 && Object.keys(W).some((Q) => Object.keys(W[Q]).some((q) => Object.keys(W[Q][q]).length > 0))), nt.current = !0; } const Oe = [ ...(u == null ? void 0 : u.length) > 1 ? [xe] : [], ...(g == null ? void 0 : g.options) || [] ]; Oe.forEach((R) => { R.hasNonOption = R.groups.some((W) => W.selections.some((Q) => Q.name.toLowerCase() === "none")); }); const dt = (R) => { if (R.id === "size") return (ie == null ? void 0 : ie.name) || ""; const W = E.find( (F) => F.optionId === R.id ); if (!W) return ""; const Q = R.groups.find((F) => F.id === W.groupId), q = Q == null ? void 0 : Q.selections.find((F) => F.id === W.selectionId); return (q == null ? void 0 : q.name) || ""; }, Ye = (R) => { _(R), Pe(!0); }, ut = (R) => { if (N === "size") { if (f !== R.id) { if (Ze.current) return; Ze.current = !0, He(R.id), S((W) => [...W.filter((q) => q.optionId !== "size"), { optionId: "size", selectionId: R.id }]), lo("SELECT_PRODUCT", R.id); } return; } else S((W) => [...W.filter((q) => q.optionId !== N), { optionId: N || "", groupId: R.groupId, selectionId: R.id }]), lo("SELECT_SELECTION", { optionId: N, groupId: R.groupId, selectionId: R.id }); !Ve && I === 1 && s && (We(!0), L(J)); }, jr = () => { const W = (Oe.findIndex((Q) => Q.id === N) + 1) % (Oe == null ? void 0 : Oe.length); _(Oe[W].id); }, Fr = () => { const W = (Oe.findIndex((Q) => Q.id === N) - 1 + (Oe == null ? void 0 : Oe.length)) % (Oe == null ? void 0 : Oe.length); _(Oe[W].id); }; Te(() => { const R = (W) => { try { const { type: Q, payload: q } = W.data; if (!Q) return; const F = q ? JSON.parse(q) : {}; switch (Q) { case "ALL_PRODUCTS": b(F); break; case "CURRENT_PRODUCT_ID": y(F); break; case "ANIMATION_STATE": te(F !== "unavailable"), le(F); break; case "CONFIGURATOR_STATE": x(F); break; case "CURRENT_PRICE": D(F.totalPrice), j(F.subtotal), A(F.formattedSubtotal), G(F.formattedPrice), X(F.discount); break; case "CURRENT_SKU": ve(F); break; case "RANGE": Z(F); break; case "AR_PREVIEW_LINK": we(F); break; case "AVAILABLE_CAMERAS": kt(F); break; case "CURRENT_QUERY_STRING": const ge = new URL(window.location.href); ge.search = F, window.history.replaceState(window.history.state, "", ge.toString()); break; case "ERROR": M(new Error(F)); break; } } catch (Q) { console.error("Error handling message:", Q, "Event data:", W.data); } }; return window.addEventListener("message", R), () => window.removeEventListener("message", R); }, []); const Vr = ((Ae = (Be = ie == null ? void 0 : ie.metadata) == null ? void 0 : Be.images) == null ? void 0 : Ae.slice(0, -1)) || [], w = [...i || [], ...Vr], [I, L] = ee(0), [J, Ee] = ee(I); Te(() => { s && w.length > 0 && !mt.current && (Ee(1), mt.current = !0); }, [w]); const Re = { // Shadow DOM references shadowDOMs: m, // State products: u, currentProductId: f, configuratorState: g, selectedSelections: E, activeOptionId: N, quantity: C, price: O, subtotal: P, formattedPrice: se, discount: re, formattedSubtotal: oe, galleryIndex: I, currentSku: B, range: pe, drawerSize: Y, isVariantsOpen: ke, isDrawerOrDialogOpen: U, arPreviewLink: he, error: ce, canAnimate: z, animationState: ne, iframeRef: fe, isMobile: Ne, isProductGalleryStacked: v, hasSwitchedAfterDefer: Ve, deferThreeD: s, showOptional: l, galleryIndexToUse: J, // Coming from injectConfigurator options productLink: t, apiKey: o, buyNowFunction: r, addToBasketFunction: n, addSwatchesToCartFunction: a, images: i, logoURL: d, mobileLogoURL: p, // Computed values currentProduct: ie, sizeOption: xe, activeOption: Qe, availableProductFilters: $e, showFilters: je, allOptions: Oe, searchQueries: lt, selectedSwatches: Je, swatchRulesData: at, isSwatchBookOpen: _t, availableCameras: qe, // Methods setProducts: b, setCurrentProductId: y, setConfiguratorState: x, setSelectedSelections: S, setActiveOptionId: _, setQuantity: k, setPrice: D, setSubtotal: j, setDiscount: X, setGalleryIndex: L, setCurrentSku: ve, setRange: Z, setDrawerSize: H, setIsVariantsOpen: Pe, setIsDrawerOrDialogOpen: Se, setArPreviewLink: we, setError: M, setCanAnimate: te, setAnimationState: le, setHasSwitchedAfterDefer: We, setAvailableProductFilters: xt, setSearchQuery: ct, setSelectedSwatches: Dt, toggleSwatch: Ge, isSwatchSelected: Ht, setSwatchRulesData: pt, setIsSwatchBookOpen: St, setAvailableCameras: kt, selectCamera: K, // Actions handleSelectionSelect: ut, handleOptionClick: Ye, handleNextOption: jr, handlePreviousOption: Fr, getSelectedValue: dt, toggleAR: tl }; return /* @__PURE__ */ h.createElement(li.Provider, { value: Re }, e); }, Ie = () => { const e = In(li); if (e === void 0) throw new Error("useOV25UI must be used within an OV25UIProvider"); return e; }, yo = (e) => { const t = document.getElementById(e); if (t) return t; if (e === "ov25-configurator-variant-menu-container") { const r = document.getElementById("ov25-variants-shadow-container"); if (r != null && r.shadowRoot) { const n = r.shadowRoot.getElementById(e); if (n) return n; } } const o = document.querySelectorAll('div[class^="ov25-configurator-"]'); for (const r of Array.from(o)) if (r.shadowRoot) { const n = r.shadowRoot.getElementById(e); if (n) return n; const a = r.shadowRoot.querySelectorAll('div[class^="ov25-configurator-"]'); for (const i of Array.from(a)) if (i.shadowRoot) { const s = i.shadowRoot.getElementById(e); if (s) return s; } } return null; }, ll = () => { const { isDrawerOrDialogOpen: e, isMobile: t, drawerSize: o, isProductGalleryStacked: r } = Ie(), n = Ue(null); Te(() => { var v, p; const a = yo("ov25-configurator-iframe"), i = yo(r ? "true-ov25-configurator-iframe-container" : "ov25-configurator-iframe-container"), s = i == null ? void 0 : i.parentElement; if (!a || !i || !s) return; const l = () => { if (!e || t) return; const m = yo("ov25-configurator-variant-menu-container"), u = m == null ? void 0 : m.offsetWidth; typeof u != "number" && console.error("Variant menu does not exist yet"); const b = window.innerWidth - (u || 0); i.style.width = `${b}px`, a.style.width = `${b}px`; }, d = () => { if (!n.current) return; const m = n.current; t ? (a.style.transition = "transform 400ms cubic-bezier(0.4, 0, 0.2, 1)", i.style.transition = "transform 400ms cubic-bezier(0.4, 0, 0.2, 1)", i.style.transform = "translateY(-100%)", a.style.transform = "translateY(-100%)", setTimeout(() => { Object.assign(i.style, m.container), Object.assign(a.style, m.iframe), Object.assign(s.style, m.parent); }, 400)) : (a.style.transition = "transform 500ms cubic-bezier(0.4, 0, 0.2, 1)", i.style.transition = "transform 500ms cubic-bezier(0.4, 0, 0.2, 1)", i.style.transform = "translateX(-100%)", a.style.transform = "translateX(-100%)", setTimeout(() => { Object.assign(i.style, m.container), Object.assign(a.style, m.iframe), Object.assign(s.style, m.parent); }, 500)); }; if (e) { n.current || (n.current = { container: { position: i.style.position, top: i.style.top, left: i.style.left, right: i.style.right, zIndex: i.style.zIndex, borderRadius: i.style.borderRadius, height: i.style.height, width: i.style.width, overflow: i.style.overflow, transform: "translateX(0) translateY(0)", transition: "none" }, iframe: { position: a.style.position, top: a.style.top, left: a.style.left, width: a.style.width, height: a.style.height, zIndex: a.style.zIndex, transform: "translateX(0) translateY(0)", transition: "none" }, parent: { height: s.style.height, width: s.style.width, overflow: s.style.overflow } }); const m = i.offsetHeight, u = i.offsetWidth; if (s.style.height = `${m}px`, s.style.width = `${u}px`, s.style.overflow = "hidden", t) { const b = () => { var y, g; const f = ((y = window.visualViewport) == null ? void 0 : y.height) !== void 0 ? (g = window.visualViewport) == null ? void 0 : g.height : window.innerHeight; i.style.height = `${f * Io}px`, a.style.height = `${f * Io}px`; }; return b(), i.style.width = "100%", i.style.right = "0", a.style.width = "100%", i.style.position = "fixed", i.style.top = "0", i.style.left = "0", i.style.right = "0", i.style.zIndex = "0", i.style.borderRadius = "0", i.style.zIndex = "100", i.style.overflow = "hidden", a.style.position = "fixed", a.style.top = "0", a.style.left = "0", a.style.zIndex = "100", (v = window.visualViewport) == null || v.addEventListener("resize", b), (p = window.visualViewport) == null || p.addEventListener("scroll", b), window.addEventListener("resize", b), i.style.transform = "translateY(-100%)", a.style.transform = "translateY(-100%)", setTimeout(() => { a.style.transition = "transform 400ms cubic-bezier(0.4, 0, 0.2, 1)", i.style.transition = "transform 400ms cubic-bezier(0.4, 0, 0.2, 1)", i.style.transform = "translateY(0%)", a.style.transform = "translateY(0%)", b(); }, 50), () => { var f, y; (f = window.visualViewport) == null || f.removeEventListener("resize", b), (y = window.visualViewport) == null || y.removeEventListener("scroll", b), window.removeEventListener("resize", b), window.removeEventListener("resize", l); }; } else return setTimeout(() => { l(); }, 100), i.style.height = "100%", a.style.height = "100%", window.addEventListener("resize", l), i.style.position = "fixed", i.style.top = "0", i.style.left = "0", i.style.right = "0", i.style.zIndex = "0", i.style.borderRadius = "0", i.style.zIndex = "100", i.style.overflow = "hidden", a.style.position = "fixed", a.style.top = "0", a.style.left = "0", a.style.zIndex = "100", i.style.transform = "translateX(-100%)", a.style.transform = "translateX(-100%)", setTimeout(() => { a.style.transition = "transform 500ms cubic-bezier(0.4, 0, 0.2, 1)", i.style.transition = "transform 500ms cubic-bezier(0.4, 0, 0.2, 1)", i.style.transform = "translateX(0%)", a.style.transform = "translateX(0%)"; }, 50), () => { window.removeEventListener("resize", l); }; } else d(); return () => { window.removeEventListener("resize", l); }; }, [e, t]), Te(() => { if (e) { const a = yo("ov25-configurator-iframe"), i = yo("ov25-configurator-iframe-container"); if (!i || !a) return; const s = a.style.height, l = i.style.height; if (a.style.transition = "height 500ms cubic-bezier(0.4, 0, 0.2, 1)", i.style.transition = "height 500ms cubic-bezier(0.4, 0, 0.2, 1)", o === "large") { const d = `${window.innerHeight * si}px`; a.style.height = d, i.style.height = d; } else if (o === "small") { const d = `${window.innerHeight * Io}px`; a.style.height = d, i.style.height = d; } return () => { e || (a.style.transition = "none", i.style.transition = "none", a.style.height = s, i.style.height = l); }; } }, [o, e]); }; function ci(e) { var t, o, r = ""; if (typeof e == "string" || typeof e == "number") r += e; else if (typeof e == "object") if (Array.isArray(e)) { var n = e.length; for (t = 0; t < n; t++) e[t] && (o = ci(e[t])) && (r && (r += " "), r += o); } else for (o in e) e[o] && (r && (r += " "), r += o); return r; } function _n() { for (var e, t, o = 0, r = "", n = arguments.length; o < n; o++) (e = arguments[o]) && (t = ci(e)) && (r && (r += " "), r += t); return r; } const On = "-", cl = (e) => { const t = ul(e), { conflictingClassGroups: o, conflictingClassGroupModifiers: r } = e; return { getClassGroupId: (i) => { const s = i.split(On); return s[0] === "" && s.length !== 1 && s.shift(), di(s, t) || dl(i); }, getConflictingClassGroupIds: (i, s) => { const l = o[i] || []; return s && r[i] ? [...l, ...r[i]] : l; } }; }, di = (e, t) => { var i; if (e.length === 0) return t.classGroupId; const o = e[0], r = t.nextPart.get(o), n = r ? di(e.slice(1), r) : void 0; if (n) return n; if (t.validators.length === 0) return; const a = e.join(On); return (i = t.validators.find(({ validator: s }) => s(a))) == null ? void 0 : i.classGroupId; }, aa = /^\[(.+)\]$/, dl = (e) => { if (aa.test(e)) { const t = aa.exec(e)[1], o = t == null ? void 0 : t.substring(0, t.indexOf(":")); if (o) return "arbitrary.." + o; } }, ul = (e) => { const { theme: t, classGroups: o } = e, r = { nextPart: /* @__PURE__ */ new Map(), validators: [] }; for (const n in o) sn(o[n], r, n, t); return r; }, sn = (e, t, o, r) => { e.forEach((n) => { if (typeof n == "string") { const a = n === "" ? t : ia(t, n); a.classGroupId = o; return; } if (typeof n == "function") { if (vl(n)) { sn(n(r), t, o, r); return; } t.validators.push({ validator: n, classGroupId: o }); return; } Object.entries(n).forEach(([a, i]) => { sn(i, ia(t, a), o, r); }); }); }, ia = (e, t) => { let o = e; return t.split(On).forEach((r) => { o.nextPart.has(r) || o.nextPart.set(r, { nextPart: /* @__PURE__ */ new Map(), validators: [] }), o = o.nextPart.get(r); }), o; }, vl = (e) => e.isThemeGetter, fl = (e) => { if (e < 1) return { get: () => { }, set: () => { } }; let t = 0, o = /* @__PURE__ */ new Map(), r = /* @__PURE__ */ new Map(); const n = (a, i) => { o.set(a, i), t++, t > e && (t = 0, r = o, o = /* @__PURE__ */ new Map()); }; return { get(a) { let i = o.get(a); if (i !== void 0) return i; if ((i = r.get(a)) !== void 0) return n(a, i), i; }, set(a, i) { o.has(a) ? o.set(a, i) : n(a, i); } }; }, ln = "!", cn = ":", ml = cn.length, pl = (e) => { const { prefix: t, experimentalParseClassName: o } = e; let r = (n) => { const a = []; let i = 0, s = 0, l = 0, d; for (let b = 0; b < n.length; b++) { let f = n[b]; if (i === 0 && s === 0) { if (f === cn) { a.push(n.slice(l, b)), l = b + ml; continue; } if (f === "/") { d = b; continue; } } f === "[" ? i++ : f === "]" ? i-- : f === "(" ? s++ : f === ")" && s--; } const v = a.length === 0 ? n : n.substring(l), p = hl(v), m = p !== v, u = d && d > l ? d - l : void 0; return { modifiers: a, hasImportantModifier: m, baseClassName: p, maybePostfixModifierPosition: u }; }; if (t) { const n = t + cn, a = r; r = (i) => i.startsWith(n) ? a(i.substring(n.length)) : { isExternal: !0, modifiers: [], hasImportantModifier: !1, baseClassName: i, maybePostfixModifierPosition: void 0 }; } if (o) { const n = r; r = (a) => o({ className: a, parseClassName: n }); } return r; }, hl = (e) => e.endsWith(ln) ? e.substring(0, e.length - 1) : e.startsWith(ln) ? e.substring(1) : e, gl = (e) => { const t = Object.fromEntries(e.orderSensitiveModifiers.map((r) => [r, !0])); return (r) => { if (r.length <= 1) return r; const n = []; let a = []; return r.forEach((i) => { i[0] === "[" || t[i] ? (n.push(...a.sort(), i), a = []) : a.push(i); }), n.push(...a.sort()), n; }; }, bl = (e) => ({ cache: fl(e.cacheSize), parseClassName: pl(e), sortModifiers: gl(e), ...cl(e) }), yl = /\s+/, wl = (e, t) => { const { parseClassName: o, getClassGroupId: r, getConflictingClassGroupIds: n, sortModifiers: a } = t, i = [], s = e.trim().split(yl); let l = ""; for (let d = s.length - 1; d >= 0; d -= 1) { const v = s[d], { isExternal: p, modifiers: m, hasImportantModifier: u, baseClassName: b, maybePostfixModifierPosition: f } = o(v); if (p) { l = v + (l.length > 0 ? " " + l : l); continue; } let y = !!f, g = r(y ? b.substring(0, f) : b); if (!g) { if (!y) { l = v + (l.length > 0 ? " " + l : l); continue; } if (g = r(b), !g) { l = v + (l.length > 0 ? " " + l : l); continue; } y = !1; } const x = a(m).join(":"), E = u ? x + ln : x, S = E + g; if (i.includes(S)) continue; i.push(S); const N = n(g, y); for (let _ = 0; _ < N.length; ++_) { const C = N[_]; i.push(E + C); } l = v + (l.length > 0 ? " " + l : l); } return l; }; function xl() { let e = 0, t, o, r = ""; for (; e < arguments.length; ) (t = arguments[e++]) && (o = ui(t)) && (r && (r += " "), r += o); return r; } const ui = (e) => { if (typeof e == "string") return e; let t, o = ""; for (let r = 0; r < e.length; r++) e[r] && (t = ui(e[r])) && (o && (o += " "), o += t); return o; }; function El(e, ...t) { let o, r, n, a = i; function i(l) { const d = t.reduce((v, p) => p(v), e()); return o = bl(d), r = o.cache.get, n = o.cache.set, a = s, s(l); } function s(l) { const d = r(l); if (d) return d; const v = wl(l, o); return n(l, v), v; } return function() { return a(xl.apply(null, arguments)); }; } const Fe = (e) => { const t = (o) => o[e] || []; return t.isThemeGetter = !0, t; }, vi = /^\[(?:(\w[\w-]*):)?(.+)\]$/i, fi = /^\((?:(\w[\w-]*):)?(.+)\)$/i, kl = /^\d+\/\d+$/, Sl = /^(\d+(\.\d+)?)?(xs|sm|md|lg|xl)$/, Cl = /\d+(%|px|r?em|[sdl]?v([hwib]|min|max)|pt|pc|in|cm|mm|cap|ch|ex|r?lh|cq(w|h|i|b|min|max))|\b(calc|min|max|clamp)\(.+\)|^0$/, Nl = /^(rgba?|hsla?|hwb|(ok)?(lab|lch)|color-mix)\(.+\)$/, Rl = /^(inset_)?-?((\d+)?\.?(\d+)[a-z]+|0)_-?((\d+)?\.?(\d+)[a-z]+|0)/, Il = /^(url|image|image-set|cross-fade|element|(repeating-)?(linear|radial|conic)-gradient)\(.+\)$/, oo = (e) => kl.test(e), ue = (e) => !!e && !Number.isNaN(Number(e)), Mt = (e) => !!e && Number.isInteger(Number(e)), Ur = (e) => e.endsWith("%") && ue(e.slice(0, -1)), Tt = (e) => Sl.test(e), _l = () => !0, Ol = (e) => ( // `colorFunctionRegex` check is necessary because color functions can have percentages in them which which would be incorrectly classified as lengths. // For example, `hsl(0 0% 0%)` would be classified as a length without this check. // I could also use lookbehind assertion in `lengthUnitRegex` but that isn't supported widely enough. Cl.test(e) && !Nl.test(e) ), mi = () => !1, Tl = (e) => Rl.test(e), Pl = (e) => Il.test(e), Al = (e) => !V(e) && !$(e), zl = (e) => ho(e, gi, mi), V = (e) => vi.test(e), Gt = (e) => ho(e, bi, Ol), Wr = (e) => ho(e, Fl, ue), sa = (e) => ho(e, pi, mi), Dl = (e) => ho(e, hi, Pl), er = (e) => ho(e, yi, Tl), $ = (e) => fi.test(e), wo = (e) => go(e, bi), Ml = (e) => go(e, Vl), la = (e) => go(e, pi), Ll = (e) => go(e, gi), jl = (e) => go(e, hi), tr = (e) => go(e, yi, !0), ho = (e, t, o) => { const r = vi.exec(e); return r ? r[1] ? t(r[1]) : o(r[2]) : !1; }, go = (e, t, o = !1) => { const r = fi.exec(e); return r ? r[1] ? t(r[1]) : o : !1; }, pi = (e) => e === "position" || e === "percentage", hi = (e) => e === "image" || e === "url", gi = (e) => e === "length" || e === "size" || e === "bg-size", bi = (e) => e === "length", Fl = (e) => e === "number", Vl = (e) => e === "family-name", yi = (e) => e === "shadow", $l = () => { const e = Fe("color"), t = Fe("font"), o = Fe("text"), r = Fe("font-weight"), n = Fe("tracking"), a = Fe("leading"), i = Fe("breakpoint"), s = Fe("container"), l = Fe("spacing"), d = Fe("radius"), v = Fe("shadow"), p = Fe("inset-shadow"), m = Fe("text-shadow"), u = Fe("drop-shadow"), b = Fe("blur"), f = Fe("perspective"), y = Fe("aspect"), g = Fe("ease"), x = Fe("animate"), E = () => ["auto", "avoid", "all", "avoid-page", "page", "left", "right", "column"], S = () => [ "center", "top", "bottom", "left", "right", "top-left", // Deprecated since Tailwind CSS v4.1.0, see https://github.com/tailwindlabs/tailwindcss/pull/17378 "left-top", "top-right", // Deprecated since Tailwind CSS v4.1.0, see https://github.com/tailwindlabs/tailwindcss/pull/17378 "right-top", "bottom-right", // Deprecated since Tailwind CSS v4.1.0, see https://github.com/tailwindlabs/tailwindcss/pull/17378 "right-bottom", "bottom-left", // Deprecated since Tailwind CSS v4.1.0, see https://github.com/tailwindlabs/tailwindcss/pull/17378 "left-bottom" ], N = () => [...S(), $, V], _ = () => ["auto", "hidden", "clip", "visible", "scroll"], C = () => ["auto", "contain", "none"], k = () => [$, V, l], O = () => [oo, "full", "auto", ...k()], D = () => [Mt, "none", "subgrid", $, V], P = () => ["auto", { span: ["full", Mt, $, V] }, Mt, $, V], j = () => [Mt, "auto", $, V], re = () => ["auto", "min", "max", "fr", $, V], X = () => ["start", "end", "center", "between", "around", "evenly", "stretch", "baseline", "center-safe", "end-safe"], se = () => ["start", "end", "center", "stretch", "center-safe", "end-safe"], G = () => ["auto", ...k()], oe = () => [oo, "auto", "full", "dvw", "dvh", "lvw", "lvh", "svw", "svh", "min", "max", "fit", ...k()], A = () => [e, $, V], B = () => [...S(), la, sa, { position: [$, V] }], ve = () => ["no-repeat", { repeat: ["", "x", "y", "space", "round"] }], pe = () => ["auto", "cover", "contain", Ll, zl, { size: [$, V] }], Z = () => [Ur, wo, Gt], Y = () => [ // Deprecated since Tailwind CSS v4.0.0 "", "none", "full", d, $, V ], H = () => ["", ue, wo, Gt], ke = () => ["solid", "dashed", "dotted", "double"], Pe = () => ["normal", "multiply", "screen", "overlay", "darken", "lighten", "color-dodge", "color-burn", "hard-light", "soft-light", "difference", "exclusion", "hue", "saturation", "color", "luminosity"], U = () => [ue, Ur, la, sa], Se = () => [ // Deprecated since Tailwind CSS v4.0.0 "", "none", b, $, V ], he = () => ["none", ue, $, V], we = () => ["none", ue, $, V], ce = () => [ue, $, V], M = () => [oo, "full", ...k()]; return { cacheSize: 500, theme: { animate: ["spin", "ping", "pulse", "bounce"], aspect: ["video"], blur: [Tt], breakpoint: [Tt], color: [_l], container: [Tt], "drop-shadow": [Tt], ease: ["in", "out", "in-out"], font: [Al], "font-weight": ["thin", "extralight", "light", "normal", "medium", "semibold", "bold", "extrabold", "black"], "inset-shadow": [Tt], leading: ["none", "tight", "snug", "normal", "relaxed", "loose"], perspective: ["dramatic", "near", "normal", "midrange", "distant", "none"], radius: [Tt], shadow: [Tt], spacing: ["px", ue], text: [Tt], "text-shadow": [Tt], tracking: ["tighter", "tight", "normal", "wide", "wider", "widest"] }, classGroups: { // -------------- // --- Layout --- // -------------- /** * Aspect Ratio * @see https://tailwindcss.com/docs/aspect-ratio */ aspect: [{ aspect: ["auto", "square", oo, V, $, y] }], /** * Container * @see https://tailwindcss.com/docs/container * @deprecated since Tailwind CSS v4.0.0 */ container: ["container"], /** * Columns * @see https://tailwindcss.com/docs/columns */ columns: [{ columns: [ue, V, $, s] }], /** * Break After * @see https://tailwindcss.com/docs/break-after */ "break-after": [{ "break-after": E() }], /** * Break Before * @see https://tailwindcss.com/docs/break-before */ "break-before": [{ "break-before": E() }], /** * Break Inside * @see https://tailwindcss.com/docs/break-inside */ "break-inside": [{ "break-inside": ["auto", "avoid", "avoid-page", "avoid-column"] }], /** * Box Decoration Break * @see https://tailwindcss.com/docs/box-decoration-break */ "box-decoration": [{ "box-decoration": ["slice", "clone"] }], /** * Box Sizing * @see https://tailwindcss.com/docs/box-sizing */ box: [{ box: ["border", "content"] }], /** * Display * @see https://tailwindcss.com/docs/display */ display: ["block", "inline-block", "inline", "flex", "inline-flex", "table", "inline-table", "table-caption", "table-cell", "table-column", "table-column-group", "table-footer-group", "table-header-group", "table-row-group", "table-row", "flow-root", "grid", "inline-grid", "contents", "list-item", "hidden"], /** * Screen Reader Only * @see https://tailwindcss.com/docs/display#screen-reader-only */ sr: ["sr-only", "not-sr-only"], /** * Floats * @see https://tailwindcss.com/docs/float */ float: [{ float: ["right", "left", "none", "start", "end"] }], /** * Clear * @see https://tailwindcss.com/docs/clear */ clear: [{ clear: ["left", "right", "both", "none", "start", "end"] }], /** * Isolation * @see https://tailwindcss.com/docs/isolation */ isolation: ["isolate", "isolation-auto"], /** * Object Fit * @see https://tailwindcss.com/docs/object-fit */ "object-fit": [{ object: ["contain", "cover", "fill", "none", "scale-down"] }], /** * Object Position * @see https://tailwindcss.com/docs/object-position */ "object-position": [{ object: N() }], /** * Overflow * @see https://tailwindcss.com/docs/overflow */ overflow: [{ overflow: _() }], /** * Overflow X * @see https://tailwindcss.com/docs/overflow */ "overflow-x": [{ "overflow-x": _() }], /** * Overflow Y * @see https://tailwindcss.com/docs/overflow */ "overflow-y": [{ "overflow-y": _() }], /** * Overscroll Behavior * @see https://tailwindcss.com/docs/overscroll-behavior */ overscroll: [{ overscroll: C() }], /** * Overscroll Behavior X * @see https://tailwindcss.com/docs/overscroll-behavior */ "overscroll-x": [{ "overscroll-x": C() }], /** * Overscroll Behavior Y * @see https://tailwindcss.com/docs/overscroll-behavior */ "overscroll-y": [{ "overscroll-y": C() }], /** * Position * @see https://tailwindcss.com/docs/position */ position: ["static", "fixed", "absolute", "relative", "sticky"], /** * Top / Right / Bottom / Left * @see https://tailwindcss.com/docs/top-right-bottom-left */ inset: [{ inset: O() }], /** * Right / Left * @see https://tailwindcss.com/docs/top-right-bottom-left */ "inset-x": [{ "inset-x": O() }], /** * Top / Bottom * @see https://tailwindcss.com/docs/top-right-bottom-left */ "inset-y": [{ "inset-y": O() }], /** * Start * @see https://tailwindcss.com/docs/top-right-bottom-left */ start: [{ start: O() }], /** * End * @see https://tailwindcss.com/docs/top-right-bottom-left */ end: [{ end: O() }], /** * Top * @see https://tailwindcss.com/docs/top-right-bottom-left */ top: [{ top: O() }], /** * Right * @see https://tailwindcss.com/docs/top-right-bottom-left */ right: [{ right: O() }], /** * Bottom * @see https://tailwindcss.com/docs/top-right-bottom-left */ bottom: [{ bottom: O() }], /** * Left * @see https://tailwindcss.com/docs/top-right-bottom-left */ left: [{ left: O() }], /** * Visibility * @see https://tailwindcss.com/docs/visibility */ visibility: ["visible", "invisible", "collapse"], /** * Z-Index * @see https://tailwindcss.com/docs/z-index */ z: [{ z: [Mt, "auto", $, V] }], // ------------------------ // --- Flexbox and Grid --- // ------------------------ /** * Flex Basis * @see https://tailwindcss.com/docs/flex-basis */ basis: [{ basis: [oo, "full", "auto", s, ...k()] }], /** * Flex Direction * @see https://tailwindcss.com/docs/flex-direction */ "flex-direction": [{ flex: ["row", "row-reverse", "col", "col-reverse"] }], /** * Flex Wrap * @see https://tailwindcss.com/docs/flex-wrap */ "flex-wrap": [{ flex: ["nowrap", "wrap", "wrap-reverse"] }], /** * Flex * @see https://tailwindcss.com/docs/flex */ flex: [{ flex: [ue, oo, "auto", "initial", "none", V] }], /** * Flex Grow * @see https://tailwindcss.com/docs/flex-grow */ grow: [{ grow: ["", ue, $, V] }], /** * Flex Shrink * @see https://tailwindcss.com/docs/flex-shrink */ shrink: [{ shrink: ["", ue, $, V] }], /** * Order * @see https://tailwindcss.com/docs/order */ order: [{ order: [Mt, "first", "last", "none", $, V] }], /** * Grid Template Columns * @see https://tailwindcss.com/docs/grid-template-columns */ "grid-cols": [{ "grid-cols": D() }], /** * Grid Column Start / End * @see https://tailwindcss.com/docs/grid-column */ "col-start-end": [{ col: P() }], /** * Grid Column Start * @see https://tailwindcss.com/docs/grid-column */ "col-start": [{ "col-start": j() }], /** * Grid Column End * @see https://tailwindcss.com/docs/grid-column */ "col-end": [{ "col-end": j() }], /** * Grid Template Rows * @see https://tailwindcss.com/docs/grid-template-rows */ "grid-rows": [{ "grid-rows": D() }], /** * Grid Row Start / End * @see https://tailwindcss.com/docs/grid-row */ "row-start-end": [{ row: P() }], /** * Grid Row Start * @see https://tailwindcss.com/docs/grid-row */ "row-start": [{ "row-start": j() }], /** * Grid Row End * @see https://tailwindcss.com/docs/grid-row */ "row-end": [{ "row-end": j() }], /** * Grid Auto Flow * @see https://tailwindcss.com/docs/grid-auto-flow */ "grid-flow": [{ "grid-flow": ["row", "col", "dense", "row-dense", "col-dense"] }], /** * Grid Auto Columns * @see https://tailwindcss.com/docs/grid-auto-columns */ "auto-cols": [{ "auto-cols": re() }], /** * Grid Auto Rows * @see https://tailwindcss.com/docs/grid-auto-rows */ "auto-rows": [{ "auto-rows": re() }], /** * Gap * @see https://tailwindcss.com/docs/gap */ gap: [{ gap: k() }], /** * Gap X * @see https://tailwindcss.com/docs/gap */ "gap-x": [{ "gap-x": k() }], /** * Gap Y * @see https://tailwindcss.com/docs/gap */ "gap-y": [{ "gap-y": k() }], /** * Justify Content * @see https://tailwindcss.com/docs/justify-content */ "justify-content": [{ justify: [...X(), "normal"] }], /** * Justify Items * @see https://tailwindcss.com/docs/justify-items */ "justify-items": [{ "justify-items": [...se(), "normal"] }], /** * Justify Self * @see https://tailwindcss.com/docs/justify-self */ "justify-self": [{ "justify-self": ["auto", ...se()] }], /** * Align Content * @see https://tailwindcss.com/docs/align-content */ "align-content": [{ content: ["normal", ...X()] }], /** * Align Items * @see https://tailwindcss.com/docs/align-items */ "align-items": [{ items: [...se(), { baseline: ["", "last"] }] }], /** * Align Self * @see https://tailwindcss.com/docs/align-self */ "align-self": [{ self: ["auto", ...se(), { baseline: ["", "last"] }] }], /** * Place Content * @see https://tailwindcss.com/docs/place-content */ "place-content": [{ "place-content": X() }], /** * Place Items * @see https://tailwindcss.com/docs/place-items */ "place-items": [{ "place-items": [...se(), "baseline"] }], /** * Place Self * @see https://tailwindcss.com/docs/place-self */ "place-self": [{ "place-self": ["auto", ...se()] }], // Spacing /** * Padding * @see https://tailwindcss.com/docs/padding */ p: [{ p: k() }], /** * Padding X * @see https://tailwindcss.com/docs/padding */ px: [{ px: k() }], /** * Padding Y * @see https://tailwindcss.com/docs/padding */ py: [{ py: k() }], /** * Padding Start * @see https://tailwindcss.com/docs/padding */ ps: [{ ps: k() }], /** * Padding End * @see https://tailwindcss.com/docs/padding */ pe: [{ pe: k() }], /** * Padding Top * @see https://tailwindcss.com/docs/padding */ pt: [{ pt: k() }], /** * Padding Right * @see https://tailwindcss.com/docs/padding */ pr: [{ pr: k() }], /** * Padding Bottom * @see https://tailwindcss.com/docs/padding */ pb: [{ pb: k() }], /** * Padding Left * @see https://tailwindcss.com/docs/padding */ pl: [{ pl: k() }], /** * Margin * @see https://tailwindcss.com/docs/margin */ m: [{ m: G() }], /** * Margin X * @see https://tailwindcss.com/docs/margin */ mx: [{ mx: G() }], /** * Margin Y * @see https://tailwindcss.com/docs/margin */ my: [{ my: G() }], /** * Margin Start * @see https://tailwindcss.com/docs/margin */ ms: [{ ms: G() }], /** * Margin End * @see https://tailwindcss.com/docs/margin */ me: [{ me: G() }], /** * Margin Top * @see https://tailwindcss.com/docs/margin */ mt: [{ mt: G() }], /** * Margin Right * @see https://tailwindcss.com/docs/margin */ mr: [{ mr: G() }], /** * Margin Bottom * @see https://tailwindcss.com/docs/margin */ mb: [{ mb: G() }], /** * Margin Left * @see https://tailwindcss.com/docs/margin */ ml: [{ ml: G() }], /** * Space Between X * @see https://tailwindcss.com/docs/margin#adding-space-between-children */ "space-x": [{ "space-x": k() }], /** * Space Between X Reverse * @see https://tailwindcss.com/docs/margin#adding-space-between-children */ "space-x-reverse": ["space-x-reverse"], /** * Space Between Y * @see https://tailwindcss.com/docs/margin#adding-space-between-children */ "space-y": [{ "space-y": k() }], /** * Space Between Y Reverse * @see https://tailwindcss.com/docs/margin#adding-space-between-children */ "space-y-reverse": ["space-y-reverse"], // -------------- // --- Sizing --- // -------------- /** * Size * @see https://tailwindcss.com/docs/width#setting-both-width-and-height */ size: [{ size: oe() }], /** * Width * @see https://tailwindcss.com/docs/width */ w: [{ w: [s, "screen", ...oe()] }], /** * Min-Width * @see https://tailwindcss.com/docs/min-width */ "min-w": [{ "min-w": [ s, "screen", /** Deprecated. @see https://github.com/tailwindlabs/tailwindcss.com/issues/2027#issuecomment-2620152757 */ "none", ...oe() ] }], /** * Max-Width * @see https://tailwindcss.com/docs/max-width */ "max-w": [{ "max-w": [ s, "screen", "none", /** Deprecated since Tailwind CSS v4.0.0. @see https://github.com/tailwindlabs/tailwindcss.com/issues/2027#issuecomment-2620152757 */ "prose", /** Deprecated since Tailwind CSS v4.0.0. @see https://github.com/tailwindlabs/tailwindcss.com/issues/2027#issuecomment-2620152757 */ { screen: [i] }, ...oe() ] }], /** * Height * @see https://tailwindcss.com/docs/height */ h: [{ h: ["screen", "lh", ...oe()] }], /** * Min-Height * @see https://tailwindcss.com/docs/min-height */ "min-h": [{ "min-h": ["screen", "lh", "none", ...oe()] }], /** * Max-Height * @see https://tailwindcss.com/docs/max-height */ "max-h": [{ "max-h": ["screen", "lh", ...oe()] }], // ------------------ // --- Typography --- // ------------------ /** * Font Size * @see https://tailwindcss.com/docs/font-size */ "font-size": [{ text: ["base", o, wo, Gt] }], /** * Font Smoothing * @see https://tailwindcss.com/docs/font-smoothing */ "font-smoothing": ["antialiased", "subpixel-antialiased"], /** * Font Style * @see https://tailwindcss.com/docs/font-style */ "font-style": ["italic", "not-italic"], /** * Font Weight * @see https://tailwindcss.com/docs/font-weight */ "font-weight": [{ font: [r,