@a4ui/core 0.16.0 → 0.18.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.
Files changed (40) hide show
  1. package/dist/{Checkbox-B5Gb3h5J.js → Checkbox-BZjX1GMG.js} +153 -146
  2. package/dist/commerce/ProductCard.d.ts +10 -0
  3. package/dist/commerce/createCart.d.ts +53 -0
  4. package/dist/commerce/index.d.ts +1 -0
  5. package/dist/commerce.js +160 -133
  6. package/dist/elements.css +244 -0
  7. package/dist/elements.iife.js +3 -3
  8. package/dist/elements.js +590 -583
  9. package/dist/full.css +244 -0
  10. package/dist/index.d.ts +5 -1
  11. package/dist/index.js +3090 -2798
  12. package/dist/layout/ActionBar.d.ts +53 -0
  13. package/dist/layout/Section.d.ts +31 -0
  14. package/dist/styles.css +66 -0
  15. package/dist/ui/Badge.d.ts +6 -0
  16. package/dist/ui/BeforeAfter.d.ts +34 -0
  17. package/dist/ui/Carousel.d.ts +6 -0
  18. package/dist/ui/FloatingActionButton.d.ts +6 -0
  19. package/dist/ui/Image.d.ts +6 -0
  20. package/dist/ui/List.d.ts +5 -0
  21. package/dist/ui/PricingTable.d.ts +60 -0
  22. package/dist/ui/Skeleton.d.ts +10 -3
  23. package/package.json +1 -1
  24. package/src/commerce/ProductCard.tsx +26 -2
  25. package/src/commerce/createCart.ts +102 -0
  26. package/src/commerce/index.ts +1 -0
  27. package/src/index.ts +5 -1
  28. package/src/layout/ActionBar.tsx +121 -0
  29. package/src/layout/Section.tsx +69 -0
  30. package/src/ui/Accordion.tsx +3 -1
  31. package/src/ui/Badge.tsx +14 -2
  32. package/src/ui/BeforeAfter.tsx +162 -0
  33. package/src/ui/Carousel.tsx +48 -3
  34. package/src/ui/Collapse.tsx +13 -4
  35. package/src/ui/FloatingActionButton.tsx +16 -1
  36. package/src/ui/Image.tsx +29 -1
  37. package/src/ui/List.tsx +10 -2
  38. package/src/ui/PricingTable.tsx +196 -0
  39. package/src/ui/Skeleton.tsx +17 -5
  40. package/src/ui/SpeedDial.tsx +3 -1
@@ -1,66 +1,73 @@
1
- import { spread as p, mergeProps as y, insert as f, template as g, effect as h, className as v, use as w, delegateEvents as k, createComponent as $, setAttribute as C } from "solid-js/web";
2
- import { splitProps as b, createSignal as _, createEffect as H, untrack as P, onCleanup as E, onMount as S, Show as K, For as T } from "solid-js";
1
+ import { spread as y, mergeProps as b, insert as f, createComponent as p, template as g, effect as h, className as v, use as $, delegateEvents as k, setAttribute as C } from "solid-js/web";
2
+ import { splitProps as x, Show as P, createSignal as _, createEffect as K, untrack as F, onCleanup as E, onMount as S, For as T } from "solid-js";
3
3
  import { c as m } from "./cn-B6yFEsav.js";
4
4
  import { animate as L, inView as Q } from "motion";
5
5
  import { Star as B } from "lucide-solid";
