@jirawatpyk/aura-tokens 4.16.0 → 4.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -86,6 +86,8 @@ Dark theme: put `class="dark"` (or `data-theme="dark"`) on `<html>`.
86
86
 
87
87
  Classes: `bg-bg-surface`, `text-fg-primary`, `border-border-strong`, `text-fg-danger`, `bg-alert-warning-bg`, `fill-chart-1`, `p-aura-6`, `gap-aura-4`, `rounded-aura-xl`, `shadow-aura-overlay`, `ease-aura-ease`, `duration-aura-fast`, `z-aura-dialog`, `font-display` / `font-sans` / `font-mono`. They point at the `--aura-*` variables, so `.dark` or `data-theme="dark"` switches them with no `dark:` prefix; the file also makes `dark:` follow those two switches. `npm run check:tailwind4` compiles it with Tailwind v4 in CI.
88
88
 
89
+ Next to an existing Tailwind theme (shadcn) use `@jirawatpyk/aura-tokens/tailwind.prefixed.css` instead (4.17). Every name carries `aura-` (`bg-aura-bg-surface`, `border-aura-border-strong`, `bg-aura-chart-1`, `font-aura-sans`), with no `@custom-variant` and no `@import`. Import `aura.css` yourself in an early layer so your theme keeps its `--font-*`. The React package README has the full setup, with `@jirawatpyk/aura-react/styles.layer.css`.
90
+
89
91
  ### Tailwind v3
90
92
 
