@jirawatpyk/aura-react 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 +66 -3
- package/dist/aura.bundle.js +198 -124
- package/dist/cjs/index.cjs +198 -124
- package/dist/esm/Breadcrumb.js +1 -1
- package/dist/esm/Command.js +69 -49
- package/dist/esm/DataTable.js +27 -11
- package/dist/esm/DatePicker.js +17 -146
- package/dist/esm/FileUpload.js +1 -10
- package/dist/esm/Pagination.js +35 -23
- package/dist/esm/Stat.js +1 -1
- package/dist/esm/StatusPill.js +4 -13
- package/dist/esm/TimePicker.js +1 -12
- package/dist/esm/breakpoints.js +5 -0
- package/dist/esm/colorScheme.js +1 -11
- package/dist/esm/colorSchemeScript.js +19 -0
- package/dist/esm/dates.js +164 -0
- package/dist/esm/locale.js +1 -347
- package/dist/esm/responsive.js +1 -1
- package/dist/esm/status.js +17 -0
- package/dist/esm/strings.js +351 -0
- package/dist/esm/text.js +30 -0
- package/dist/index.d.ts +33 -7
- package/dist/server/index.cjs +791 -0
- package/dist/server/index.d.ts +171 -0
- package/dist/server/index.js +768 -0
- package/dist/styles.css +18 -3
- package/dist/styles.layer.css +1352 -0
- package/package.json +8 -2
package/README.md
CHANGED
|
@@ -80,12 +80,27 @@ Actions: Button (`ghost`, `size="sm"`), IconButton, Menu, DropdownMenu, Tag · F
|
|
|
80
80
|
|
|
81
81
|
## Router links, Swedish, motion
|
|
82
82
|
|
|
83
|
+
Next.js App Router: `next/link` is a function, and a Server Component (your layout) can't pass functions to a client component. Put the provider in a small `'use client'` file:
|
|
84
|
+
|
|
83
85
|
```tsx
|
|
86
|
+
// app/providers.tsx
|
|
87
|
+
'use client';
|
|
84
88
|
import Link from 'next/link';
|
|
85
|
-
|
|
89
|
+
import { AuraProvider } from '@jirawatpyk/aura-react';
|
|
90
|
+
export function Providers({ children, locale }: { children: React.ReactNode; locale: 'th' | 'en' | 'sv' }) {
|
|
91
|
+
return (
|
|
92
|
+
<AuraProvider locale={locale} linkComponent={Link}>
|
|
93
|
+
{children}
|
|
94
|
+
</AuraProvider>
|
|
95
|
+
);
|
|
96
|
+
{
|
|
97
|
+
/* th | en | sv */
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
// app/layout.tsx (a Server Component): <body><Providers locale="th">{children}</Providers></body>
|
|
86
101
|
```
|
|
87
102
|
|
|
88
|
-
`linkComponent` is used by Button `href`, Breadcrumb, Pagination `getHref
|
|
103
|
+
`linkComponent` is used by Button `href`, Breadcrumb, Pagination `getHref` (page numbers and, since 4.17, the previous / next arrows), Stat `href`, SideNav and DataTable row/pager links. Each of them also takes its own `linkComponent`, which wins over the provider's. Pass `getHref` from a client component (it's a function too). The Next.js starter does all of this, and CI clicks every AURA link in it to check none triggers a full page load. Only `th` shows Buddhist-era years; `en` and `sv` are Gregorian (`sv` weeks start Monday). **Without a provider, components are English with Gregorian dates** — wrap Thai apps in `<AuraProvider locale="th">`. For dates in your own components use `useFormatDate()` — it follows the provider (`const fmt = useFormatDate(); fmt(iso, { format: 'long' })`). Plain `formatDate()` from the package root has no provider to read and stays Thai unless you pass `locale` (until 5.0); the one in `@jirawatpyk/aura-react/server` defaults to English and Gregorian. Values are always Gregorian ISO dates.
|
|
89
104
|
|
|
90
105
|
## Compact density
|
|
91
106
|
|
|
@@ -123,9 +138,30 @@ toast.error('Could not save'); // danger = role="alert"; the rest
|
|
|
123
138
|
<Command open={open} onOpenChange={setOpen} items={commands} /> {/* ⌘K / Ctrl+K toggles it */}
|
|
124
139
|
```
|
|
125
140
|
|
|
141
|
+
Server search in the palette (4.17): control the query and hand over what the server found. The active item is kept by id while results change, and `loading` announces "Searching…" and then the count.
|
|
142
|
+
|
|
143
|
+
```tsx
|
|
144
|
+
<Command
|
|
145
|
+
open={open}
|
|
146
|
+
onOpenChange={setOpen}
|
|
147
|
+
query={q}
|
|
148
|
+
onQueryChange={setQ} // fetch results for q (debounced)
|
|
149
|
+
items={results}
|
|
150
|
+
filter={false}
|
|
151
|
+
loading={isFetching}
|
|
152
|
+
empty={
|
|
153
|
+
<Button size="sm" icon="plus">
|
|
154
|
+
Create member
|
|
155
|
+
</Button>
|
|
156
|
+
}
|
|
157
|
+
/>
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
DataTable with sort and page in the URL (4.17): `onStateChange={({ sort, page }) => router.push(…)}` reports a sort click once, as `{ sort, page: 1 }`, instead of `onSortChange` and then `onPageChange(1)`. That's one history entry and one server render.
|
|
161
|
+
|
|
126
162
|
## Phones and touch
|
|
127
163
|
|
|
128
|
-
Under 640px every text control uses 16px text (iOS Safari doesn't zoom). On touch screens (`pointer: coarse`) IconButton and `<Button size="sm">` keep their 32px look with a 44px hit area, and Radio, Checkbox and Switch rows are at least 44px with the whole row as the target. `<Button fullWidth>` fills its row and wraps long Thai or Swedish labels.
|
|
164
|
+
Under 640px every text control uses 16px text (iOS Safari doesn't zoom). On touch screens (`pointer: coarse`) IconButton and `<Button size="sm">` keep their 32px look with a 44px hit area, and Radio, Checkbox and Switch rows are at least 44px with the whole row as the target. Since 4.17 so are menu items, page numbers, segments and calendar days (44px); Combobox and DatePicker toggles and the Tag remove button get 44px hit areas. A Dialog sheet on a phone is capped at `92dvh`, so the browser toolbar never hides its footer. `<Button fullWidth>` fills its row and wraps long Thai or Swedish labels.
|
|
129
165
|
|
|
130
166
|
## Light and dark
|
|
131
167
|
|
|
@@ -163,6 +199,33 @@ Portals (Dialog, Drawer, menus, pickers, toasts) wait until after hydration; `us
|
|
|
163
199
|
|
|
164
200
|
Layout is right before hydration (4.16). AppShell's sidebar-or-drawer switch is CSS (a 1024px media query), so a phone gets the menu button from the server's HTML. A DataTable with `stackBelow` renders cards and grid together until it has measured itself, and a container query shows the right one. It supports `stackBelow` 360, 400, 480, 520, 560, 600, 640, 720, 768, 800, 900, 960 and 1024; other widths stack once JavaScript runs. `npm run test:layout` loads both at 390 and 1280px with JavaScript off, then hydrated, and requires CLS 0. Columns with `hideBelow` still settle after hydration.
|
|
165
201
|
|
|
202
|
+
## Next to another Tailwind theme (shadcn), page by page
|
|
203
|
+
|
|
204
|
+
`styles.css` is unlayered, so it beats utilities. For a migration next to an existing theme, use the layered stylesheet and the prefixed Tailwind theme (4.17):
|
|
205
|
+
|
|
206
|
+
```css
|
|
207
|
+
@layer aura-tokens, theme, base, aura, components, utilities;
|
|
208
|
+
@import 'tailwindcss';
|
|
209
|
+
@import '@jirawatpyk/aura-tokens/aura.css' layer(aura-tokens); /* your theme wins for --font-sans / --font-mono */
|
|
210
|
+
@import '@jirawatpyk/aura-tokens/tailwind.prefixed.css'; /* bg-aura-bg-surface, font-aura-sans … no @custom-variant */
|
|
211
|
+
@import '@jirawatpyk/aura-react/styles.layer.css'; /* components in @layer aura: a utility className wins */
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
Nothing an existing page uses is redefined: `npm run check:tailwind4` compiles a shadcn-style page alone and next to this setup, with AURA imported first and last. It checks that the computed styles are identical, and that `rounded-none` overrides `.aura-btn` with no `!important`. While both run, AURA components use your `--font-sans` / `--font-mono`; set them to AURA's stacks in your token bridge when a page moves over.
|
|
215
|
+
|
|
216
|
+
## Server Components
|
|
217
|
+
|
|
218
|
+
Everything in the package root is a client module (`'use client'`), so a Server Component can render AURA components but can't call AURA functions. The pure helpers have their own entry with no `'use client'` and no React (4.17):
|
|
219
|
+
|
|
220
|
+
```tsx
|
|
221
|
+
// app/invoices/[id]/page.tsx — a Server Component
|
|
222
|
+
import { formatDate, createTheme, statusTone, STRINGS } from '@jirawatpyk/aura-react/server';
|
|
223
|
+
formatDate('2026-09-24'); // "24 Sept 2026" — English and Gregorian by default
|
|
224
|
+
formatDate('2026-09-24', { locale: 'th' }); // "24 ก.ย. 2569"
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
It exports `formatDate`, `parseDate`, `toISO`, `fromISO`, `parseTime`, `formatBytes`, `statusTone`, `STRINGS`, `createTheme`, `contrast`, `brandScale`, `colorSchemeScript` and `breakpoints`. `npm run test:ssr` loads it under Node's `react-server` condition, and the Next.js starter formats a date with it in a Server Component.
|
|
228
|
+
|
|
166
229
|
## TypeScript
|
|
167
230
|
|
|
168
231
|
Every optional prop takes `undefined` (4.16), so apps on `exactOptionalPropertyTypes` can write `hint={t.hint}` or `icon={x ?? undefined}`. `types-test/exact-optional.tsx` checks every exported component against the published declarations under `strict`, `exactOptionalPropertyTypes` and `noUncheckedIndexedAccess`.
|
package/dist/aura.bundle.js
CHANGED
|
@@ -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
|
-
|
|
950
|
-
|
|
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
|
|
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
|
-
|
|
2779
|
-
act[1](
|
|
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,
|
|
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
|
|
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:
|
|
2911
|
+
value: query,
|
|
2892
2912
|
autoComplete: "off",
|
|
2893
2913
|
spellCheck: false,
|
|
2894
2914
|
onChange: function(e) {
|
|
2895
|
-
|
|
2896
|
-
act[1](
|
|
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(
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
"
|
|
2905
|
-
|
|
2906
|
-
|
|
2907
|
-
|
|
2908
|
-
|
|
2909
|
-
|
|
2910
|
-
|
|
2911
|
-
|
|
2912
|
-
g
|
|
2913
|
-
|
|
2914
|
-
|
|
2915
|
-
|
|
2916
|
-
|
|
2917
|
-
|
|
2918
|
-
|
|
2919
|
-
|
|
2920
|
-
|
|
2921
|
-
|
|
2922
|
-
|
|
2923
|
-
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
|
|
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
|
-
|
|
2931
|
-
|
|
2932
|
-
}
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
|
|
2936
|
-
|
|
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
|
|
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(
|
|
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
|
|
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
|
-
|
|
3321
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
5784
|
-
|
|
5785
|
-
|
|
5786
|
-
|
|
5787
|
-
|
|
5788
|
-
|
|
5789
|
-
|
|
5790
|
-
|
|
5791
|
-
|
|
5792
|
-
|
|
5793
|
-
|
|
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)),
|
|
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
|