6
- var q = /* @__PURE__ */ g("<span>");
7
- const J = {
6
+ var q = /* @__PURE__ */ g('<span class="relative flex h-1.5 w-1.5"aria-hidden=true><span class="absolute inline-flex h-full w-full animate-ping rounded-full bg-current opacity-75"></span><span class="relative inline-flex h-1.5 w-1.5 rounded-full bg-current">'), J = /* @__PURE__ */ g("<span>");
7
+ const W = {
8
8
  neutral: "bg-muted text-muted-foreground ring-border",
9
9
  success: "bg-emerald-500/15 text-emerald-600 ring-emerald-500/30",
10
10
  warning: "bg-amber-500/15 text-amber-600 ring-amber-500/30",
11
11
  danger: "bg-rose-500/15 text-rose-600 ring-rose-500/30",
12
12
  info: "bg-sky-500/15 text-sky-600 ring-sky-500/30"
13
- }, W = "badge inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-xs font-semibold ring-1 ring-inset whitespace-nowrap";
13
+ }, Z = "badge inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-xs font-semibold ring-1 ring-inset whitespace-nowrap";
14
14
  function $e(t) {
15
- const [e, r] = b(t, ["tone", "class", "children"]);
15
+ const [e, r] = x(t, ["tone", "class", "children", "pulse"]);
16
16
  return (() => {
17
- var n = q();
18
- return p(n, y({
17
+ var n = J();
18
+ return y(n, b({
19
19
  get class() {
20
- return m(W, J[e.tone ?? "neutral"], e.class);
20
+ return m(Z, W[e.tone ?? "neutral"], e.class);
21
21
  }
22
- }, r), !1, !0), f(n, () => e.children), n;
22
+ }, r), !1, !0), f(n, p(P, {
23
+ get when() {
24
+ return e.pulse;
25
+ },
26
+ get children() {
27
+ return q();
28
+ }
29
+ }), null), f(n, () => e.children, null), n;
23
30
  })();
24
31
  }
