@a4ui/core 0.8.1 → 0.10.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.
@@ -0,0 +1,21 @@
1
+ import { JSX } from 'solid-js';
2
+ export interface QuantityStepperProps {
3
+ value: number;
4
+ onChange: (value: number) => void;
5
+ /** Minimum allowed value. Defaults to `0`. */
6
+ min?: number;
7
+ /** Maximum allowed value. Defaults to `Number.MAX_SAFE_INTEGER`. */
8
+ max?: number;
9
+ disabled?: boolean;
10
+ class?: string;
11
+ }
12
+ /**
13
+ * Bordered "−"/value/"+" control for adjusting an integer quantity, clamped to
14
+ * `[min, max]`.
15
+ *
16
+ * @example
17
+ * ```tsx
18
+ * <QuantityStepper value={qty()} onChange={setQty} min={1} max={10} />
19
+ * ```
20
+ */
21
+ export declare function QuantityStepper(props: QuantityStepperProps): JSX.Element;
@@ -0,0 +1,7 @@
1
+ export { PriceTag, type PriceTagProps } from './PriceTag';
2
+ export { QuantityStepper, type QuantityStepperProps } from './QuantityStepper';
3
+ export { ProductCard, type ProductCardProps } from './ProductCard';
4
+ export { ProductGrid, type ProductGridProps } from './ProductGrid';
5
+ export { CartLine, type CartLineProps } from './CartLine';
6
+ export { CartSummary, type CartSummaryProps, type CartSummaryItem } from './CartSummary';
7
+ export { FilterGroup, type FilterGroupProps, type FacetOption } from './FilterGroup';
@@ -0,0 +1,282 @@
1
+ import { insert as n, createComponent as u, memo as T, effect as f, className as b, template as s, delegateEvents as C, setAttribute as $ } from "solid-js/web";
2
+ import { Show as v, For as w } from "solid-js";
3
+ import { c as h } from "./cn-B6yFEsav.js";
4
+ import { B as S, C as E, R as F, a as k, b as I } from "./Checkbox-DQcDOBLd.js";
5
+ import { Minus as N, Plus as R, Trash2 as U } from "lucide-solid";
6
+ var j = /* @__PURE__ */ s('<span class="text-muted-foreground line-through">'), q = /* @__PURE__ */ s("<div><span>");
7
+ const M = {
8
+ sm: "text-sm",
9
+ md: "text-lg",
10
+ lg: "text-2xl"
11
+ };
12
+ function A(e) {
13
+ const r = (c) => new Intl.NumberFormat(e.locale ?? "en-US", {
14
+ style: "currency",
15
+ currency: e.currency ?? "USD"
16
+ }).format(c), a = () => (e.compareAt ?? 0) > e.amount, t = () => Math.round((1 - e.amount / e.compareAt) * 100);
17
+ return (() => {
18
+ var c = q(), d = c.firstChild;
19
+ return n(d, () => r(e.amount)), n(c, u(v, {
20
+ get when() {
21
+ return a();
22
+ },
23
+ get children() {
24
+ return [(() => {
25
+ var i = j();
26
+ return n(i, () => r(e.compareAt)), i;
27
+ })(), u(S, {
28
+ tone: "danger",
29
+ get children() {
30
+ return ["-", T(() => t()), "%"];
31
+ }
32
+ })];
33
+ }
34
+ }), null), f((i) => {
35
+ var l = h("inline-flex items-center gap-2", e.class), m = h("font-bold text-foreground", M[e.size ?? "md"]);
36
+ return l !== i.e && b(c, i.e = l), m !== i.t && b(d, i.t = m), i;
37
+ }, {
38
+ e: void 0,
39
+ t: void 0
40
+ }), c;
41
+ })();
42
+ }
43
+ var P = /* @__PURE__ */ s('<div><button type=button aria-label="Decrease quantity"class="grid h-8 w-8 place-items-center hover:bg-muted disabled:opacity-40"></button><span class="grid min-w-[2.5rem] place-items-center tabular-nums"></span><button type=button aria-label="Increase quantity"class="grid h-8 w-8 place-items-center hover:bg-muted disabled:opacity-40">');
44
+ function D(e) {
45
+ const r = () => e.min ?? 0, a = () => e.max ?? Number.MAX_SAFE_INTEGER, t = (i) => Math.min(a(), Math.max(r(), i)), c = () => e.onChange(t(e.value - 1)), d = () => e.onChange(t(e.value + 1));
46
+ return (() => {
47
+ var i = P(), l = i.firstChild, m = l.nextSibling, g = m.nextSibling;
48
+ return l.$$click = c, n(l, u(N, {
49
+ class: "h-4 w-4"
50
+ })), n(m, () => e.value), g.$$click = d, n(g, u(R, {
51
+ class: "h-4 w-4"
52
+ })), f((o) => {
53
+ var x = h("inline-flex items-stretch rounded-md border border-input", e.class), _ = e.disabled || e.value <= r(), y = e.disabled || e.value >= a();
54
+ return x !== o.e && b(i, o.e = x), _ !== o.t && (l.disabled = o.t = _), y !== o.a && (g.disabled = o.a = y), o;
55
+ }, {
56
+ e: void 0,
57
+ t: void 0,
58
+ a: void 0
59
+ }), i;
60
+ })();
61
+ }
62
+ C(["click"]);
63
+ var z = /* @__PURE__ */ s('<div class="relative aspect-square overflow-hidden rounded-lg bg-muted"><img loading=lazy class="h-full w-full object-cover">', !0, !1, !1), B = /* @__PURE__ */ s('<div class="mt-3 space-y-2"><p class="line-clamp-1 font-medium text-foreground">');
64
+ function te(e) {
65
+ return u(E, {
66
+ get class() {
67
+ return h("overflow-hidden p-4", e.class);
68
+ },
69
+ get children() {
70
+ return [(() => {
71
+ var r = z(), a = r.firstChild;
72
+ return n(r, u(v, {
73
+ get when() {
74
+ return e.badge;
75
+ },
76
+ get children() {
77
+ return u(S, {
78
+ class: "absolute left-2 top-2",
79
+ get children() {
80
+ return e.badge;
81
+ }
82
+ });
83
+ }
84
+ }), null), f((t) => {
85
+ var c = e.image, d = e.title;
86
+ return c !== t.e && $(a, "src", t.e = c), d !== t.t && $(a, "alt", t.t = d), t;
87
+ }, {
88
+ e: void 0,
89
+ t: void 0
90
+ }), r;
91
+ })(), (() => {
92
+ var r = B(), a = r.firstChild;
93
+ return n(a, () => e.title), n(r, u(v, {
94
+ get when() {
95
+ return e.rating !== void 0;
96
+ },
97
+ get children() {
98
+ return u(F, {
99
+ get value() {
100
+ return e.rating;
101
+ },
102
+ readonly: !0,
103
+ max: 5
104
+ });
105
+ }
106
+ }), null), n(r, u(A, {
107
+ get amount() {
108
+ return e.price;
109
+ },
110
+ get compareAt() {
111
+ return e.compareAt;
112
+ },
113
+ get currency() {
114
+ return e.currency;
115
+ },
116
+ get locale() {
117
+ return e.locale;
118
+ }
119
+ }), null), n(r, u(v, {
120
+ get when() {
121
+ return e.onAddToCart;
122
+ },
123
+ get children() {
124
+ return u(k, {
125
+ class: "w-full",
126
+ onClick: () => {
127
+ var t;
128
+ return (t = e.onAddToCart) == null ? void 0 : t.call(e);
129
+ },
130
+ children: "Add to cart"
131
+ });
132
+ }
133
+ }), null), r;
134
+ })()];
135
+ }
136
+ });
137
+ }
138
+ var G = /* @__PURE__ */ s("<div>");
139
+ function ne(e) {
140
+ return (() => {
141
+ var r = G();
142
+ return n(r, () => e.children), f(() => b(r, h("grid grid-cols-2 gap-4 sm:grid-cols-3 lg:grid-cols-4", e.class))), r;
143
+ })();
144
+ }
145
+ var L = /* @__PURE__ */ s('<img class="h-16 w-16 shrink-0 rounded-md bg-muted object-cover">'), Q = /* @__PURE__ */ s('<button type=button aria-label="Remove item"class="text-muted-foreground hover:text-foreground">'), O = /* @__PURE__ */ s('<div><div class="min-w-[8rem] flex-1"><p class="line-clamp-1 font-medium text-foreground"></p></div><span class="min-w-[4rem] text-right font-medium tabular-nums text-foreground">');
146
+ function le(e) {
147
+ const r = () => e.price * e.quantity, a = (t) => new Intl.NumberFormat(e.locale ?? "en-US", {
148
+ style: "currency",
149
+ currency: e.currency ?? "USD"
150
+ }).format(t);
151
+ return (() => {
152
+ var t = O(), c = t.firstChild, d = c.firstChild, i = c.nextSibling;
153
+ return n(t, u(v, {
154
+ get when() {
155
+ return e.image;
156
+ },
157
+ get children() {
158
+ var l = L();
159
+ return f((m) => {
160
+ var g = e.image, o = e.title;
161
+ return g !== m.e && $(l, "src", m.e = g), o !== m.t && $(l, "alt", m.t = o), m;
162
+ }, {
163
+ e: void 0,
164
+ t: void 0
165
+ }), l;
166
+ }
167
+ }), c), n(d, () => e.title), n(c, u(A, {
168
+ get amount() {
169
+ return e.price;
170
+ },
171
+ get currency() {
172
+ return e.currency;
173
+ },
174
+ get locale() {
175
+ return e.locale;
176
+ },
177
+ size: "sm"
178
+ }), null), n(t, u(D, {
179
+ get value() {
180
+ return e.quantity;
181
+ },
182
+ onChange: (l) => {
183
+ var m;
184
+ return (m = e.onQuantityChange) == null ? void 0 : m.call(e, l);
185
+ },
186
+ min: 1
187
+ }), i), n(i, () => a(r())), n(t, u(v, {
188
+ get when() {
189
+ return e.onRemove;
190
+ },
191
+ get children() {
192
+ var l = Q();
193
+ return l.$$click = () => {
194
+ var m;
195
+ return (m = e.onRemove) == null ? void 0 : m.call(e);
196
+ }, n(l, u(U, {
197
+ class: "h-4 w-4"
198
+ })), l;
199
+ }
200
+ }), null), f(() => b(t, h("flex flex-wrap items-center gap-4", e.class))), t;
201
+ })();
202
+ }
203
+ C(["click"]);
204
+ var X = /* @__PURE__ */ s('<div><div class="my-3 border-t border-border"></div><div class="flex items-center justify-between text-base font-bold text-foreground"><span>Total</span><span class=tabular-nums>'), Z = /* @__PURE__ */ s('<div class="flex items-center justify-between py-1 text-sm"><span class=text-muted-foreground></span><span class="tabular-nums text-foreground">');
205
+ function re(e) {
206
+ const r = (a) => new Intl.NumberFormat(e.locale ?? "en-US", {
207
+ style: "currency",
208
+ currency: e.currency ?? "USD"
209
+ }).format(a);
210
+ return (() => {
211
+ var a = X(), t = a.firstChild, c = t.nextSibling, d = c.firstChild, i = d.nextSibling;
212
+ return n(a, u(w, {
213
+ get each() {
214
+ return e.lines;
215
+ },
216
+ children: (l) => (() => {
217
+ var m = Z(), g = m.firstChild, o = g.nextSibling;
218
+ return n(g, () => l.label), n(o, () => r(l.amount)), m;
219
+ })()
220
+ }), t), n(i, () => r(e.total)), n(a, u(v, {
221
+ get when() {
222
+ return e.onCheckout;
223
+ },
224
+ get children() {
225
+ return u(k, {
226
+ class: "mt-4 w-full",
227
+ onClick: () => {
228
+ var l;
229
+ return (l = e.onCheckout) == null ? void 0 : l.call(e);
230
+ },
231
+ get children() {
232
+ return e.checkoutLabel ?? "Checkout";
233
+ }
234
+ });
235
+ }
236
+ }), null), f(() => b(a, h("rounded-xl border border-border bg-card p-5", e.class))), a;
237
+ })();
238
+ }
239
+ var H = /* @__PURE__ */ s('<div><p class="text-sm font-semibold text-foreground"></p><div class=space-y-1.5>'), J = /* @__PURE__ */ s('<span class="text-xs text-muted-foreground">'), K = /* @__PURE__ */ s('<div class="flex items-center justify-between gap-2">');
240
+ function ae(e) {
241
+ const r = (a, t) => {
242
+ const c = e.selected.slice(), d = c.indexOf(a);
243
+ t ? d === -1 && c.push(a) : d !== -1 && c.splice(d, 1), e.onChange(c);
244
+ };
245
+ return (() => {
246
+ var a = H(), t = a.firstChild, c = t.nextSibling;
247
+ return n(t, () => e.title), n(c, u(w, {
248
+ get each() {
249
+ return e.options;
250
+ },
251
+ children: (d) => (() => {
252
+ var i = K();
253
+ return n(i, u(I, {
254
+ get checked() {
255
+ return e.selected.includes(d.value);
256
+ },
257
+ onChange: (l) => r(d.value, l),
258
+ get label() {
259
+ return d.label;
260
+ }
261
+ }), null), n(i, u(v, {
262
+ get when() {
263
+ return d.count != null;
264
+ },
265
+ get children() {
266
+ var l = J();
267
+ return n(l, () => d.count), l;
268
+ }
269
+ }), null), i;
270
+ })()
271
+ })), f(() => b(a, h("space-y-2", e.class))), a;
272
+ })();
273
+ }
274
+ export {
275
+ le as CartLine,
276
+ re as CartSummary,
277
+ ae as FilterGroup,
278
+ A as PriceTag,
279
+ te as ProductCard,
280
+ ne as ProductGrid,
281
+ D as QuantityStepper
282
+ };
package/dist/elements.css CHANGED
@@ -1505,6 +1505,10 @@ html.calm .tile-glass {
1505
1505
  margin-left: auto;
1506
1506
  margin-right: auto;
1507
1507
  }