91
93
  ```ts
package/aura-tailwind.css CHANGED
@@ -1,4 +1,4 @@
1
- /* AURA v4.16.0 — Tailwind v4 theme. GENERATED by scripts/build-tokens.js from tokens.json. Do not edit by hand.
1
+ /* AURA v4.17.0 — Tailwind v4 theme. GENERATED by scripts/build-tokens.js from tokens.json. Do not edit by hand.
2
2
  * @import "tailwindcss";
3
3
  * @import "@jirawatpyk/aura-tokens/tailwind.css";
4
4
  * Gives bg-bg-surface, text-fg-primary, border-border-strong, p-aura-6, rounded-aura-xl, shadow-aura-overlay,
@@ -0,0 +1,165 @@
1
+ /* AURA v4.17.0 — Tailwind v4 theme with aura- prefixed names. GENERATED by scripts/build-tokens.js. Do not edit by hand.
2
+ * For apps that already have a Tailwind theme (shadcn): nothing here redefines an existing name.
3
+ * @layer aura-tokens, theme, base, aura, components, utilities;
4
+ * @import "tailwindcss";
5
+ * @import "@jirawatpyk/aura-tokens/aura.css" layer(aura-tokens); <- the --aura-* variables; your theme wins for --font-*
6
+ * @import "@jirawatpyk/aura-tokens/tailwind.prefixed.css";
7
+ * @import "@jirawatpyk/aura-react/styles.layer.css"; <- components in @layer aura, so utilities win
8
+ * Classes: bg-aura-bg-surface, text-aura-fg-primary, border-aura-border-strong, bg-aura-chart-1, p-aura-6,
9
+ * rounded-aura-xl, shadow-aura-overlay, font-aura-sans … Use your own dark: variant. */
10
+
11
+ @theme inline {
12
+ --color-aura-violet-50: var(--aura-violet-50);
13
+ --color-aura-violet-100: var(--aura-violet-100);
14
+ --color-aura-violet-200: var(--aura-violet-200);
15
+ --color-aura-violet-300: var(--aura-violet-300);
16
+ --color-aura-violet-400: var(--aura-violet-400);
17
+ --color-aura-violet-500: var(--aura-violet-500);
18
+ --color-aura-violet-600: var(--aura-violet-600);
19
+ --color-aura-violet-700: var(--aura-violet-700);
20
+ --color-aura-violet-800: var(--aura-violet-800);
21
+ --color-aura-violet-900: var(--aura-violet-900);
22
+ --color-aura-zinc-0: var(--aura-zinc-0);
23
+ --color-aura-zinc-50: var(--aura-zinc-50);
24
+ --color-aura-zinc-100: var(--aura-zinc-100);
25
+ --color-aura-zinc-200: var(--aura-zinc-200);
26
+ --color-aura-zinc-300: var(--aura-zinc-300);
27
+ --color-aura-zinc-400: var(--aura-zinc-400);
28
+ --color-aura-zinc-450: var(--aura-zinc-450);
29
+ --color-aura-zinc-500: var(--aura-zinc-500);
30
+ --color-aura-zinc-600: var(--aura-zinc-600);
31
+ --color-aura-zinc-700: var(--aura-zinc-700);
32
+ --color-aura-zinc-800: var(--aura-zinc-800);
33
+ --color-aura-zinc-900: var(--aura-zinc-900);
34
+ --color-aura-zinc-950: var(--aura-zinc-950);
35
+ --color-aura-lime-50: var(--aura-lime-50);
36
+ --color-aura-lime-100: var(--aura-lime-100);
37
+ --color-aura-lime-200: var(--aura-lime-200);
38
+ --color-aura-lime-300: var(--aura-lime-300);
39
+ --color-aura-lime-400: var(--aura-lime-400);
40
+ --color-aura-lime-500: var(--aura-lime-500);
41
+ --color-aura-lime-600: var(--aura-lime-600);
42
+ --color-aura-lime-800: var(--aura-lime-800);
43
+ --color-aura-red-50: var(--aura-red-50);
44
+ --color-aura-red-200: var(--aura-red-200);
45
+ --color-aura-red-300: var(--aura-red-300);
46
+ --color-aura-red-400: var(--aura-red-400);
47
+ --color-aura-red-600: var(--aura-red-600);
48
+ --color-aura-red-700: var(--aura-red-700);
49
+ --color-aura-red-800: var(--aura-red-800);
50
+ --color-aura-amber-50: var(--aura-amber-50);
51
+ --color-aura-amber-200: var(--aura-amber-200);
52
+ --color-aura-amber-300: var(--aura-amber-300);
53
+ --color-aura-amber-800: var(--aura-amber-800);
54
+ --color-aura-ink: var(--aura-ink);
55
+ --color-aura-white: var(--aura-white);
56
+ --color-aura-bg-surface: var(--aura-bg-surface);
57
+ --color-aura-bg-surface-hover: var(--aura-bg-surface-hover);
58
+ --color-aura-bg-surface-strong: var(--aura-bg-surface-strong);
59
+ --color-aura-bg-canvas: var(--aura-bg-canvas);
60
+ --color-aura-bg-inverted: var(--aura-bg-inverted);
61
+ --color-aura-bg-selected: var(--aura-bg-selected);
62
+ --color-aura-bg-skeleton: var(--aura-bg-skeleton);
63
+ --color-aura-bg-input: var(--aura-bg-input);
64
+ --color-aura-bg-input-disabled: var(--aura-bg-input-disabled);
65
+ --color-aura-bg-scrim: var(--aura-bg-scrim);
66
+ --color-aura-bg-hover: var(--aura-bg-surface-hover);
67
+ --color-aura-bg-strong: var(--aura-bg-surface-strong);
68
+ --color-aura-fg-primary: var(--aura-fg-primary);
69
+ --color-aura-fg-secondary: var(--aura-fg-secondary);
70
+ --color-aura-fg-tertiary: var(--aura-fg-tertiary);
71
+ --color-aura-fg-inverted: var(--aura-fg-inverted);
72
+ --color-aura-fg-accent: var(--aura-fg-accent);
73
+ --color-aura-fg-danger: var(--aura-fg-danger);
74
+ --color-aura-fg-positive: var(--aura-fg-positive);
75
+ --color-aura-border: var(--aura-border-default);
76
+ --color-aura-border-default: var(--aura-border-default);
77
+ --color-aura-border-strong: var(--aura-border-strong);
78
+ --color-aura-border-subtle: var(--aura-border-subtle);
79
+ --color-aura-border-control: var(--aura-border-control);
80
+ --color-aura-border-danger: var(--aura-border-danger);
81
+ --color-aura-accent-dot: var(--aura-accent-dot);
82
+ --color-aura-accent-violet: var(--aura-accent-violet);
83
+ --color-aura-accent-lime: var(--aura-accent-lime);
84
+ --color-aura-status-neutral-bg: var(--aura-status-neutral-bg);
85
+ --color-aura-status-neutral-fg: var(--aura-status-neutral-fg);
86
+ --color-aura-status-progress-bg: var(--aura-status-progress-bg);
87
+ --color-aura-status-progress-fg: var(--aura-status-progress-fg);
88
+ --color-aura-status-ready-bg: var(--aura-status-ready-bg);
89
+ --color-aura-status-ready-fg: var(--aura-status-ready-fg);
90
+ --color-aura-status-blocked-bg: var(--aura-status-blocked-bg);
91
+ --color-aura-status-blocked-fg: var(--aura-status-blocked-fg);
92
+ --color-aura-chart-1: var(--aura-chart-1);
93
+ --color-aura-chart-2: var(--aura-chart-2);
94
+ --color-aura-chart-3: var(--aura-chart-3);
95
+ --color-aura-chart-4: var(--aura-chart-4);
96
+ --color-aura-chart-5: var(--aura-chart-5);
97
+ --color-aura-chart-6: var(--aura-chart-6);
98
+ --color-aura-chart-7: var(--aura-chart-7);
99
+ --color-aura-chart-8: var(--aura-chart-8);
100
+ --color-aura-chart-seq-1: var(--aura-chart-seq-1);
101
+ --color-aura-chart-seq-2: var(--aura-chart-seq-2);
102
+ --color-aura-chart-seq-3: var(--aura-chart-seq-3);
103
+ --color-aura-chart-seq-4: var(--aura-chart-seq-4);
104
+ --color-aura-chart-seq-5: var(--aura-chart-seq-5);
105
+ --color-aura-chart-grid: var(--aura-chart-grid);
106
+ --color-aura-chart-axis: var(--aura-chart-axis);
107
+ --color-aura-alert-info-bg: var(--aura-alert-info-bg);
108
+ --color-aura-alert-info-fg: var(--aura-alert-info-fg);
109
+ --color-aura-alert-info-border: var(--aura-alert-info-border);
110
+ --color-aura-alert-success-bg: var(--aura-alert-success-bg);
111
+ --color-aura-alert-success-fg: var(--aura-alert-success-fg);
112
+ --color-aura-alert-success-border: var(--aura-alert-success-border);
113
+ --color-aura-alert-warning-bg: var(--aura-alert-warning-bg);
114
+ --color-aura-alert-warning-fg: var(--aura-alert-warning-fg);
115
+ --color-aura-alert-warning-border: var(--aura-alert-warning-border);
116
+ --color-aura-alert-danger-bg: var(--aura-alert-danger-bg);
117
+ --color-aura-alert-danger-fg: var(--aura-alert-danger-fg);
118
+ --color-aura-alert-danger-border: var(--aura-alert-danger-border);
119
+ --color-aura-focus-ring: var(--aura-focus-ring);
120
+ --spacing-aura-0: var(--aura-space-0);
121
+ --spacing-aura-1: var(--aura-space-1);
122
+ --spacing-aura-2: var(--aura-space-2);
123
+ --spacing-aura-3: var(--aura-space-3);
124
+ --spacing-aura-4: var(--aura-space-4);
125
+ --spacing-aura-5: var(--aura-space-5);
126
+ --spacing-aura-6: var(--aura-space-6);
127
+ --spacing-aura-8: var(--aura-space-8);
128
+ --spacing-aura-10: var(--aura-space-10);
129
+ --spacing-aura-12: var(--aura-space-12);
130
+ --spacing-aura-16: var(--aura-space-16);
131
+ --spacing-aura-card-padding: var(--aura-card-padding);
132
+ --radius-aura-xs: var(--aura-radius-xs);
133
+ --radius-aura-sm: var(--aura-radius-sm);
134
+ --radius-aura-md: var(--aura-radius-md);
135
+ --radius-aura-lg: var(--aura-radius-lg);
136
+ --radius-aura-xl: var(--aura-radius-xl);
137
+ --radius-aura-2xl: var(--aura-radius-2xl);
138
+ --radius-aura-full: var(--aura-radius-full);
139
+ --radius-aura-squircle: var(--aura-radius-squircle);
140
+ --radius-aura-card-radius: var(--aura-card-radius);
141
+ --radius-aura-button-radius: var(--aura-button-radius);
142
+ --shadow-aura-enterprise: var(--aura-shadow-enterprise);
143
+ --shadow-aura-overlay: var(--aura-shadow-overlay);
144
+ --shadow-aura-creative: var(--aura-shadow-creative);
145
+ --shadow-aura-creative-hover: var(--aura-shadow-creative-hover);
146
+ --shadow-aura-card-shadow-creative: var(--aura-card-shadow-creative);
147
+ --ease-aura-ease: var(--aura-ease);
148
+ --ease-aura-spring: var(--aura-spring);
149
+ --font-aura-display: "Fraunces", "Noto Sans Thai", serif;
150
+ --font-aura-sans: "Inter", "Noto Sans Thai", sans-serif;
151
+ --font-aura-mono: "JetBrains Mono", monospace;
152
+ --font-aura-thai: "Noto Sans Thai", sans-serif;
153
+ }
154
+
155
+ @utility duration-aura-fast { transition-duration: var(--aura-duration-fast); }
156
+ @utility duration-aura-base { transition-duration: var(--aura-duration-base); }
157
+ @utility duration-aura-slow { transition-duration: var(--aura-duration-slow); }
158
+ @utility duration-aura-spin { transition-duration: var(--aura-duration-spin); }
159
+ @utility duration-aura-pulse { transition-duration: var(--aura-duration-pulse); }
160
+ @utility duration-aura-toast { transition-duration: var(--aura-duration-toast); }
161
+ @utility duration-aura-tooltip { transition-duration: var(--aura-duration-tooltip); }
162
+ @utility z-aura-menu { z-index: var(--aura-z-menu); }
163
+ @utility z-aura-dialog { z-index: var(--aura-z-dialog); }
164
+ @utility z-aura-toast { z-index: var(--aura-z-toast); }
165
+ @utility z-aura-tooltip { z-index: var(--aura-z-tooltip); }
package/aura.css CHANGED
@@ -1,4 +1,4 @@
1
- /* AURA v4.16.0 — GENERATED by scripts/build-tokens.js from tokens.json. Do not edit by hand. */
1
+ /* AURA v4.17.0 — GENERATED by scripts/build-tokens.js from tokens.json. Do not edit by hand. */
2
2
  /* Fonts: load aura-fonts.css (or the <link> tags in README) separately, so a blocked Google Fonts never breaks this file. */
3
3
 
4
4
  :root, [data-theme="light"] {
@@ -267,6 +267,8 @@ window.Aura = (() => {
267
267
 
268
268
  // src/locale.tsx
269
269
  var React3 = __toESM(require_react(), 1);
270
+
271
+ // src/strings.ts
270
272
  var n = function(x) {
271
273
  return Number(x).toLocaleString("en");
272
274
  };
@@ -614,6 +616,8 @@ window.Aura = (() => {
614
616
  }
615
617
  }
616
618
  };
619
+
620
+ // src/locale.tsx
617
621
  var LocaleContext = React3.createContext(null);
618
622
  function AuraProvider(props) {
619
623
  const outer = React3.useContext(LocaleContext);
@@ -946,12 +950,8 @@ window.Aura = (() => {
946
950
 
947
951
  // src/StatusPill.tsx
948
952
  var React9 = __toESM(require_react(), 1);
949
- var TONE_ICON = {
950
- neutral: "circle",
951
- progress: "circle-dot-dashed",
952
- ready: "circle-check",
953
- blocked: "ban"
954
- };
953
+
954
+ // src/status.ts
955
955
  var TONE_WORDS = {
956
956
  ready: ["ready", "done", "complete", "completed", "approved", "live", "passed"],
957
957
  progress: ["in progress", "in review", "review", "syncing", "running", "pending"],
@@ -963,6 +963,14 @@ window.Aura = (() => {
963
963
  return "neutral";
964
964
  }
965
965
  var TONE_ORDER = { neutral: 0, progress: 1, ready: 2, blocked: 3 };
966
+
967
+ // src/StatusPill.tsx
968
+ var TONE_ICON = {
969
+ neutral: "circle",
970
+ progress: "circle-dot-dashed",
971
+ ready: "circle-check",
972
+ blocked: "ban"
973
+ };
966
974
  var StatusPill = React9.forwardRef(function StatusPill2(props, ref) {
967
975
  const tone2 = props.tone || toneFor(props.children);
968
976
  return /* @__PURE__ */ React9.createElement("span", { ref, className: cx("aura-pill", "aura-pill--" + tone2, props.className) }, /* @__PURE__ */ React9.createElement(Icon, { name: TONE_ICON[tone2] || "circle", size: 12 }), props.children);
@@ -1544,6 +1552,8 @@ window.Aura = (() => {
1544
1552
  // src/DatePicker.tsx
1545
1553
  var React17 = __toESM(require_react(), 1);
1546
1554
  var import_react_dom3 = __toESM(require_react_dom(), 1);
1555
+
1556
+ // src/dates.ts
1547
1557
  var ERA = /^พ\.ศ\.\s?|\s?(BE|พ\.ศ\.)$/g;
1548
1558
  var pad = function(n2) {
1549
1559
  return (n2 < 10 ? "0" : "") + n2;
@@ -1649,22 +1659,6 @@ window.Aura = (() => {
1649
1659
  const loc = o.locale || "th";
1650
1660
  return fmt(localeTag(loc, o.calendar || defaultCalendar(loc)), f, d).replace(ERA, "");
1651
1661
  }
1652
- function useFormatDate() {
1653
- const ctx = useAuraLocale(), locale = ctx.locale || "en", calendar = ctx.calendar;
1654
- return React17.useCallback(
1655
- function(iso, opts) {
1656
- const o = opts || {}, loc = o.locale || locale;
1657
- return formatDate(
1658
- iso,
1659
- Object.assign({}, o, {
1660
- locale: loc,
1661
- calendar: o.calendar || (o.locale ? void 0 : calendar) || defaultCalendar(loc)
1662
- })
1663
- );
1664
- },
1665
- [locale, calendar]
1666
- );
1667
- }
1668
1662
  var MONTHS = null;
1669
1663
  function monthIndex(word) {
1670
1664
  if (!MONTHS) {
@@ -1702,6 +1696,24 @@ window.Aura = (() => {
1702
1696
  const dt = new Date(y, mo - 1, d);
1703
1697
  return dt.getMonth() === mo - 1 && dt.getDate() === d ? toISO(dt) : null;
1704
1698
  }
1699
+
1700
+ // src/DatePicker.tsx
1701
+ function useFormatDate() {
1702
+ const ctx = useAuraLocale(), locale = ctx.locale || "en", calendar = ctx.calendar;
1703
+ return React17.useCallback(
1704
+ function(iso, opts) {
1705
+ const o = opts || {}, loc = o.locale || locale;
1706
+ return formatDate(
1707
+ iso,
1708
+ Object.assign({}, o, {
1709
+ locale: loc,
1710
+ calendar: o.calendar || (o.locale ? void 0 : calendar) || defaultCalendar(loc)
1711
+ })
1712
+ );
1713
+ },
1714
+ [locale, calendar]
1715
+ );
1716
+ }
1705
1717
  var Calendar = React17.forwardRef(function Calendar2(props, ref) {
1706
1718
  const ctx = useAuraLocale(), locale = props.locale || ctx.locale || "en", calendar = props.calendar || ctx.calendar || defaultCalendar(locale), tag = localeTag(locale, calendar);
1707
1719
  const weekStart = props.weekStartsOn == null ? locale === "sv" ? 1 : 0 : props.weekStartsOn;
@@ -2749,7 +2761,12 @@ window.Aura = (() => {
2749
2761
  const id = uid(), listId = id + "-list";
2750
2762
  const box = React25.useRef(null);
2751
2763
  const input = React25.useRef(null);
2752
- const q = React25.useState(""), act = React25.useState(0);
2764
+ const qState = React25.useState(""), act = React25.useState(null);
2765
+ const query = props.query !== void 0 ? props.query : qState[0];
2766
+ function setQuery(v) {
2767
+ if (props.query === void 0) qState[1](v);
2768
+ if (props.onQueryChange) props.onQueryChange(v);
2769
+ }
2753
2770
  const openRef = React25.useRef(props.open);
2754
2771
  openRef.current = props.open;
2755
2772
  const close = function() {
@@ -2775,15 +2792,15 @@ window.Aura = (() => {
2775
2792
  React25.useEffect(
2776
2793
  function() {
2777
2794
  if (!props.open) {
2778
- q[1]("");
2779
- act[1](0);
2795
+ if (query) setQuery("");
2796
+ act[1](null);
2780
2797
  }
2781
2798
  },
2782
2799
  [props.open]
2783
2800
  );
2784
- const filter = props.filter || defaultFilter;
2801
+ const filter = props.filter === false ? null : props.filter || defaultFilter;
2785
2802
  const shown = (props.items || []).filter(function(it) {
2786
- return filter(it, q[0]);
2803
+ return !filter || filter(it, query);
2787
2804
  });
2788
2805
  const groups = [];
2789
2806
  shown.forEach(function(it) {
@@ -2805,7 +2822,10 @@ window.Aura = (() => {
2805
2822
  }).filter(function(i2) {
2806
2823
  return i2 >= 0;
2807
2824
  });
2808
- const active = enabled.indexOf(act[0]) >= 0 ? act[0] : enabled.length ? enabled[0] : -1;
2825
+ const byId = act[0] == null ? -1 : flat.findIndex(function(it) {
2826
+ return it.id === act[0];
2827
+ });
2828
+ const active = enabled.indexOf(byId) >= 0 ? byId : enabled.length ? enabled[0] : -1;
2809
2829
  const optId = function(i2) {
2810
2830
  return id + "-o" + i2;
2811
2831
  };
@@ -2830,7 +2850,7 @@ window.Aura = (() => {
2830
2850
  if (dir === "first") n2 = 0;
2831
2851
  else if (dir === "last") n2 = enabled.length - 1;
2832
2852
  else n2 = (at + dir + enabled.length) % enabled.length;
2833
- act[1](enabled[n2]);
2853
+ act[1](flat[enabled[n2]].id);
2834
2854
  }
2835
2855
  function onKey(e) {
2836
2856
  if (e.key === "ArrowDown") {
@@ -2888,56 +2908,68 @@ window.Aura = (() => {
2888
2908
  "aria-label": props.label || t.commandMenu,
2889
2909
  placeholder: props.placeholder || t.commandPlaceholder,
2890
2910
  className: "aura-command__input",
2891
- value: q[0],
2911
+ value: query,
2892
2912
  autoComplete: "off",
2893
2913
  spellCheck: false,
2894
2914
  onChange: function(e) {
2895
- q[1](e.target.value);
2896
- act[1](0);
2915
+ setQuery(e.target.value);
2916
+ act[1](null);
2897
2917
  },
2898
2918
  onKeyDown: onKey
2899
2919
  }
2900
2920
  ), /* @__PURE__ */ React25.createElement("kbd", { className: "aura-command__kbd" }, "Esc")),
2901
- /* @__PURE__ */ React25.createElement("div", { className: "aura-command__list", id: listId, role: "listbox", "aria-label": props.label || t.commandMenu }, !flat.length ? /* @__PURE__ */ React25.createElement("p", { className: "aura-command__empty", role: "presentation" }, props.emptyText || t.noMatches) : groups.map(function(g, gi) {
2902
- const gid = id + "-g" + gi;
2903
- return /* @__PURE__ */ React25.createElement(
2904
- "div",
2905
- {
2906
- key: g.name || gi,
2907
- role: "group",
2908
- "aria-labelledby": g.name ? gid : void 0,
2909
- className: "aura-command__group"
2910
- },
2911
- g.name ? /* @__PURE__ */ React25.createElement("div", { className: "aura-command__heading", id: gid, role: "presentation" }, g.name) : null,
2912
- g.items.map(function(it) {
2913
- i++;
2914
- const n2 = i;
2915
- return /* @__PURE__ */ React25.createElement(
2916
- "div",
2917
- {
2918
- key: it.id,
2919
- id: optId(n2),
2920
- role: "option",
2921
- "aria-selected": n2 === active,
2922
- "aria-disabled": it.disabled || void 0,
2923
- className: cx("aura-command__item", n2 === active && "is-active", it.disabled && "is-disabled"),
2924
- onPointerDown: function(e) {
2925
- e.preventDefault();
2926
- },
2927
- onPointerMove: function() {
2928
- if (!it.disabled && act[0] !== n2) act[1](n2);
2921
+ /* @__PURE__ */ React25.createElement(
2922
+ "div",
2923
+ {
2924
+ className: "aura-command__list",
2925
+ id: listId,
2926
+ role: "listbox",
2927
+ "aria-label": props.label || t.commandMenu,
2928
+ "aria-busy": props.loading || void 0
2929
+ },
2930
+ props.loading ? /* @__PURE__ */ React25.createElement("div", { className: "aura-command__loading", role: "presentation" }, /* @__PURE__ */ React25.createElement(Icon, { name: "loader-circle", className: "aura-spin" }), t.searching) : null,
2931
+ !flat.length ? props.loading ? null : /* @__PURE__ */ React25.createElement("div", { className: "aura-command__empty", role: "presentation" }, props.empty != null ? props.empty : props.emptyText || t.noMatches) : groups.map(function(g, gi) {
2932
+ const gid = id + "-g" + gi;
2933
+ return /* @__PURE__ */ React25.createElement(
2934
+ "div",
2935
+ {
2936
+ key: g.name || gi,
2937
+ role: "group",
2938
+ "aria-labelledby": g.name ? gid : void 0,
2939
+ className: "aura-command__group"
2940
+ },
2941
+ g.name ? /* @__PURE__ */ React25.createElement("div", { className: "aura-command__heading", id: gid, role: "presentation" }, g.name) : null,
2942
+ g.items.map(function(it) {
2943
+ i++;
2944
+ const n2 = i;
2945
+ return /* @__PURE__ */ React25.createElement(
2946
+ "div",
2947
+ {
2948
+ key: it.id,
2949
+ id: optId(n2),
2950
+ role: "option",
2951
+ "aria-selected": n2 === active,
2952
+ "aria-disabled": it.disabled || void 0,
2953
+ className: cx("aura-command__item", n2 === active && "is-active", it.disabled && "is-disabled"),
2954
+ onPointerDown: function(e) {
2955
+ e.preventDefault();
2956
+ },
2957
+ onPointerMove: function() {
2958
+ if (!it.disabled && act[0] !== it.id) act[1](it.id);
2959
+ },
2960
+ onClick: function() {
2961
+ run(it);
2962
+ }
2929
2963
  },
2930
- onClick: function() {
2931
- run(it);
2932
- }
2933
- },
2934
- it.icon ? /* @__PURE__ */ React25.createElement(Icon, { name: it.icon }) : null,
2935
- /* @__PURE__ */ React25.createElement("span", { className: "aura-command__text" }, /* @__PURE__ */ React25.createElement("span", { className: "aura-command__label" }, it.label), it.description ? /* @__PURE__ */ React25.createElement("span", { className: "aura-command__desc" }, it.description) : null),
2936
- it.shortcut ? /* @__PURE__ */ React25.createElement("kbd", { className: "aura-command__kbd" }, it.shortcut) : null
2937
- );
2938
- })
2939
- );
2940
- })),
2964
+ it.icon ? /* @__PURE__ */ React25.createElement(Icon, { name: it.icon }) : null,
2965
+ /* @__PURE__ */ React25.createElement("span", { className: "aura-command__text" }, /* @__PURE__ */ React25.createElement("span", { className: "aura-command__label" }, it.label), it.description ? /* @__PURE__ */ React25.createElement("span", { className: "aura-command__desc" }, it.description) : null),
2966
+ it.shortcut ? /* @__PURE__ */ React25.createElement("kbd", { className: "aura-command__kbd" }, it.shortcut) : null
2967
+ );
2968
+ })
2969
+ );
2970
+ })
2971
+ ),
2972
+ /* @__PURE__ */ React25.createElement("span", { className: "aura-sr-only", role: "status" }, props.loading ? t.searching : props.loading === false && query ? t.results(flat.length) : ""),
2941
2973
  /* @__PURE__ */ React25.createElement("div", { className: "aura-command__foot", "aria-hidden": true }, t.commandHint, /* @__PURE__ */ React25.createElement("span", { className: "aura-command__mod" }, isMac() ? "\u2318K" : "Ctrl K"))
2942
2974
  )
2943
2975
  ),
@@ -3127,11 +3159,20 @@ window.Aura = (() => {
3127
3159
  const selectable = !!props.selectable;
3128
3160
  const reorderable = props.reorderable !== false && !!props.columnControls;
3129
3161
  const controls = !!props.columnControls;
3130
- const sortState = useMaybeControlled(props.sort, props.defaultSort || null, props.onSortChange);
3162
+ const oneCallback = !!props.onStateChange;
3163
+ const sortState = useMaybeControlled(
3164
+ props.sort,
3165
+ props.defaultSort || null,
3166
+ oneCallback ? null : props.onSortChange
3167
+ );
3131
3168
  const sort = sortState[0], setSort = sortState[1];
3132
3169
  const selState = useMaybeControlled(props.selected, props.defaultSelected || [], props.onSelectionChange);
3133
3170
  const selected = selState[0], setSelected = selState[1];
3134
- const pageState = useMaybeControlled(props.page, props.defaultPage || 1, props.onPageChange);
3171
+ const pageState = useMaybeControlled(
3172
+ props.page,
3173
+ props.defaultPage || 1,
3174
+ oneCallback ? null : props.onPageChange
3175
+ );
3135
3176
  const orderState = useMaybeControlled(
3136
3177
  props.columnOrder,
3137
3178
  columns.map(function(c) {
@@ -3301,11 +3342,15 @@ window.Aura = (() => {
3301
3342
  const pageRows = pageSize && !manual ? view.slice(first, first + pageSize) : view;
3302
3343
  const canSortAny = !busy && (manual ? total > 1 : rows.length > 1);
3303
3344
  const shownTotal = manual && props.totalRows == null ? first + rows.length : total;
3304
- const linkPaging = !!props.getPageHref && !props.onPageChange;
3345
+ const linkPaging = !!props.getPageHref && !props.onPageChange && !oneCallback;
3305
3346
  const prevLink = React28.useRef(null), nextLink = React28.useRef(null);
3306
- function goPage(p, focus) {
3347
+ function emit(s, p) {
3348
+ if (props.onStateChange) props.onStateChange({ sort: s, page: p });
3349
+ }
3350
+ function goPage(p, focus, quiet) {
3307
3351
  const next = Math.min(Math.max(1, p), pageCount);
3308
3352
  if (next === page) return false;
3353
+ if (!quiet) emit(sort, next);
3309
3354
  if (linkPaging) {
3310
3355
  const a = next === page - 1 ? prevLink.current : next === page + 1 ? nextLink.current : null;
3311
3356
  if (a) a.click();
@@ -3317,8 +3362,12 @@ window.Aura = (() => {
3317
3362
  return true;
3318
3363
  }
3319
3364
  function sortBy(key) {
3320
- setSort(nextSort(key));
3321
- if (!(manual && linkPaging)) goPage(1);
3365
+ applySort(nextSort(key));
3366
+ }
3367
+ function applySort(s) {
3368
+ setSort(s);
3369
+ if (!(manual && linkPaging)) goPage(1, void 0, true);
3370
+ emit(s, 1);
3322
3371
  }
3323
3372
  const rowHref = props.getRowHref;
3324
3373
  function followRow(el, e) {
@@ -3533,16 +3582,14 @@ window.Aura = (() => {
3533
3582
  label: t.sortAsc,
3534
3583
  icon: "arrow-up",
3535
3584
  onSelect: function() {
3536
- setSort({ key: c.key, dir: "asc" });
3537
- goPage(1);
3585
+ applySort({ key: c.key, dir: "asc" });
3538
3586
  }
3539
3587
  },
3540
3588
  {
3541
3589
  label: t.sortDesc,
3542
3590
  icon: "arrow-down",
3543
3591
  onSelect: function() {
3544
- setSort({ key: c.key, dir: "desc" });
3545
- goPage(1);
3592
+ applySort({ key: c.key, dir: "desc" });
3546
3593
  }
3547
3594
  },
3548
3595
  { separator: true }
@@ -3979,9 +4026,10 @@ window.Aura = (() => {
3979
4026
  className: "aura-icon-btn",
3980
4027
  "aria-label": label,
3981
4028
  onClick: function(e) {
3982
- if (props.onPageChange) {
4029
+ if (props.onPageChange || oneCallback) {
3983
4030
  e.preventDefault();
3984
4031
  pageState[1](p);
4032
+ emit(sort, p);
3985
4033
  }
3986
4034
  }
3987
4035
  },
@@ -4475,7 +4523,7 @@ window.Aura = (() => {
4475
4523
  var React32 = __toESM(require_react(), 1);
4476
4524
  var Breadcrumb = React32.forwardRef(function Breadcrumb2(props, ref) {
4477
4525
  const t = useStrings();
4478
- const Link = useLinkComponent();
4526
+ const Link = useLinkComponent(props.linkComponent);
4479
4527
  const items2 = props.items || [];
4480
4528
  return /* @__PURE__ */ React32.createElement("nav", { ref, "aria-label": props.label || t.breadcrumb, className: cx("aura-crumbs", props.className) }, /* @__PURE__ */ React32.createElement("ol", null, items2.map(function(it, i) {
4481
4529
  const last = i === items2.length - 1;
@@ -4524,7 +4572,11 @@ window.Aura = (() => {
4524
4572
 
4525
4573
  // src/responsive.tsx
4526
4574
  var React34 = __toESM(require_react(), 1);
4575
+
4576
+ // src/breakpoints.ts
4527
4577
  var breakpoints = { sm: 640, md: 768, lg: 1024, xl: 1280 };
4578
+
4579
+ // src/responsive.tsx
4528
4580
  var ORDER = ["base", "sm", "md", "lg", "xl"];
4529
4581
  function useBreakpoint() {
4530
4582
  return React34.useSyncExternalStore(subscribe, current, function() {
@@ -4693,7 +4745,7 @@ window.Aura = (() => {
4693
4745
  const ch = props.change;
4694
4746
  const dir = ch && (ch.direction || "flat");
4695
4747
  const tone2 = ch && (ch.tone || (dir === "up" ? "positive" : dir === "down" ? "negative" : "neutral"));
4696
- const Link = useLinkComponent();
4748
+ const Link = useLinkComponent(props.linkComponent);
4697
4749
  const v = props.value;
4698
4750
  const numeric = typeof v === "number" || typeof v === "string" && /\d/.test(v) && /^[\s\d.,:+\-\u2212%()\u0E3F$\u20AC\u00A3\u00A5kKmMbB]+$/.test(v.replace(/\b[A-Z]{3}\b/g, ""));
4699
4751
  const Tag3 = props.href ? Link : props.onClick ? "button" : "div";
@@ -4717,16 +4769,21 @@ window.Aura = (() => {
4717
4769
  // src/TimePicker.tsx
4718
4770
  var React41 = __toESM(require_react(), 1);
4719
4771
  var import_react_dom9 = __toESM(require_react_dom(), 1);
4772
+
4773
+ // src/text.ts
4774
+ function formatBytes(n2) {
4775
+ if (n2 == null) return "";
4776
+ if (n2 < 1024) return n2 + " B";
4777
+ let u = ["KB", "MB", "GB"], i = -1;
4778
+ do {
4779
+ n2 /= 1024;
4780
+ i++;
4781
+ } while (n2 >= 1024 && i < u.length - 1);
4782
+ return (n2 >= 10 || Math.round(n2) === n2 ? Math.round(n2) : n2.toFixed(1)) + " " + u[i];
4783
+ }
4720
4784
  function pad2(n2) {
4721
4785
  return (n2 < 10 ? "0" : "") + n2;
4722
4786
  }
4723
- function toMin(t) {
4724
- const m = /^(\d{2}):(\d{2})$/.exec(t || "");
4725
- return m ? +m[1] * 60 + +m[2] : null;
4726
- }
4727
- function fromMin(n2) {
4728
- return pad2(Math.floor(n2 / 60)) + ":" + pad2(n2 % 60);
4729
- }
4730
4787
  function parseTime(text) {
4731
4788
  let s = String(text || "").trim().toLowerCase().replace(/\s*(น\.?|นาฬิกา)$/, "").trim();
4732
4789
  const pm = /\s*(pm|p\.m\.)$/.test(s), am = /\s*(am|a\.m\.)$/.test(s);
@@ -4739,6 +4796,18 @@ window.Aura = (() => {
4739
4796
  if (hh > 23 || mm > 59) return null;
4740
4797
  return pad2(hh) + ":" + pad2(mm);
4741
4798
  }
4799
+
4800
+ // src/TimePicker.tsx
4801
+ function pad3(n2) {
4802
+ return (n2 < 10 ? "0" : "") + n2;
4803
+ }
4804
+ function toMin(t) {
4805
+ const m = /^(\d{2}):(\d{2})$/.exec(t || "");
4806
+ return m ? +m[1] * 60 + +m[2] : null;
4807
+ }
4808
+ function fromMin(n2) {
4809
+ return pad3(Math.floor(n2 / 60)) + ":" + pad3(n2 % 60);
4810
+ }
4742
4811
  var TimePicker = React41.forwardRef(function TimePicker2(props, ref) {
4743
4812
  const t = useStrings();
4744
4813
  const auto = uid(), id = props.id || auto, listId = id + "-list";
@@ -5039,16 +5108,6 @@ window.Aura = (() => {
5039
5108
 
5040
5109
  // src/FileUpload.tsx
5041
5110
  var React42 = __toESM(require_react(), 1);
5042
- function formatBytes(n2) {
5043
- if (n2 == null) return "";
5044
- if (n2 < 1024) return n2 + " B";
5045
- let u = ["KB", "MB", "GB"], i = -1;
5046
- do {
5047
- n2 /= 1024;
5048
- i++;
5049
- } while (n2 >= 1024 && i < u.length - 1);
5050
- return (n2 >= 10 || Math.round(n2) === n2 ? Math.round(n2) : n2.toFixed(1)) + " " + u[i];
5051
- }
5052
5111
  function matches(file, accept) {
5053
5112
  if (!accept) return true;
5054
5113
  const name = (file.name || "").toLowerCase(), type = (file.type || "").toLowerCase();
@@ -5507,6 +5566,8 @@ window.Aura = (() => {
5507
5566
 
5508
5567
  // src/colorScheme.tsx
5509
5568
  var React44 = __toESM(require_react(), 1);
5569
+
5570
+ // src/colorSchemeScript.ts
5510
5571
  var DEFAULT_KEY = "aura-color-scheme";
5511
5572
  var SCHEMES = ["light", "dark", "system"];
5512
5573
  var EVENT = "aura-color-scheme";
@@ -5518,6 +5579,8 @@ window.Aura = (() => {
5518
5579
  const fallback = JSON.stringify(options && options.defaultScheme || "system");
5519
5580
  return "(function(){try{var s=localStorage.getItem(" + key + ");if(s!=='light'&&s!=='dark'&&s!=='system')s=" + fallback + `;var d=document.documentElement;d.setAttribute("data-theme",s);var dark=s==='dark'||(s==='system'&&window.matchMedia('(prefers-color-scheme: dark)').matches);d.classList.toggle("dark",dark);}catch(e){}})();`;
5520
5581
  }
5582
+
5583
+ // src/colorScheme.tsx
5521
5584
  function ColorSchemeScript(props) {
5522
5585
  return /* @__PURE__ */ React44.createElement(
5523
5586
  "script",
@@ -5745,7 +5808,7 @@ window.Aura = (() => {
5745
5808
  if (p >= 1 && p <= count && p !== page) st[1](p);
5746
5809
  }
5747
5810
  const link = props.getHref;
5748
- const Link = useLinkComponent();
5811
+ const Link = useLinkComponent(props.linkComponent);
5749
5812
  function item(p, label, extra) {
5750
5813
  const common = Object.assign(
5751
5814
  {
@@ -5780,29 +5843,40 @@ window.Aura = (() => {
5780
5843
  label
5781
5844
  );
5782
5845
  }
5783
- return /* @__PURE__ */ React49.createElement("nav", { ref, className: cx("aura-pagination", props.className), "aria-label": props.label || t.pagination }, /* @__PURE__ */ React49.createElement(
5784
- IconButton,
5785
- {
5786
- icon: "chevron-left",
5787
- label: t.prevPage,
5788
- disabled: page <= 1,
5789
- onClick: function() {
5790
- go(page - 1);
5791
- }
5792
- }
5793
- ), /* @__PURE__ */ React49.createElement("ol", { className: "aura-pagination__list" }, pageList(page, count, props.siblingCount == null ? 1 : props.siblingCount).map(function(p) {
5846
+ function arrow(p, icon, label, rel, disabled) {
5847
+ if (!link || disabled)
5848
+ return /* @__PURE__ */ React49.createElement(
5849
+ IconButton,
5850
+ {
5851
+ icon,
5852
+ label,
5853
+ disabled,
5854
+ onClick: function() {
5855
+ go(p);
5856
+ }
5857
+ }
5858
+ );
5859
+ return /* @__PURE__ */ React49.createElement(
5860
+ Link,
5861
+ {
5862
+ href: link(p),
5863
+ rel,
5864
+ className: "aura-icon-btn",
5865
+ "aria-label": label,
5866
+ title: label,
5867
+ onClick: function(e) {
5868
+ if (props.onChange) {
5869
+ e.preventDefault();
5870
+ go(p);
5871
+ }
5872
+ }
5873
+ },
5874
+ /* @__PURE__ */ React49.createElement(Icon, { name: icon, size: "sm" })
5875
+ );
5876
+ }
5877
+ return /* @__PURE__ */ React49.createElement("nav", { ref, className: cx("aura-pagination", props.className), "aria-label": props.label || t.pagination }, arrow(page - 1, "chevron-left", t.prevPage, "prev", page <= 1), /* @__PURE__ */ React49.createElement("ol", { className: "aura-pagination__list" }, pageList(page, count, props.siblingCount == null ? 1 : props.siblingCount).map(function(p) {
5794
5878
  return typeof p === "number" ? /* @__PURE__ */ React49.createElement("li", { key: p }, item(p, p)) : /* @__PURE__ */ React49.createElement("li", { key: p, className: "aura-pagination__gap", "aria-hidden": true }, "\u2026");
5795
- })), /* @__PURE__ */ React49.createElement("span", { className: "aura-pagination__compact", "aria-hidden": true }, t.page(page, count)), /* @__PURE__ */ React49.createElement(
5796
- IconButton,
5797
- {
5798
- icon: "chevron-right",
5799
- label: t.nextPage,
5800
- disabled: page >= count,
5801
- onClick: function() {
5802
- go(page + 1);
5803
- }
5804
- }
5805
- ));
5879
+ })), /* @__PURE__ */ React49.createElement("span", { className: "aura-pagination__compact", "aria-hidden": true }, t.page(page, count)), arrow(page + 1, "chevron-right", t.nextPage, "next", page >= count));
5806
5880
  });
5807
5881
 
5808
5882
  // src/Accordion.tsx
@@ -247,6 +247,7 @@ a.aura-btn { text-decoration: none; }
247
247
  .aura-table__pager > span { margin-right: var(--aura-space-2); }
248
248
 
249
249
  /* Icon button — 32px round, icon in the text colour */
250
+ a.aura-icon-btn { text-decoration: none; }
250
251
  .aura-icon-btn {
251
252
  width: var(--aura-control-sm); height: var(--aura-control-sm); flex: none;
252
253
  display: inline-flex; align-items: center; justify-content: center;
@@ -1147,10 +1148,23 @@ button.aura-stepper__step:hover .aura-stepper__label { text-decoration: underlin
1147
1148
 
1148
1149
  /* Touch screens: bigger targets for days and options. */
1149
1150
  @media (pointer: coarse) {
1150
- .aura-cal { --aura-cal-cell: 40px; }
1151
+ .aura-cal { --aura-cal-cell: var(--aura-touch-target); }
1151
1152
  .aura-combo__option { min-height: 44px; }
1152
- .aura-segmented__option, .aura-segmented--sm .aura-segmented__option { height: 40px; }
1153
+ .aura-segmented__option, .aura-segmented--sm .aura-segmented__option { height: var(--aura-touch-target); }
1153
1154
  .aura-number__step { width: 44px; }
1155
+ /* 4.17: the rest of the controls under 44px on touch screens. */
1156
+ .aura-menu__item { height: var(--aura-touch-target); }
1157
+ .aura-page { min-width: var(--aura-touch-target); height: var(--aura-touch-target); }
1158
+ /* Side by side, each 44px wide (40px tall inside the 44px field), so their targets never overlap. */
1159
+ .aura-combo__clear, .aura-combo__toggle, .aura-date__toggle { width: var(--aura-touch-target); height: 40px; }
1160
+ .aura-combo__toggle, .aura-date__toggle { right: 0; }
1161
+ .aura-combo__clear, .aura-date .aura-combo__clear { right: var(--aura-touch-target); }
1162
+ .aura-combo .aura-input__control, .aura-date .aura-input__control { padding-right: calc(var(--aura-space-1) + 2 * var(--aura-touch-target)); }
1163
+ .aura-combo__clear::after, .aura-combo__toggle::after, .aura-date__toggle::after, .aura-tag__remove::after {
1164
+ content: ''; position: absolute; top: 50%; left: 50%; width: max(100%, var(--aura-touch-target)); height: max(100%, var(--aura-touch-target)); transform: translate(-50%, -50%);
1165
+ }
1166
+ .aura-tag__remove { position: relative; }
1167
+ .aura-combo.is-multi .aura-combo__clear, .aura-combo.is-multi .aura-combo__toggle { top: calc((var(--aura-input-height) - 2px - 40px) / 2); }
1154
1168
  }
1155
1169
 
1156
1170
  /* ---------- Small screens (< 640px) ---------- */
@@ -1160,7 +1174,7 @@ button.aura-stepper__step:hover .aura-stepper__label { text-decoration: underlin
1160
1174
  .aura-stepper--horizontal .aura-stepper__item:not(:last-child)::after { right: 8px; }
1161
1175
  .aura-stepper--horizontal .aura-stepper__compact { display: block; }
1162
1176
  .aura-dialog-layer:not(.aura-drawer-layer) { align-items: flex-end; padding: 0; }
1163
- .aura-dialog { max-width: none !important; max-height: 92vh; border-radius: var(--aura-radius-2xl) var(--aura-radius-2xl) 0 0; border-bottom: 0;
1177
+ .aura-dialog { max-width: none !important; max-height: 92vh; max-height: 92dvh; border-radius: var(--aura-radius-2xl) var(--aura-radius-2xl) 0 0; border-bottom: 0;
1164
1178
  padding-bottom: calc(var(--aura-space-6) + env(safe-area-inset-bottom)); animation-name: aura-sheet-in; }
1165
1179
  .aura-dialog__foot { flex-direction: column-reverse; }
1166
1180
  .aura-dialog__foot > * { width: 100%; }
@@ -1275,6 +1289,7 @@ button.aura-stepper__step:hover .aura-stepper__label { text-decoration: underlin
1275
1289
  flex: none; padding: 2px 6px; border: 1px solid var(--aura-border-default); border-radius: var(--aura-radius-xs);
1276
1290
  font-family: var(--font-mono); font-size: 11px; line-height: 16px; color: var(--aura-fg-secondary); background: var(--aura-bg-canvas);
1277
1291
  }
1292
+ .aura-command__loading { display: flex; align-items: center; gap: var(--aura-space-2); padding: var(--aura-space-2) var(--aura-space-3); font-size: 13px; color: var(--aura-fg-secondary); }
1278
1293
  .aura-command__empty { margin: 0; padding: var(--aura-space-6) var(--aura-space-2); text-align: center; font-size: 14px; color: var(--aura-fg-secondary); }
1279
1294
  .aura-command__foot { display: flex; justify-content: space-between; gap: var(--aura-space-3); padding: var(--aura-space-2) var(--aura-space-4); border-top: 1px solid var(--aura-border-default); font-size: 12px; color: var(--aura-fg-secondary); }
1280
1295
  @media (max-width: 639.98px) {
@@ -41,6 +41,11 @@ export interface ButtonLinkProps extends Omit<React$1.AnchorHTMLAttributes<HTMLA
41
41
  /** A router's link to render instead of `<a>`, e.g. `Link` from `next/link` (client-side navigation). It gets `href`, `className`, the children and the ref. */
42
42
  linkComponent?: React$1.ElementType | undefined;
43
43
  }
44
+ /** What DataTable's onStateChange reports: the sort and the 1-based page, together. */
45
+ export interface DataTableState {
46
+ sort: DataTableSort | null;
47
+ page: number;
48
+ }
44
49
  export interface DataTableColumn {
45
50
  /** Key into each row object. */
46
51
  key: string;
@@ -119,6 +124,10 @@ export interface DataTableProps {
119
124
  /** Initial page when uncontrolled. Default 1. */
120
125
  defaultPage?: number | undefined;
121
126
  onPageChange?: ((page: number) => void) | undefined;
127
+ /** Sort and page in one callback (4.17): a sort click reports `{ sort, page: 1 }` once, a page change
128
+ * `{ sort, page }`. When set, onSortChange and onPageChange are not called for them, so an app that keeps both in
129
+ * the URL does one navigation per click. Pair with `sort` + `page` for controlled state. */
130
+ onStateChange?: ((state: DataTableState) => void) | undefined;
122
131
  /** Adds drag/keyboard resize handles to every column that has a width. */
123
132
  resizable?: boolean | undefined;
124
133
  onColumnResize?: ((key: string, width: number) => void) | undefined;
@@ -362,10 +371,20 @@ export interface CommandProps {
362
371
  placeholder?: string | undefined;
363
372
  /** Default "No matches". */
364
373
  emptyText?: string | undefined;
374
+ /** Shown when nothing matches, instead of `emptyText`: any content, e.g. a hint and a "Create member" button. (4.17) */
375
+ empty?: React$1.ReactNode | undefined;
365
376
  /** ⌘K / Ctrl+K toggles the palette from anywhere on the page. Default true. */
366
377
  hotkey?: boolean | undefined;
367
- /** Replace the Thai-aware default filter. */
368
- filter?: ((item: CommandItem, query: string) => boolean) | undefined;
378
+ /** Replace the Thai-aware default filter, or `false` to show `items` as given — for results your server already
379
+ * searched (4.17). */
380
+ filter?: ((item: CommandItem, query: string) => boolean) | false | undefined;
381
+ /** The search text, controlled (4.17). Pair with `onQueryChange`; fetch results for it and pass them as `items`. */
382
+ query?: string | undefined;
383
+ /** Called on every keystroke, and with "" when the palette closes. (4.17) */
384
+ onQueryChange?: ((query: string) => void) | undefined;
385
+ /** Results are on their way: a "Searching…" row, `aria-busy`, and the result count announced when they arrive. The
386
+ * current items stay listed meanwhile. (4.17) */
387
+ loading?: boolean | undefined;
369
388
  className?: string | undefined;
370
389
  }
371
390
  export interface TextareaProps extends FieldProps, Omit<React$1.TextareaHTMLAttributes<HTMLTextAreaElement>, "required"> {
@@ -554,6 +573,8 @@ export interface BreadcrumbProps {
554
573
  onClick?: (() => void) | undefined;
555
574
  }>;
556
575
  label?: string | undefined;
576
+ /** Your router's link (e.g. `Link` from `next/link`) for this component; defaults to AuraProvider's `linkComponent`, then `<a>`. */
577
+ linkComponent?: React$1.ElementType | undefined;
557
578
  className?: string | undefined;
558
579
  }
559
580
  export interface AvatarProps {
@@ -813,6 +834,8 @@ export interface StatChange {
813
834
  label?: React$1.ReactNode | undefined;
814
835
  }
815
836
  export interface StatProps {
837
+ /** Your router's link (e.g. `Link` from `next/link`) for this component; defaults to AuraProvider's `linkComponent`, then `<a>`. */
838
+ linkComponent?: React$1.ElementType | undefined;
816
839
  label: React$1.ReactNode;
817
840
  value?: React$1.ReactNode | undefined;
818
841
  /** Small unit after the value ("งาน", "คน", "%"). */
@@ -943,9 +966,12 @@ export interface PaginationProps {
943
966
  onChange?: ((page: number) => void) | undefined;
944
967
  /** Pages shown each side of the current one. Default 1. */
945
968
  siblingCount?: number | undefined;
946
- /** Render real links (SEO, open in new tab); onChange still runs for client routing. */
969
+ /** Render real links — page numbers and the previous / next arrows (4.17) — through your router's link. With
970
+ * `onChange` too, onChange runs instead of following the link. */
947
971
  getHref?: ((page: number) => string) | undefined;
948
972
  label?: string | undefined;
973
+ /** Your router's link (e.g. `Link` from `next/link`) for this component; defaults to AuraProvider's `linkComponent`, then `<a>`. */
974
+ linkComponent?: React$1.ElementType | undefined;
949
975
  className?: string | undefined;
950
976
  }
951
977
  export interface AccordionItem {
@@ -1077,11 +1103,11 @@ export type FormatDateOptions = DateDisplayOptions & {
1077
1103
  };
1078
1104
  /** Format an ISO date for display, e.g. "18 ก.ย. 2569" (th, Buddhist) or "18 Sept 2026" (en, Gregorian). */
1079
1105
  export declare function formatDate(iso: ISODate | null | undefined, opts?: FormatDateOptions): string;
1106
+ /** Parse typed text: dd/mm/yyyy (Buddhist years ≥ 2400 are converted), d-m-yyyy, d.m.yyyy, yyyy-mm-dd or '18 ก.ย. 2569' / '18 Sep 2026'. */
1107
+ export declare function parseDate(text: string | null | undefined): ISODate | null;
1080
1108
  /** formatDate bound to the nearest AuraProvider: its locale and calendar (English, Gregorian without one).
1081
1109
  * Options you pass still win. Use it in components; plain formatDate() stays for code outside React. */
1082
1110
  export declare function useFormatDate(): (iso: ISODate | null | undefined, opts?: FormatDateOptions) => string;
1083
- /** Parse typed text: dd/mm/yyyy (Buddhist years ≥ 2400 are converted), d-m-yyyy, d.m.yyyy, yyyy-mm-dd or '18 ก.ย. 2569' / '18 Sep 2026'. */
1084
- export declare function parseDate(text: string | null | undefined): ISODate | null;
1085
1111
  export declare const Calendar: React$1.ForwardRefExoticComponent<CalendarProps & React$1.RefAttributes<HTMLDivElement>>;
1086
1112
  /** Typed date field + calendar popover. English / Gregorian unless a locale is set; `th` shows Buddhist-era dates (18 ก.ย. 2569) and accepts พ.ศ. or ค.ศ. years. The value is always a Gregorian ISO date. */
1087
1113
  export declare const DatePicker: React$1.ForwardRefExoticComponent<DatePickerProps & React$1.RefAttributes<HTMLInputElement>>;
@@ -1249,11 +1275,11 @@ export declare function useAuraLocale(): AuraLocaleValue;
1249
1275
  /** The provider's density, for portals that render outside its wrapper. */
1250
1276
  export declare function useDensity(): "comfortable" | "compact" | undefined;
1251
1277
  export declare const Stat: React$1.ForwardRefExoticComponent<StatProps & React$1.RefAttributes<HTMLElement>>;
1278
+ /** 1536 → "1.5 KB". */
1279
+ export declare function formatBytes(n: number | null | undefined): string;
1252
1280
  /** Parse typed time: 9 · 09 · 930 · 0930 · 9:30 · 9.30 · 09.30 น. · 9:30 pm → "HH:mm" (24-hour) or null. */
1253
1281
  export declare function parseTime(text: string | null | undefined): string | null;
1254
1282
  export declare const TimePicker: React$1.ForwardRefExoticComponent<TimePickerProps & React$1.RefAttributes<HTMLInputElement>>;
1255
- /** 1536 → "1.5 KB". */
1256
- export declare function formatBytes(n: number | null | undefined): string;
1257
1283
  export declare const FileUpload: React$1.ForwardRefExoticComponent<FileUploadProps & React$1.RefAttributes<HTMLInputElement>>;
1258
1284
  /** WCAG contrast ratio of two #hex colours. */
1259
1285
  export declare function contrast(a: string, b: string): number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jirawatpyk/aura-tokens",
3
- "version": "4.16.0",
3
+ "version": "4.17.0",
4
4
  "description": "AURA Design System — tokens (CSS variables, Tailwind preset, Figma variables), theme contrast checks and token lint.",
5
5
  "main": "tailwind.tokens.cjs",
6
6
  "types": "components/index.d.ts",
@@ -13,6 +13,7 @@
13
13
  "tailwind.config.ts",
14
14
  "tailwind.tokens.cjs",
15
15
  "aura-tailwind.css",
16
+ "aura-tailwind.prefixed.css",
16
17
  "figma-variables.csv",
17
18
  "eslint-plugin-aura.js",
18
19
  "components/aura.bundle.js",
@@ -32,6 +33,7 @@
32
33
  "./tokens.json": "./tokens.json",
33
34
  "./tailwind": "./tailwind.tokens.cjs",
34
35
  "./tailwind.css": "./aura-tailwind.css",
36
+ "./tailwind.prefixed.css": "./aura-tailwind.prefixed.css",
35
37
  "./components.js": "./components/aura.bundle.js",
36
38
  "./components.css": "./components/aura.components.css",
37
39
  "./eslint-plugin": "./eslint-plugin-aura.js"
@@ -41,7 +43,7 @@
41
43
  "a11y": "node scripts/a11y-check.js",
42
44
  "check:tailwind4": "node scripts/tailwind4-check.mjs",
43
45
  "lint:tokens": "node scripts/lint-tokens.js ../react/src && node scripts/lint-tokens.js ../react/styles",
44
- "check:generated": "node scripts/build-tokens.js && git diff --exit-code -- aura.css aura-fonts.css aura-fonts.local.css tailwind.tokens.cjs aura-tailwind.css figma-variables.csv",
46
+ "check:generated": "node scripts/build-tokens.js && git diff --exit-code -- aura.css aura-fonts.css aura-fonts.local.css tailwind.tokens.cjs aura-tailwind.css aura-tailwind.prefixed.css figma-variables.csv",
45
47
  "prepack": "npm run build",
46
48
  "check:fonts": "node scripts/fonts-check.mjs"
47
49
  },
package/tokens.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "4.16.0",
2
+ "version": "4.17.0",
3
3
  "meta": {
4
4
  "name": "AURA Design System",
5
5
  "tier": "3-tier",