25
- const F = "a4ui-effects";
26
- function I() {
32
+ const I = "a4ui-effects";
33
+ function Y() {
27
34
  try {
28
35
  return window.localStorage;
29
36
  } catch {
30
37
  return null;
31
38
  }
32
39
  }
33
- function Z() {
40
+ function ee() {
34
41
  var e;
35
42
  try {
36
43
  if (new URLSearchParams(window.location.search).get("calm") === "1") return !1;
37
44
  } catch {
38
45
  }
39
- const t = (e = I()) == null ? void 0 : e.getItem(F);
46
+ const t = (e = Y()) == null ? void 0 : e.getItem(I);
40
47
  return t === null ? !0 : t === "1";
41
48
  }
42
- function Y(t) {
49
+ function N(t) {
43
50
  typeof document > "u" || document.documentElement.classList.toggle("calm", !t);
44
51
  }
45
- const N = Z();
46
- Y(N);
47
- const [U, ee] = _(N);
48
- function we() {
49
- return U;
52
+ const U = ee();
53
+ N(U);
54
+ const [z, te] = _(U);
55
+ function _e() {
56
+ return z;
50
57
  }
51
- function te() {
52
- return !U();
58
+ function ne() {
59
+ return !z();
53
60
  }
54
- function _e(t) {
61
+ function Ee(t) {
55
62
  var e;
56
- (e = I()) == null || e.setItem(F, t ? "1" : "0"), Y(t), ee(t);
63
+ (e = Y()) == null || e.setItem(I, t ? "1" : "0"), N(t), te(t);
57
64
  }
58
- const ne = "(prefers-reduced-motion: reduce)";
59
- function re() {
60
- return typeof window > "u" || typeof window.matchMedia != "function" ? !1 : window.matchMedia(ne).matches;
65
+ const re = "(prefers-reduced-motion: reduce)";
66
+ function oe() {
67
+ return typeof window > "u" || typeof window.matchMedia != "function" ? !1 : window.matchMedia(re).matches;
61
68
  }
62
- const z = "a4ui-motion-forced";
63
- function X() {
69
+ const X = "a4ui-motion-forced";
70
+ function j() {
64
71
  try {
65
72
  return window.localStorage;
66
73
  } catch {
@@ -68,44 +75,44 @@ function X() {
68
75
  }
69
76
  }
70
77
  var D;
71
- const [R, oe] = _(((D = X()) == null ? void 0 : D.getItem(z)) === "1");
72
- typeof document < "u" && document.documentElement.classList.toggle("force-motion", P(R));
73
- function Ee() {
78
+ const [R, ae] = _(((D = j()) == null ? void 0 : D.getItem(X)) === "1");
79
+ typeof document < "u" && document.documentElement.classList.toggle("force-motion", F(R));
80
+ function Ce() {
74
81
  return R;
75
82
  }
76
- function Ce(t) {
83
+ function ke(t) {
77
84
  var e;
78
- (e = X()) == null || e.setItem(z, t ? "1" : "0"), typeof document < "u" && document.documentElement.classList.toggle("force-motion", t), oe(t);
85
+ (e = j()) == null || e.setItem(X, t ? "1" : "0"), typeof document < "u" && document.documentElement.classList.toggle("force-motion", t), ae(t);
79
86
  }
80
- function x() {
81
- return te() || re() && !R();
87
+ function w() {
88
+ return ne() || oe() && !R();
82
89
  }
83
- function ke(t, e = 600) {
90
+ function Se(t, e = 600) {
84
91
  const [r, n] = _(0);
85
92
  let o;
86
- return H(() => {
93
+ return K(() => {
87
94
  const a = t();
88
- if (o == null || o.stop(), x()) {
95
+ if (o == null || o.stop(), w()) {
89
96
  n(a);
90
97
  return;
91
98
  }
92
- const s = P(r);
93
- s !== a && (o = L(s, a, {
99
+ const l = F(r);
100
+ l !== a && (o = L(l, a, {
94
101
  duration: e / 1e3,
95
102
  ease: "easeOut",
96
103
  onUpdate: (u) => n(u)
97
104
  }));
98
105
  }), E(() => o == null ? void 0 : o.stop()), r;
99
106
  }
100
- function Se(t, e = {}) {
101
- x() || L(
107
+ function Le(t, e = {}) {
108
+ w() || L(
102
109
  t,
103
110
  { opacity: [0, 1], y: [e.y ?? 8, 0] },
104
111
  { duration: e.duration ?? 0.32, delay: e.delay ?? 0, ease: "easeOut" }
105
112
  );
106
113
  }
107
- function Le(t, e = {}) {
108
- if (x()) return () => {
114
+ function Re(t, e = {}) {
115
+ if (w()) return () => {
109
116
  };
110
117
  t.style.opacity = "0";
111
118
  let r = !1;
@@ -121,22 +128,22 @@ function Le(t, e = {}) {
121
128
  { amount: e.amount ?? 0.2 }
122
129
  );
123
130
  }
124
- var ae = /* @__PURE__ */ g("<span>");
125
- function j(t, e, r = {}) {
126
- if (x()) return;
127
- const n = t.getBoundingClientRect(), o = e.clientX - n.left, a = e.clientY - n.top, s = 2 * Math.max(Math.hypot(o, a), Math.hypot(n.width - o, a), Math.hypot(o, n.height - a), Math.hypot(n.width - o, n.height - a)), u = document.createElement("span");
131
+ var ie = /* @__PURE__ */ g("<span>");
132
+ function G(t, e, r = {}) {
133
+ if (w()) return;
134
+ const n = t.getBoundingClientRect(), o = e.clientX - n.left, a = e.clientY - n.top, l = 2 * Math.max(Math.hypot(o, a), Math.hypot(n.width - o, a), Math.hypot(o, n.height - a), Math.hypot(n.width - o, n.height - a)), u = document.createElement("span");
128
135
  u.setAttribute("aria-hidden", "true"), Object.assign(u.style, {
129
136
  position: "absolute",
130
137
  left: `${o}px`,
131
138
  top: `${a}px`,
132
- width: `${s}px`,
133
- height: `${s}px`,
139
+ width: `${l}px`,
140
+ height: `${l}px`,
134
141
  borderRadius: "9999px",
135
142
  background: r.color ?? "currentColor",
136
143
  pointerEvents: "none",
137
144
  transform: "translate(-50%,-50%) scale(0)"
138
145
  }), t.appendChild(u);
139
- const l = u.animate([{
146
+ const s = u.animate([{
140
147
  transform: "translate(-50%,-50%) scale(0)",
141
148
  opacity: String(r.opacity ?? 0.3)
142
149
  }, {
@@ -146,93 +153,93 @@ function j(t, e, r = {}) {
146
153
  duration: 600,
147
154
  easing: "ease-out"
148
155
  }), i = () => u.remove();
149
- l.finished.then(i).catch(i);
156
+ s.finished.then(i).catch(i);
150
157
  }
151
- function Re(t) {
158
+ function Me(t) {
152
159
  let e;
153
160
  const r = (n) => {
154
- e && j(e, n, {
161
+ e && G(e, n, {
155
162
  color: t.color,
156
163
  opacity: t.opacity
157
164
  });
158
165
  };
159
166
  return (() => {
160
- var n = ae();
167
+ var n = ie();
161
168
  n.$$pointerdown = r;
162
169
  var o = e;
163
- return typeof o == "function" ? w(o, n) : e = n, f(n, () => t.children), h(() => v(n, m("relative inline-block overflow-hidden", t.class))), n;
170
+ return typeof o == "function" ? $(o, n) : e = n, f(n, () => t.children), h(() => v(n, m("relative inline-block overflow-hidden", t.class))), n;
164
171
  })();
165
172
  }
166
173
  k(["pointerdown"]);
167
- var ie = /* @__PURE__ */ g("<button>");
174
+ var le = /* @__PURE__ */ g("<button>");
168
175
  const se = {
169
176
  primary: "bg-primary text-primary-foreground hover:bg-primary/90",
170
177
  secondary: "bg-muted text-foreground hover:bg-muted/70",
171
178
  outline: "border border-border bg-transparent text-foreground hover:bg-muted",
172
179
  ghost: "bg-transparent text-foreground hover:bg-muted"
173
- }, le = "inline-flex items-center justify-center rounded-md px-3 py-2 text-sm font-medium transition-[color,background-color,transform] duration-150 active:scale-[0.97] focus:outline-none focus:ring-2 focus:ring-ring disabled:pointer-events-none disabled:opacity-50";
174
- function Me(t) {
175
- const [e, r] = b(t, ["variant", "class", "type", "children", "ripple", "onPointerDown"]), n = (o) => {
176
- e.ripple && j(o.currentTarget, o, {
180
+ }, ce = "inline-flex items-center justify-center rounded-md px-3 py-2 text-sm font-medium transition-[color,background-color,transform] duration-150 active:scale-[0.97] focus:outline-none focus:ring-2 focus:ring-ring disabled:pointer-events-none disabled:opacity-50";
181
+ function Ae(t) {
182
+ const [e, r] = x(t, ["variant", "class", "type", "children", "ripple", "onPointerDown"]), n = (o) => {
183
+ e.ripple && G(o.currentTarget, o, {
177
184
  opacity: 0.35
178
185
  });
179
186
  const a = e.onPointerDown;
180
187
  typeof a == "function" ? a(o) : a && a[0](a[1], o);
181
188
  };
182
189
  return (() => {
183
- var o = ie();
184
- return o.$$pointerdown = n, p(o, y({
190
+ var o = le();
191
+ return o.$$pointerdown = n, y(o, b({
185
192
  get type() {
186
193
  return e.type ?? "button";
187
194
  },
188
195
  get class() {
189
- return m(le, se[e.variant ?? "primary"], e.ripple && "relative overflow-hidden", e.class);
196
+ return m(ce, se[e.variant ?? "primary"], e.ripple && "relative overflow-hidden", e.class);
190
197
  }
191
198
  }, r), !1, !0), f(o, () => e.children), o;
192
199
  })();
193
200
  }
194
201
  k(["pointerdown"]);
195
- var ce = /* @__PURE__ */ g("<div>");
196
- function G(t, e = {}) {
197
- if (x()) return () => {
202
+ var ue = /* @__PURE__ */ g("<div>");
203
+ function V(t, e = {}) {
204
+ if (w()) return () => {
198
205
  };
199
206
  const r = document.createElement("span");
200
207
  r.setAttribute("aria-hidden", "true"), r.className = "pointer-events-none absolute inset-0 opacity-0 transition-opacity duration-300", t.appendChild(r);
201
208
  const n = e.size ?? 180, o = e.color ?? "hsl(var(--primary))", a = (i, c) => {
202
209
  r.style.background = `radial-gradient(${n}px circle at ${i}px ${c}px, color-mix(in srgb, ${o} 30%, transparent), transparent 70%)`;
203
- }, s = (i) => {
210
+ }, l = (i) => {
204
211
  const c = t.getBoundingClientRect();
205
212
  a(i.clientX - c.left, i.clientY - c.top);
206
213
  }, u = () => {
207
214
  r.style.opacity = "1";
208
- }, l = () => {
215
+ }, s = () => {
209
216
  r.style.opacity = "0";
210
217
  };
211
- return t.addEventListener("pointermove", s), t.addEventListener("pointerenter", u), t.addEventListener("pointerleave", l), () => {
212
- t.removeEventListener("pointermove", s), t.removeEventListener("pointerenter", u), t.removeEventListener("pointerleave", l), r.remove();
218
+ return t.addEventListener("pointermove", l), t.addEventListener("pointerenter", u), t.addEventListener("pointerleave", s), () => {
219
+ t.removeEventListener("pointermove", l), t.removeEventListener("pointerenter", u), t.removeEventListener("pointerleave", s), r.remove();
213
220
  };
214
221
  }
215
- function Ae(t) {
222
+ function Oe(t) {
216
223
  let e;
217
224
  return S(() => {
218
- const r = G(e, {
225
+ const r = V(e, {
219
226
  color: t.color,
220
227
  size: t.size
221
228
  });
222
229
  E(r);
223
230
  }), (() => {
224
- var r = ce(), n = e;
225
- return typeof n == "function" ? w(n, r) : e = r, f(r, () => t.children), h(() => v(r, m("relative overflow-hidden", t.class))), r;
231
+ var r = ue(), n = e;
232
+ return typeof n == "function" ? $(n, r) : e = r, f(r, () => t.children), h(() => v(r, m("relative overflow-hidden", t.class))), r;
226
233
  })();
227
234
  }
228
- var ue = /* @__PURE__ */ g("<div style=perspective:800px><div style=transform-style:preserve-3d>");
229
- function V(t, e, r = {}) {
230
- if (x()) return () => {
235
+ var de = /* @__PURE__ */ g("<div style=perspective:800px><div style=transform-style:preserve-3d>");
236
+ function H(t, e, r = {}) {
237
+ if (w()) return () => {
231
238
  };
232
239
  e.style.willChange = "transform";
233
240
  const n = (a) => {
234
- const s = t.getBoundingClientRect(), u = (a.clientX - s.left) / s.width - 0.5, l = (a.clientY - s.top) / s.height - 0.5, i = r.max ?? 10;
235
- e.style.transition = "transform 0.15s ease-out", e.style.transform = `perspective(800px) rotateX(${(l * -2 * i).toFixed(2)}deg) rotateY(${(u * 2 * i).toFixed(2)}deg) scale(1.02)`;
241
+ const l = t.getBoundingClientRect(), u = (a.clientX - l.left) / l.width - 0.5, s = (a.clientY - l.top) / l.height - 0.5, i = r.max ?? 10;
242
+ e.style.transition = "transform 0.15s ease-out", e.style.transform = `perspective(800px) rotateX(${(s * -2 * i).toFixed(2)}deg) rotateY(${(u * 2 * i).toFixed(2)}deg) scale(1.02)`;
236
243
  }, o = () => {
237
244
  e.style.transition = "transform 0.4s ease", e.style.transform = "perspective(800px) rotateX(0deg) rotateY(0deg) scale(1)";
238
245
  };
@@ -240,89 +247,89 @@ function V(t, e, r = {}) {
240
247
  t.removeEventListener("pointermove", n), t.removeEventListener("pointerleave", o), e.style.transform = "", e.style.transition = "", e.style.willChange = "";
241
248
  };
242
249
  }
243
- function Oe(t) {
250
+ function Te(t) {
244
251
  let e, r;
245
252
  return S(() => {
246
- const n = V(e, r, {
253
+ const n = H(e, r, {
247
254
  max: t.max
248
255
  });
249
256
  E(n);
250
257
  }), (() => {
251
- var n = ue(), o = n.firstChild, a = e;
252
- typeof a == "function" ? w(a, n) : e = n;
253
- var s = r;
254
- return typeof s == "function" ? w(s, o) : r = o, f(o, () => t.children), h(() => v(n, m("inline-block", t.class))), n;
258
+ var n = de(), o = n.firstChild, a = e;
259
+ typeof a == "function" ? $(a, n) : e = n;
260
+ var l = r;
261
+ return typeof l == "function" ? $(l, o) : r = o, f(o, () => t.children), h(() => v(n, m("inline-block", t.class))), n;
255
262
  })();
256
263
  }
257
- var M = /* @__PURE__ */ g("<div>"), de = /* @__PURE__ */ g("<h2>");
258
- function Te(t) {
259
- const [e, r] = b(t, ["class", "children", "glass", "glow", "tilt", "spotlight"]), n = () => (e.glow ?? e.glass) === !0;
264
+ var M = /* @__PURE__ */ g("<div>"), fe = /* @__PURE__ */ g("<h2>");
265
+ function Be(t) {
266
+ const [e, r] = x(t, ["class", "children", "glass", "glow", "tilt", "spotlight"]), n = () => (e.glow ?? e.glass) === !0;
260
267
  let o;
261
268
  return S(() => {
262
- const a = [e.tilt && o ? V(o, o) : null, e.spotlight && o ? G(o) : null].filter((s) => s !== null);
263
- E(() => a.forEach((s) => s()));
269
+ const a = [e.tilt && o ? H(o, o) : null, e.spotlight && o ? V(o) : null].filter((l) => l !== null);
270
+ E(() => a.forEach((l) => l()));
264
271
  }), (() => {
265
- var a = M(), s = o;
266
- return typeof s == "function" ? w(s, a) : o = a, p(a, y({
272
+ var a = M(), l = o;
273
+ return typeof l == "function" ? $(l, a) : o = a, y(a, b({
267
274
  get class() {
268
275
  return m(e.glass ? "card rounded-xl text-card-foreground" : "rounded-xl border border-border bg-card text-card-foreground shadow-sm", n() && "glow-edge", e.spotlight && "relative overflow-hidden", e.tilt && "will-change-transform", e.class);
269
276
  }
270
277
  }, r), !1, !0), f(a, () => e.children), a;
271
278
  })();
272
279
  }
273
- function Be(t) {
274
- const [e, r] = b(t, ["class", "children"]);
280
+ function De(t) {
281
+ const [e, r] = x(t, ["class", "children"]);
275
282
  return (() => {
276
283
  var n = M();
277
- return p(n, y({
284
+ return y(n, b({
278
285
  get class() {
279
286
  return m("flex flex-col space-y-1.5 p-6", e.class);
280
287
  }
281
288
  }, r), !1, !0), f(n, () => e.children), n;
282
289
  })();
283
290
  }
284
- function De(t) {
285
- const [e, r] = b(t, ["class", "children"]);
291
+ function Pe(t) {
292
+ const [e, r] = x(t, ["class", "children"]);
286
293
  return (() => {
287
- var n = de();
288
- return p(n, y({
294
+ var n = fe();
295
+ return y(n, b({
289
296
  get class() {
290
297
  return m("text-lg font-semibold leading-none tracking-tight", e.class);
291
298
  }
292
299
  }, r), !1, !0), f(n, () => e.children), n;
293
300
  })();
294
301
  }
295
- function Pe(t) {
296
- const [e, r] = b(t, ["class", "children"]);
302
+ function Fe(t) {
303
+ const [e, r] = x(t, ["class", "children"]);
297
304
  return (() => {
298
305
  var n = M();
299
- return p(n, y({
306
+ return y(n, b({
300
307
  get class() {
301
308
  return m("p-6 pt-0", e.class);
302
309
  }
303
310
  }, r), !1, !0), f(n, () => e.children), n;
304
311
  })();
305
312
  }
306
- var fe = /* @__PURE__ */ g("<div role=radiogroup>"), me = /* @__PURE__ */ g("<div role=img>"), ge = /* @__PURE__ */ g('<button type=button role=radio class="rounded outline-none focus-visible:ring-2 focus-visible:ring-ring/40">');
307
- function Fe(t) {
313
+ var me = /* @__PURE__ */ g("<div role=radiogroup>"), ge = /* @__PURE__ */ g("<div role=img>"), he = /* @__PURE__ */ g('<button type=button role=radio class="rounded outline-none focus-visible:ring-2 focus-visible:ring-ring/40">');
314
+ function Ie(t) {
308
315
  const [e, r] = _(0), n = () => t.max ?? 5, o = () => Array.from({
309
316
  length: n()
310
- }, (l, i) => i + 1), a = () => e() > 0 ? e() : t.value, s = (l) => {
317
+ }, (s, i) => i + 1), a = () => e() > 0 ? e() : t.value, l = (s) => {
311
318
  var i;
312
- t.readonly || (i = t.onChange) == null || i.call(t, l);
313
- }, u = (l) => m("h-5 w-5 transition-colors", l <= a() ? "fill-primary text-primary" : "fill-transparent text-muted-foreground");
314
- return $(K, {
319
+ t.readonly || (i = t.onChange) == null || i.call(t, s);
320
+ }, u = (s) => m("h-5 w-5 transition-colors", s <= a() ? "fill-primary text-primary" : "fill-transparent text-muted-foreground");
321
+ return p(P, {
315
322
  get when() {
316
323
  return !t.readonly;
317
324
  },
318
325
  get fallback() {
319
326
  return (() => {
320
- var l = me();
321
- return f(l, $(T, {
327
+ var s = ge();
328
+ return f(s, p(T, {
322
329
  get each() {
323
330
  return o();
324
331
  },
325
- children: (i) => $(B, {
332
+ children: (i) => p(B, {
326
333
  get class() {
327
334
  return u(i);
328
335
  },
@@ -330,24 +337,24 @@ function Fe(t) {
330
337
  })
331
338
  })), h((i) => {
332
339
  var c = m("inline-flex items-center gap-1", t.class), d = `Rating ${t.value} of ${n()}`;
333
- return c !== i.e && v(l, i.e = c), d !== i.t && C(l, "aria-label", i.t = d), i;
340
+ return c !== i.e && v(s, i.e = c), d !== i.t && C(s, "aria-label", i.t = d), i;
334
341
  }, {
335
342
  e: void 0,
336
343
  t: void 0
337
- }), l;
344
+ }), s;
338
345
  })();
339
346
  },
340
347
  get children() {
341
- var l = fe();
342
- return l.addEventListener("mouseleave", () => r(0)), f(l, $(T, {
348
+ var s = me();
349
+ return s.addEventListener("mouseleave", () => r(0)), f(s, p(T, {
343
350
  get each() {
344
351
  return o();
345
352
  },
346
353
  children: (i) => (() => {
347
- var c = ge();
354
+ var c = he();
348
355
  return c.$$keydown = (d) => {
349
- d.key === "ArrowRight" || d.key === "ArrowUp" ? (d.preventDefault(), s(Math.min(t.value + 1, n()))) : (d.key === "ArrowLeft" || d.key === "ArrowDown") && (d.preventDefault(), s(Math.max(t.value - 1, 0)));
350
- }, c.$$click = () => s(i), c.addEventListener("blur", () => r(0)), c.addEventListener("focus", () => r(i)), c.addEventListener("mouseenter", () => r(i)), f(c, $(B, {
356
+ d.key === "ArrowRight" || d.key === "ArrowUp" ? (d.preventDefault(), l(Math.min(t.value + 1, n()))) : (d.key === "ArrowLeft" || d.key === "ArrowDown") && (d.preventDefault(), l(Math.max(t.value - 1, 0)));
357
+ }, c.$$click = () => l(i), c.addEventListener("blur", () => r(0)), c.addEventListener("focus", () => r(i)), c.addEventListener("mouseenter", () => r(i)), f(c, p(B, {
351
358
  get class() {
352
359
  return u(i);
353
360
  },
@@ -360,41 +367,41 @@ function Fe(t) {
360
367
  t: void 0
361
368
  }), c;
362
369
  })()
363
- })), h(() => v(l, m("inline-flex items-center gap-1", t.class))), l;
370
+ })), h(() => v(s, m("inline-flex items-center gap-1", t.class))), s;
364
371
  }
365
372
  });
366
373
  }
367
374
  k(["click", "keydown"]);
368
- var he = /* @__PURE__ */ g('<label><input type=checkbox class="h-4 w-4 rounded border-input accent-primary">');
369
- function Ie(t) {
375
+ var pe = /* @__PURE__ */ g('<label><input type=checkbox class="h-4 w-4 rounded border-input accent-primary">');
376
+ function Ye(t) {
370
377
  return (() => {
371
- var e = he(), r = e.firstChild;
378
+ var e = pe(), r = e.firstChild;
372
379
  return r.addEventListener("change", (n) => t.onChange(n.currentTarget.checked)), f(e, () => t.label, null), h(() => v(e, m("inline-flex items-center gap-2 text-sm text-foreground", t.class))), h(() => r.checked = t.checked), e;
373
380
  })();
374
381
  }
375
382
  export {
376
383
  $e as B,
377
- Te as C,
378
- Fe as R,
379
- Ae as S,
380
- Oe as T,
381
- Me as a,
382
- Ie as b,
383
- ke as c,
384
- Pe as d,
385
- Se as e,
386
- Be as f,
387
- De as g,
388
- Re as h,
389
- G as i,
384
+ Be as C,
385
+ Ie as R,
386
+ Oe as S,
387
+ Te as T,
388
+ Ae as a,
389
+ Ye as b,
390
+ Se as c,
391
+ Fe as d,
392
+ Le as e,
393
+ De as f,
394
+ Pe as g,
395
+ Ee as h,
396
+ Me as i,
390
397
  V as j,
391
- te as k,
392
- Ce as l,
393
- x as m,
394
- j as n,
395
- Ee as o,
396
- re as p,
397
- Le as r,
398
- _e as s,
399
- we as u
398
+ H as k,
399
+ ne as l,
400
+ w as m,
401
+ ke as n,
402
+ Ce as o,
403
+ oe as p,
404
+ Re as r,
405
+ G as s,
406
+ _e as u
400
407
  };
@@ -19,6 +19,16 @@ export interface ProductCardProps {
19
19
  currency?: string;
20
20
  locale?: string;
21
21
  onAddToCart?: () => void;
22
+ /**
23
+ * 3D hover tilt toward the cursor — forwarded to the underlying {@link Card}
24
+ * ({@link attachTilt}). Engine-free and reduced-motion aware.
25
+ */
26
+ tilt?: boolean;
27
+ /**
28
+ * Cursor-following radial glow inside the card — forwarded to the underlying
29
+ * {@link Card} ({@link attachSpotlight}). Engine-free and reduced-motion aware.
30
+ */
31
+ spotlight?: boolean;
22
32
  class?: string;
23
33
  }
24
34
  /**
@@ -0,0 +1,53 @@
1
+ import { Accessor } from 'solid-js';
2
+ export interface CartProduct {
3
+ id: string | number;
4
+ price: number;
5
+ }
6
+ export interface CartEntry<T extends CartProduct> {
7
+ product: T;
8
+ qty: number;
9
+ }
10
+ export interface Cart<T extends CartProduct> {
11
+ /** Reactive list of cart entries. */
12
+ items: Accessor<CartEntry<T>[]>;
13
+ /** Add a product, or increment its `qty` if it's already in the cart. */
14
+ add: (product: T, qty?: number) => void;
15
+ /** Remove a product from the cart by id. */
16
+ remove: (id: T['id']) => void;
17
+ /** Set a product's quantity. `qty <= 0` removes the entry. */
18
+ setQty: (id: T['id'], qty: number) => void;
19
+ /** Empty the cart. */
20
+ clear: () => void;
21
+ /** Total number of units across all entries. */
22
+ count: () => number;
23
+ /** Sum of `price * qty` across all entries. */
24
+ subtotal: () => number;
25
+ /** Whether a product with this id is currently in the cart. */
26
+ has: (id: T['id']) => boolean;
27
+ }
28
+ /**
29
+ * Create a signal-backed shopping cart store, generic over the product type.
30
+ * `count()` and `subtotal()` are memoized and stay in sync with `items()`.
31
+ *
32
+ * @example
33
+ * ```ts
34
+ * interface Product extends CartProduct {
35
+ * id: string
36
+ * price: number
37
+ * title: string
38
+ * }
39
+ *
40
+ * const cart = createCart<Product>()
41
+ *
42
+ * cart.add({ id: 'sku-1', price: 29.99, title: 'Wireless Mouse' })
43
+ * cart.add({ id: 'sku-1', price: 29.99, title: 'Wireless Mouse' }) // qty -> 2
44
+ * cart.setQty('sku-1', 3)
45
+ *
46
+ * cart.count() // 3
47
+ * cart.subtotal() // 89.97
48
+ *
49
+ * cart.remove('sku-1')
50
+ * cart.has('sku-1') // false
51
+ * ```
52
+ */
53
+ export declare function createCart<T extends CartProduct>(initial?: CartEntry<T>[]): Cart<T>;
@@ -5,3 +5,4 @@ export { ProductGrid, type ProductGridProps } from './ProductGrid';
5
5
  export { CartLine, type CartLineProps } from './CartLine';
6
6
  export { CartSummary, type CartSummaryProps, type CartSummaryItem } from './CartSummary';
7
7
  export { FilterGroup, type FilterGroupProps, type FacetOption } from './FilterGroup';
8
+ export { createCart, type Cart, type CartProduct, type CartEntry } from './createCart';