1508
+ .my-3 {
1509
+ margin-top: 0.75rem;
1510
+ margin-bottom: 0.75rem;
1511
+ }
1508
1512
  .-ml-2 {
1509
1513
  margin-left: -0.5rem;
1510
1514
  }
@@ -1538,6 +1542,12 @@ html.calm .tile-glass {
1538
1542
  .mt-6 {
1539
1543
  margin-top: 1.5rem;
1540
1544
  }
1545
+ .line-clamp-1 {
1546
+ overflow: hidden;
1547
+ display: -webkit-box;
1548
+ -webkit-box-orient: vertical;
1549
+ -webkit-line-clamp: 1;
1550
+ }
1541
1551
  .block {
1542
1552
  display: block;
1543
1553
  }
@@ -1568,6 +1578,9 @@ html.calm .tile-glass {
1568
1578
  .hidden {
1569
1579
  display: none;
1570
1580
  }
1581
+ .aspect-square {
1582
+ aspect-ratio: 1 / 1;
1583
+ }
1571
1584
  .size-3 {
1572
1585
  width: 0.75rem;
1573
1586
  height: 0.75rem;
@@ -1635,6 +1648,9 @@ html.calm .tile-glass {
1635
1648
  .h-\[65vh\] {
1636
1649
  height: 65vh;
1637
1650
  }
1651
+ .h-auto {
1652
+ height: auto;
1653
+ }
1638
1654
  .h-full {
1639
1655
  height: 100%;
1640
1656
  }
@@ -1665,6 +1681,9 @@ html.calm .tile-glass {
1665
1681
  .min-h-4 {
1666
1682
  min-height: 1rem;
1667
1683
  }
1684
+ .min-h-9 {
1685
+ min-height: 2.25rem;
1686
+ }
1668
1687
  .min-h-\[80px\] {
1669
1688
  min-height: 80px;
1670
1689
  }
@@ -1680,6 +1699,9 @@ html.calm .tile-glass {
1680
1699
  .w-1\.5 {
1681
1700
  width: 0.375rem;
1682
1701
  }
1702
+ .w-10 {
1703
+ width: 2.5rem;
1704
+ }
1683
1705
  .w-11 {
1684
1706
  width: 2.75rem;
1685
1707
  }
@@ -1764,12 +1786,24 @@ html.calm .tile-glass {
1764
1786
  .min-w-40 {
1765
1787
  min-width: 10rem;
1766
1788
  }
1789
+ .min-w-56 {
1790
+ min-width: 14rem;
1791
+ }
1767
1792
  .min-w-\[1\.5rem\] {
1768
1793
  min-width: 1.5rem;
1769
1794
  }
1770
1795
  .min-w-\[10rem\] {
1771
1796
  min-width: 10rem;
1772
1797
  }
1798
+ .min-w-\[2\.5rem\] {
1799
+ min-width: 2.5rem;
1800
+ }
1801
+ .min-w-\[4rem\] {
1802
+ min-width: 4rem;
1803
+ }
1804
+ .min-w-\[8rem\] {
1805
+ min-width: 8rem;
1806
+ }
1773
1807
  .max-w-\[520px\] {
1774
1808
  max-width: 520px;
1775
1809
  }
@@ -1879,6 +1913,9 @@ html.calm .tile-glass {
1879
1913
  .grid-cols-1 {
1880
1914
  grid-template-columns: repeat(1, minmax(0, 1fr));
1881
1915
  }
1916
+ .grid-cols-2 {
1917
+ grid-template-columns: repeat(2, minmax(0, 1fr));
1918
+ }
1882
1919
  .grid-cols-3 {
1883
1920
  grid-template-columns: repeat(3, minmax(0, 1fr));
1884
1921
  }
@@ -1900,6 +1937,9 @@ html.calm .tile-glass {
1900
1937
  .items-start {
1901
1938
  align-items: flex-start;
1902
1939
  }
1940
+ .items-end {
1941
+ align-items: flex-end;
1942
+ }
1903
1943
  .items-center {
1904
1944
  align-items: center;
1905
1945
  }
@@ -1952,6 +1992,11 @@ html.calm .tile-glass {
1952
1992
  margin-top: calc(0.375rem * calc(1 - var(--tw-space-y-reverse)));
1953
1993
  margin-bottom: calc(0.375rem * var(--tw-space-y-reverse));
1954
1994
  }
1995
+ .space-y-2 > :not([hidden]) ~ :not([hidden]) {
1996
+ --tw-space-y-reverse: 0;
1997
+ margin-top: calc(0.5rem * calc(1 - var(--tw-space-y-reverse)));
1998
+ margin-bottom: calc(0.5rem * var(--tw-space-y-reverse));
1999
+ }
1955
2000
  .space-y-4 > :not([hidden]) ~ :not([hidden]) {
1956
2001
  --tw-space-y-reverse: 0;
1957
2002
  margin-top: calc(1rem * calc(1 - var(--tw-space-y-reverse)));
@@ -1980,6 +2025,9 @@ html.calm .tile-glass {
1980
2025
  .overflow-hidden {
1981
2026
  overflow: hidden;
1982
2027
  }
2028
+ .overflow-visible {
2029
+ overflow: visible;
2030
+ }
1983
2031
  .overflow-x-auto {
1984
2032
  overflow-x: auto;
1985
2033
  }
@@ -2023,6 +2071,10 @@ html.calm .tile-glass {
2023
2071
  border-top-right-radius: 0.375rem;
2024
2072
  border-bottom-right-radius: 0.375rem;
2025
2073
  }
2074
+ .rounded-t {
2075
+ border-top-left-radius: 0.25rem;
2076
+ border-top-right-radius: 0.25rem;
2077
+ }
2026
2078
  .border {
2027
2079
  border-width: 1px;
2028
2080
  }
@@ -2163,6 +2215,9 @@ html.calm .tile-glass {
2163
2215
  .bg-primary\/15 {
2164
2216
  background-color: hsl(var(--primary) / 0.15);
2165
2217
  }
2218
+ .bg-primary\/20 {
2219
+ background-color: hsl(var(--primary) / 0.2);
2220
+ }
2166
2221
  .bg-primary\/25 {
2167
2222
  background-color: hsl(var(--primary) / 0.25);
2168
2223
  }
@@ -2266,6 +2321,10 @@ html.calm .tile-glass {
2266
2321
  padding-left: 1.5rem;
2267
2322
  padding-right: 1.5rem;
2268
2323
  }
2324
+ .py-0 {
2325
+ padding-top: 0px;
2326
+ padding-bottom: 0px;
2327
+ }
2269
2328
  .py-0\.5 {
2270
2329
  padding-top: 0.125rem;
2271
2330
  padding-bottom: 0.125rem;
@@ -2519,6 +2578,9 @@ html.calm .tile-glass {
2519
2578
  --tw-text-opacity: 1;
2520
2579
  color: rgb(2 132 199 / var(--tw-text-opacity, 1));
2521
2580
  }
2581
+ .line-through {
2582
+ text-decoration-line: line-through;
2583
+ }
2522
2584
  .accent-foreground {
2523
2585
  accent-color: hsl(var(--foreground) / 1);
2524
2586
  }
@@ -2736,6 +2798,10 @@ html.calm .tile-glass {
2736
2798
  .focus-within\:ring-ring\/30:focus-within {
2737
2799
  --tw-ring-color: hsl(var(--ring) / 0.3);
2738
2800
  }
2801
+ .hover\:border-primary:hover {
2802
+ --tw-border-opacity: 1;
2803
+ border-color: hsl(var(--primary) / var(--tw-border-opacity, 1));
2804
+ }
2739
2805
  .hover\:border-ring\/60:hover {
2740
2806
  border-color: hsl(var(--ring) / 0.6);
2741
2807
  }
@@ -2749,6 +2815,9 @@ html.calm .tile-glass {
2749
2815
  .hover\:bg-muted\/70:hover {
2750
2816
  background-color: hsl(var(--muted) / 0.7);
2751
2817
  }
2818
+ .hover\:bg-primary\/5:hover {
2819
+ background-color: hsl(var(--primary) / 0.05);
2820
+ }
2752
2821
  .hover\:bg-primary\/50:hover {
2753
2822
  background-color: hsl(var(--primary) / 0.5);
2754
2823
  }
@@ -2776,6 +2845,10 @@ html.calm .tile-glass {
2776
2845
  --tw-border-opacity: 1;
2777
2846
  border-color: hsl(var(--ring) / var(--tw-border-opacity, 1));
2778
2847
  }
2848
+ .focus\:bg-muted:focus {
2849
+ --tw-bg-opacity: 1;
2850
+ background-color: hsl(var(--muted) / var(--tw-bg-opacity, 1));
2851
+ }
2779
2852
  .focus\:outline-none:focus {
2780
2853
  outline: 2px solid transparent;
2781
2854
  outline-offset: 2px;
@@ -2923,6 +2996,12 @@ html.calm .tile-glass {
2923
2996
  padding-right: 1.5rem;
2924
2997
  }
2925
2998
  }
2999
+ @media (min-width: 1024px) {
3000
+
3001
+ .lg\:grid-cols-4 {
3002
+ grid-template-columns: repeat(4, minmax(0, 1fr));
3003
+ }
3004
+ }
2926
3005
  .\[\&\:\:-webkit-details-marker\]\:hidden::-webkit-details-marker {
2927
3006
  display: none;
2928
3007
  }
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export declare const A4UI_VERSION = "0.8.1";
1
+ export declare const A4UI_VERSION = "0.10.0";
2
2
  export { cn } from './lib/cn';
3
3
  export { useTheme, toggleTheme, setTheme, storedTheme, applyTheme, toggled, type Theme } from './lib/theme';
4
4
  export { useEffects, isCalm, setEffects } from './lib/effects';
@@ -13,6 +13,10 @@ export { Checkbox } from './ui/Checkbox';
13
13
  export { DateField } from './ui/DateField';
14
14
  export { TimeField, type TimeFieldProps } from './ui/TimeField';
15
15
  export { DateTimeField, type DateTimeFieldProps } from './ui/DateTimeField';
16
+ export { DateRangePicker, type DateRange, type DateRangePickerProps } from './ui/DateRangePicker';
17
+ export { FormField, FormLabel, FormControl, FormDescription, FormError, type FormFieldProps } from './ui/Form';
18
+ export { FileUpload, type UploadFile, type FileUploadProps } from './ui/FileUpload';
19
+ export { MultiSelect, type MultiSelectOption, type MultiSelectProps } from './ui/MultiSelect';
16
20
  export { Drawer } from './ui/Drawer';
17
21
  export { Dropdown, type DropdownItem } from './ui/Dropdown';
18
22
  export { Dropzone } from './ui/Dropzone';