@jirawatpyk/aura-react 5.0.1 → 5.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/README.md +8 -0
  2. package/dist/aura.bundle.js +464 -154
  3. package/dist/cjs/index.cjs +464 -154
  4. package/dist/esm/AppShell.js +10 -2
  5. package/dist/esm/Avatar.js +4 -3
  6. package/dist/esm/BottomNav.js +2 -1
  7. package/dist/esm/Checkbox.js +13 -4
  8. package/dist/esm/Combobox.js +19 -19
  9. package/dist/esm/Command.js +1 -0
  10. package/dist/esm/DataTable.js +46 -14
  11. package/dist/esm/DatePicker.js +81 -18
  12. package/dist/esm/DropdownMenu.js +12 -0
  13. package/dist/esm/FileUpload.js +15 -0
  14. package/dist/esm/FormErrorSummary.js +19 -4
  15. package/dist/esm/Icon.js +1 -1
  16. package/dist/esm/Menu.js +20 -7
  17. package/dist/esm/NumberField.js +3 -1
  18. package/dist/esm/Pagination.js +3 -3
  19. package/dist/esm/Popover.js +11 -1
  20. package/dist/esm/RadioGroup.js +14 -1
  21. package/dist/esm/SideNav.js +8 -2
  22. package/dist/esm/StatusPill.js +1 -0
  23. package/dist/esm/Switch.js +1 -1
  24. package/dist/esm/Table.js +3 -2
  25. package/dist/esm/Tabs.js +11 -7
  26. package/dist/esm/TextField.js +2 -2
  27. package/dist/esm/Textarea.js +2 -2
  28. package/dist/esm/ThemeStyle.js +13 -3
  29. package/dist/esm/Toaster.js +1 -0
  30. package/dist/esm/Tooltip.js +54 -29
  31. package/dist/esm/colorScheme.js +7 -3
  32. package/dist/esm/colorSchemeScript.js +3 -3
  33. package/dist/esm/dates.js +6 -3
  34. package/dist/esm/internal.js +32 -7
  35. package/dist/esm/locale.js +6 -5
  36. package/dist/esm/status.js +2 -1
  37. package/dist/esm/theme.js +3 -1
  38. package/dist/esm/useModal.js +42 -9
  39. package/dist/index.d.cts +1508 -0
  40. package/dist/index.d.ts +13 -6
  41. package/dist/server/index.cjs +7 -4
  42. package/dist/server/index.d.cts +176 -0
  43. package/dist/server/index.d.ts +2 -1
  44. package/dist/server/index.js +7 -4
  45. package/dist/styles.css +23 -3
  46. package/dist/styles.layer.css +23 -3
  47. package/package.json +19 -8
package/dist/index.d.ts CHANGED
@@ -177,7 +177,7 @@ export interface DataTableProps {
177
177
  }
178
178
  /** An AURA icon name, or any icon element (e.g. `<Building />` from lucide-react). AURA sizes it and hides it from screen readers. */
179
179
  export type IconInput = IconName | React$1.ReactElement;
180
- export type IconName = "check" | "x" | "plus" | "minus" | "search" | "chevron-down" | "chevron-up" | "chevron-left" | "chevron-right" | "arrow-right" | "arrow-up-right" | "arrow-up-down" | "loader-circle" | "circle-alert" | "circle-check" | "info" | "triangle-alert" | "settings" | "user" | "users" | "filter" | "ellipsis" | "external-link" | "copy" | "trash-2" | "pencil" | "download" | "upload" | "calendar" | "bell" | "menu" | "eye" | "log-out" | "circle" | "circle-dot-dashed" | "ban" | "arrow-up" | "arrow-down" | "inbox" | "pin" | "pin-off" | "eye-off" | "columns-3" | "arrow-left" | "rotate-ccw" | "house" | "layout-dashboard" | "folder" | "chart-column" | "file-text" | "mail" | "lock" | "clock" | "trending-up" | "trending-down" | "image" | "paperclip" | "cloud-upload" | "file" | "sun" | "moon" | "monitor" | "panel-left-close" | "panel-left-open";
180
+ export type IconName = "check" | "x" | "plus" | "minus" | "search" | "chevron-down" | "chevron-up" | "chevron-left" | "chevron-right" | "arrow-right" | "arrow-up-right" | "arrow-up-down" | "loader-circle" | "circle-alert" | "circle-check" | "info" | "triangle-alert" | "settings" | "user" | "users" | "filter" | "ellipsis" | "external-link" | "copy" | "trash-2" | "pencil" | "download" | "upload" | "calendar" | "bell" | "menu" | "eye" | "log-out" | "circle" | "circle-dot-dashed" | "ban" | "arrow-up" | "arrow-down" | "inbox" | "pin" | "pin-off" | "eye-off" | "columns-3" | "arrow-left" | "rotate-ccw" | "house" | "layout-dashboard" | "folder" | "chart-column" | "file-text" | "mail" | "lock" | "clock" | "trending-up" | "trending-down" | "image" | "paperclip" | "cloud-upload" | "file" | "sun" | "moon" | "monitor" | "panel-left-close" | "panel-left-open" | "server" | "globe" | "activity" | "shield-alert" | "phone" | "wrench";
181
181
  /** Lucide stroke icon drawn inline in currentColor. */
182
182
  export interface IconProps {
183
183
  /** A name from the set, or an icon element of your own (sized and styled the same way). */
@@ -214,12 +214,13 @@ export interface AuraProviderProps {
214
214
  linkComponent?: React$1.ElementType | undefined;
215
215
  children?: React$1.ReactNode | undefined;
216
216
  }
217
- export type StatusTone = "neutral" | "progress" | "ready" | "blocked";
217
+ /** `warning` (5.1): needs attention but still works — Warning, Problem, Degraded, At risk. */
218
+ export type StatusTone = "neutral" | "progress" | "ready" | "warning" | "blocked";
218
219
  /** Status pill: tone fill + icon + the status word. Tone comes from the word unless given. */
219
220
  export interface StatusPillProps {
220
221
  /** The status word shown, e.g. "In Progress". */
221
222
  children: React$1.ReactNode;
222
- /** Force a tone. Default: matched from the word (Ready/Done → ready, In Progress/In Review → progress, Blocked/Failed → blocked, anything else → neutral). */
223
+ /** Force a tone. Default: matched from the word (Ready/Done → ready, In Progress/In Review → progress, Warning/Problem/Degraded/At risk → warning (5.1), Blocked/Failed → blocked, anything else → neutral). */
223
224
  tone?: StatusTone | undefined;
224
225
  className?: string | undefined;
225
226
  }
@@ -229,9 +230,12 @@ export interface CheckboxProps extends Omit<React$1.InputHTMLAttributes<HTMLInpu
229
230
  checked?: boolean | undefined;
230
231
  defaultChecked?: boolean | undefined;
231
232
  indeterminate?: boolean | undefined;
232
- /** Accessible name for a bare box (tables). Not needed when children give a visible label. */
233
+ /** Accessible name. In 5.x it is shown only when given as children; **6.0 shows `label` beside the box** like
234
+ * Switch and TextField. Without children and without `hideLabel` it warns once in development. */
233
235
  label?: string | undefined;
234
- /** Visible label beside the box (form use). */
236
+ /** A bare box named by `label`, e.g. in a table row: keeps it hidden in 6.0 and silences the 5.1 notice. */
237
+ hideLabel?: boolean | undefined;
238
+ /** The visible label beside the box. */
235
239
  children?: React$1.ReactNode | undefined;
236
240
  /** Second line under the visible label (needs an id to be linked). */
237
241
  description?: React$1.ReactNode | undefined;
@@ -590,6 +594,9 @@ export interface SideNavProps {
590
594
  onCollapsedChange?: ((collapsed: boolean) => void) | undefined;
591
595
  /** Adds a collapse / expand button at the bottom. AppShell hides it in its phone drawer. */
592
596
  collapsible?: boolean | undefined;
597
+ /** The 1px right edge that divides the nav from the page. Default true; `false` when your layout draws its own
598
+ * divider. (5.1) */
599
+ bordered?: boolean | undefined;
593
600
  className?: string | undefined;
594
601
  }
595
602
  export interface BreadcrumbProps {
@@ -1447,7 +1454,7 @@ export interface ThemeStyleProps extends ThemeOptions {
1447
1454
  /** Scope the theme to this selector instead of the whole page (multi-tenant). */
1448
1455
  selector?: string | undefined;
1449
1456
  }
1450
- export declare function ThemeStyle(props: ThemeStyleProps): React$1.ReactElement;
1457
+ export declare function ThemeStyle(props: ThemeStyleProps): React$1.ReactElement | null;
1451
1458
  /** `system` follows the operating system and changes with it. */
1452
1459
  export type ColorScheme = "light" | "dark" | "system";
1453
1460
  export interface ColorSchemeOptions {
@@ -159,6 +159,7 @@ function parseTime(text) {
159
159
  var TONE_WORDS = {
160
160
  ready: ["ready", "done", "complete", "completed", "approved", "live", "passed"],
161
161
  progress: ["in progress", "in review", "review", "syncing", "running", "pending"],
162
+ warning: ["warning", "problem", "degraded", "at risk"],
162
163
  blocked: ["blocked", "failed", "error", "rejected", "on hold", "cancelled"]
163
164
  };
164
165
  function toneFor(status) {
@@ -766,6 +767,8 @@ function createTheme(opts) {
766
767
  }
767
768
  if (s) check("light", "ink", "accent-lime (signal)", 4.5, INK, s[200]);
768
769
  function css(selector) {
770
+ if (selector !== void 0 && /[<{};@\r\n]|\/\*|\*\//.test(selector))
771
+ throw new Error('createTheme: "' + selector + '" is not a plain CSS selector');
769
772
  const light = selector ? selector : ':root, [data-theme="light"]';
770
773
  const dark = selector ? selector + ".dark, .dark " + selector + ", " + selector + '[data-theme="dark"], [data-theme="dark"] ' + selector : '.dark, [data-theme="dark"]';
771
774
  const system = selector ? '[data-theme="system"] ' + selector + ", " + selector + '[data-theme="system"]' : '[data-theme="system"]';
@@ -774,7 +777,7 @@ function createTheme(opts) {
774
777
  return " --aura-" + k + ": " + m[k] + ";";
775
778
  }).join("\n") + "\n}";
776
779
  }
777
- return "/* AURA theme" + (o.name ? ' "' + o.name + '"' : "") + ": brand " + o.brand + (o.signal ? ", signal " + o.signal : "") + (o.primary === "brand" ? ", brand primary buttons" : "") + ". Load after aura.css. Generated by createTheme. */\n" + block(light, L) + "\n" + block(dark, D) + "\n@media (prefers-color-scheme: dark) {\n" + block(system, D) + "\n}\n";
780
+ return "/* AURA theme" + (o.name ? ' "' + String(o.name).replace(/[*/<>\\]/g, "") + '"' : "") + ": brand " + o.brand + (o.signal ? ", signal " + o.signal : "") + (o.primary === "brand" ? ", brand primary buttons" : "") + ". Load after aura.css. Generated by createTheme. */\n" + block(light, L) + "\n" + block(dark, D) + "\n@media (prefers-color-scheme: dark) {\n" + block(system, D) + "\n}\n";
778
781
  }
779
782
  return {
780
783
  name: o.name || null,
@@ -793,9 +796,9 @@ function createTheme(opts) {
793
796
  // src/colorSchemeScript.ts
794
797
  var DEFAULT_KEY = "aura-color-scheme";
795
798
  function colorSchemeScript(options) {
796
- const key = JSON.stringify(options && options.storageKey || DEFAULT_KEY);
797
- const fallback = JSON.stringify(options && options.defaultScheme || "system");
798
- 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){}})();`;
799
+ const key = JSON.stringify(options && options.storageKey || DEFAULT_KEY).replace(/</g, "\\u003c");
800
+ const fallback = JSON.stringify(options && options.defaultScheme || "system").replace(/</g, "\\u003c");
801
+ 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 m=window.matchMedia('(prefers-color-scheme: dark)');d.classList.toggle('dark',s==='dark'||(s==='system'&&m.matches));if(m.addEventListener)m.addEventListener('change',function(e){if(d.getAttribute('data-theme')==='system')d.classList.toggle('dark',e.matches)});}catch(e){}})();`;
799
802
  }
800
803
 
801
804
  // src/breakpoints.ts
@@ -0,0 +1,176 @@
1
+ import * as React$1 from 'react';
2
+
3
+ /** `warning` (5.1): needs attention but still works — Warning, Problem, Degraded, At risk. */
4
+ export type StatusTone = "neutral" | "progress" | "ready" | "warning" | "blocked";
5
+ /** ISO date string, `YYYY-MM-DD` (Gregorian — the era is display only). */
6
+ export type ISODate = string;
7
+ export interface DateDisplayOptions {
8
+ /** Components: the AuraProvider's locale, else `en`. `formatDate()` (no provider to read): `en` unless given (5.0; `th` before). */
9
+ locale?: "th" | "en" | "sv" | undefined;
10
+ /** `buddhist` (พ.ศ.; default for th) or `gregory` (ค.ศ.; default for en and sv). */
11
+ calendar?: "buddhist" | "gregory" | undefined;
12
+ }
13
+ export interface ThemeOptions {
14
+ /** The project's brand colour, #rgb or #rrggbb. Replaces AURA violet (links, focus ring, selection, info, progress, creative shadow in dark, mesh). */
15
+ brand: string;
16
+ /** Optional signal colour; replaces AURA lime in the accent dot and mesh only (success/ready stay green). */
17
+ signal?: string | undefined;
18
+ /** ink (default): primary buttons stay zinc ink. brand: primary buttons use the brand colour. */
19
+ primary?: "ink" | "brand" | undefined;
20
+ name?: string | undefined;
21
+ }
22
+ export interface ThemeCheck {
23
+ theme: "light" | "dark";
24
+ pair: string;
25
+ ratio: number;
26
+ target: number;
27
+ pass: boolean;
28
+ }
29
+ export interface Theme {
30
+ name: string | null;
31
+ brand: Record<50 | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900, string>;
32
+ signal: Record<50 | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900, string> | null;
33
+ light: Record<string, string>;
34
+ dark: Record<string, string>;
35
+ checks: ThemeCheck[];
36
+ ok: boolean;
37
+ /** CSS overriding the tokens. No selector: the whole page. A selector (".tenant-acme") scopes it. Load after aura.css. */
38
+ css(selector?: string): string;
39
+ }
40
+ /** Options for formatDate: locale/calendar plus a preset or any Intl.DateTimeFormat options. */
41
+ export type FormatDateOptions = DateDisplayOptions & {
42
+ format?: "short" | "long" | "numeric" | Intl.DateTimeFormatOptions | undefined;
43
+ };
44
+ export declare function toISO(d: Date | null | undefined): ISODate | null;
45
+ export declare function fromISO(s: ISODate | null | undefined): Date | null;
46
+ /** Format an ISO date for display: "18 Sept 2026" by default (English, Gregorian — 5.0); `{ locale: 'th' }` gives
47
+ * "18 ก.ย. 2569" (Buddhist era), `{ locale: 'sv' }` "18 sep. 2026". The same function from the package root and from
48
+ * `/server`. In components, `useFormatDate()` follows the AuraProvider's locale instead. */
49
+ export declare function formatDate(iso: ISODate | null | undefined, opts?: FormatDateOptions): string;
50
+ /** 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'. */
51
+ export declare function parseDate(text: string | null | undefined): ISODate | null;
52
+ /** Today as an ISO date in an IANA time zone (e.g. `Asia/Bangkok`), or in the runtime's own zone without one. (4.19) */
53
+ export declare function todayIn(timeZone?: string | null): ISODate;
54
+ /** 1536 → "1.5 KB". */
55
+ export declare function formatBytes(n: number | null | undefined): string;
56
+ /** Parse typed time: 9 · 09 · 930 · 0930 · 9:30 · 9.30 · 09.30 น. · 9:30 pm → "HH:mm" (24-hour) or null. */
57
+ export declare function parseTime(text: string | null | undefined): string | null;
58
+ /** The tone the pill would pick for a status word. */
59
+ declare function toneFor(status: unknown): StatusTone;
60
+ /** Every built-in label. Function entries build the text from their arguments. */
61
+ export interface AuraStrings {
62
+ close: string;
63
+ dismiss: string;
64
+ dismissToast: string;
65
+ showPassword: string;
66
+ filters: string;
67
+ search: string;
68
+ clearFilters: string;
69
+ results: (n: number) => string;
70
+ commandMenu: string;
71
+ commandPlaceholder: string;
72
+ commandHint: string;
73
+ errorSummary: (n: number) => string;
74
+ notifications: string;
75
+ mainNav: string;
76
+ breadcrumb: string;
77
+ navigation: string;
78
+ openNav: string;
79
+ collapseNav: string;
80
+ expandNav: string;
81
+ searching: string;
82
+ noMatches: string;
83
+ clear: (what?: string) => string;
84
+ keepTyping: (total: number) => string;
85
+ sortAsc: string;
86
+ sortDesc: string;
87
+ pin: string;
88
+ unpin: string;
89
+ moveLeft: string;
90
+ moveRight: string;
91
+ hideColumn: string;
92
+ resetColumns: string;
93
+ selectRows: string;
94
+ selectAllRows: string;
95
+ deselectAllRows: string;
96
+ selectAll: string;
97
+ selectRow: (k: React$1.ReactNode) => string;
98
+ selectedCount: (c: number) => string;
99
+ pinned: string;
100
+ columnOptions: (label?: string) => string;
101
+ column: (label?: string) => string;
102
+ columns: string;
103
+ showHideColumns: string;
104
+ empty: string;
105
+ loading: string;
106
+ loadingRows: string;
107
+ range: (a: number | string, b: number | string, total: number) => string;
108
+ page: (p: number, total: number) => string;
109
+ prevPage: string;
110
+ nextPage: string;
111
+ rowCount: (c: number) => string;
112
+ totals: string;
113
+ actions: string;
114
+ optional: string;
115
+ timePlaceholder: string;
116
+ timeInvalid: string;
117
+ timeOutOfRange: (a: number | string, b: number | string) => string;
118
+ dropFiles: string;
119
+ browse: string;
120
+ browseOne: string;
121
+ remove: (n: number | string) => string;
122
+ fileTooBig: (max?: number | string) => string;
123
+ fileWrongType: string;
124
+ tooManyFiles: (n: number | string) => string;
125
+ colorScheme: string;
126
+ increase: string;
127
+ decrease: string;
128
+ stepDone: string;
129
+ stepOf: (i: number, total: number) => string;
130
+ schemeLight: string;
131
+ schemeDark: string;
132
+ schemeSystem: string;
133
+ uploading: string;
134
+ images: string;
135
+ pagination: string;
136
+ pageN: (p: number) => string;
137
+ accepts: (list?: string, max?: number | string) => string;
138
+ }
139
+ export declare const STRINGS: {
140
+ en: AuraStrings;
141
+ th: AuraStrings;
142
+ sv: AuraStrings;
143
+ };
144
+ /** WCAG contrast ratio of two #hex colours. */
145
+ export declare function contrast(a: string, b: string): number;
146
+ /** A 50–900 scale around one colour: same hue, AURA's lightness steps, chroma kept in gamut. */
147
+ declare function scale(hex: string): Theme["brand"];
148
+ /**
149
+ * createTheme({ brand, signal?, primary?: 'ink' | 'brand', name? })
150
+ * → { name, brand: {50…900}, signal: {50…900}|null, light: {token: #hex}, dark: {…}, checks: [{pair, ratio, target, pass}], ok, css(selector?) }
151
+ */
152
+ export declare function createTheme(opts: ThemeOptions): Theme;
153
+ /** `system` follows the operating system and changes with it. */
154
+ export type ColorScheme = "light" | "dark" | "system";
155
+ export interface ColorSchemeOptions {
156
+ /** localStorage key for the choice. Default `aura-color-scheme`. */
157
+ storageKey?: string | undefined;
158
+ /** Used when nothing is saved. Default `system`. */
159
+ defaultScheme?: ColorScheme | undefined;
160
+ }
161
+ /** The script ColorSchemeScript renders, as a string — for frameworks that want it in a raw <head> template. */
162
+ export declare function colorSchemeScript(options?: ColorSchemeOptions): string;
163
+ /** Min-width breakpoints in px, mirroring the aura-bp-* tokens. */
164
+ export declare const breakpoints: {
165
+ sm: 640;
166
+ md: 768;
167
+ lg: 1024;
168
+ xl: 1280;
169
+ };
170
+
171
+ export {
172
+ scale as brandScale,
173
+ toneFor as statusTone,
174
+ };
175
+
176
+ export {};
@@ -1,6 +1,7 @@
1
1
  import * as React$1 from 'react';
2
2
 
3
- export type StatusTone = "neutral" | "progress" | "ready" | "blocked";
3
+ /** `warning` (5.1): needs attention but still works — Warning, Problem, Degraded, At risk. */
4
+ export type StatusTone = "neutral" | "progress" | "ready" | "warning" | "blocked";
4
5
  /** ISO date string, `YYYY-MM-DD` (Gregorian — the era is display only). */
5
6
  export type ISODate = string;
6
7
  export interface DateDisplayOptions {
@@ -120,6 +120,7 @@ function parseTime(text) {
120
120
  var TONE_WORDS = {
121
121
  ready: ["ready", "done", "complete", "completed", "approved", "live", "passed"],
122
122
  progress: ["in progress", "in review", "review", "syncing", "running", "pending"],
123
+ warning: ["warning", "problem", "degraded", "at risk"],
123
124
  blocked: ["blocked", "failed", "error", "rejected", "on hold", "cancelled"]
124
125
  };
125
126
  function toneFor(status) {
@@ -727,6 +728,8 @@ function createTheme(opts) {
727
728
  }
728
729
  if (s) check("light", "ink", "accent-lime (signal)", 4.5, INK, s[200]);
729
730
  function css(selector) {
731
+ if (selector !== void 0 && /[<{};@\r\n]|\/\*|\*\//.test(selector))
732
+ throw new Error('createTheme: "' + selector + '" is not a plain CSS selector');
730
733
  const light = selector ? selector : ':root, [data-theme="light"]';
731
734
  const dark = selector ? selector + ".dark, .dark " + selector + ", " + selector + '[data-theme="dark"], [data-theme="dark"] ' + selector : '.dark, [data-theme="dark"]';
732
735
  const system = selector ? '[data-theme="system"] ' + selector + ", " + selector + '[data-theme="system"]' : '[data-theme="system"]';
@@ -735,7 +738,7 @@ function createTheme(opts) {
735
738
  return " --aura-" + k + ": " + m[k] + ";";
736
739
  }).join("\n") + "\n}";
737
740
  }
738
- return "/* AURA theme" + (o.name ? ' "' + o.name + '"' : "") + ": brand " + o.brand + (o.signal ? ", signal " + o.signal : "") + (o.primary === "brand" ? ", brand primary buttons" : "") + ". Load after aura.css. Generated by createTheme. */\n" + block(light, L) + "\n" + block(dark, D) + "\n@media (prefers-color-scheme: dark) {\n" + block(system, D) + "\n}\n";
741
+ return "/* AURA theme" + (o.name ? ' "' + String(o.name).replace(/[*/<>\\]/g, "") + '"' : "") + ": brand " + o.brand + (o.signal ? ", signal " + o.signal : "") + (o.primary === "brand" ? ", brand primary buttons" : "") + ". Load after aura.css. Generated by createTheme. */\n" + block(light, L) + "\n" + block(dark, D) + "\n@media (prefers-color-scheme: dark) {\n" + block(system, D) + "\n}\n";
739
742
  }
740
743
  return {
741
744
  name: o.name || null,
@@ -754,9 +757,9 @@ function createTheme(opts) {
754
757
  // src/colorSchemeScript.ts
755
758
  var DEFAULT_KEY = "aura-color-scheme";
756
759
  function colorSchemeScript(options) {
757
- const key = JSON.stringify(options && options.storageKey || DEFAULT_KEY);
758
- const fallback = JSON.stringify(options && options.defaultScheme || "system");
759
- 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){}})();`;
760
+ const key = JSON.stringify(options && options.storageKey || DEFAULT_KEY).replace(/</g, "\\u003c");
761
+ const fallback = JSON.stringify(options && options.defaultScheme || "system").replace(/</g, "\\u003c");
762
+ 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 m=window.matchMedia('(prefers-color-scheme: dark)');d.classList.toggle('dark',s==='dark'||(s==='system'&&m.matches));if(m.addEventListener)m.addEventListener('change',function(e){if(d.getAttribute('data-theme')==='system')d.classList.toggle('dark',e.matches)});}catch(e){}})();`;
760
763
  }
761
764
 
762
765
  // src/breakpoints.ts
package/dist/styles.css CHANGED
@@ -212,7 +212,7 @@ a.aura-btn { text-decoration: none; }
212
212
 
213
213
  /* Menu — popover list for column options and the column picker */
214
214
  .aura-menu {
215
- position: fixed; z-index: var(--aura-z-menu); min-width: 200px; padding: var(--aura-space-1);
215
+ position: fixed; z-index: var(--aura-z-menu); min-width: 200px; padding: var(--aura-space-1); overflow-y: auto; overscroll-behavior: contain;
216
216
  background: var(--aura-bg-surface); color: var(--aura-fg-primary);
217
217
  border: 1px solid var(--aura-border-default); border-radius: var(--aura-radius-md);
218
218
  box-shadow: var(--aura-shadow-enterprise);
@@ -334,6 +334,7 @@ a.aura-icon-btn { text-decoration: none; }
334
334
  }
335
335
  .aura-pill--progress { background: var(--aura-status-progress-bg); color: var(--aura-status-progress-fg); }
336
336
  .aura-pill--ready { background: var(--aura-status-ready-bg); color: var(--aura-status-ready-fg); }
337
+ .aura-pill--warning { background: var(--aura-status-warning-bg); color: var(--aura-status-warning-fg); }
337
338
  .aura-pill--blocked { background: var(--aura-status-blocked-bg); color: var(--aura-status-blocked-fg); }
338
339
 
339
340
  /* Icon — Lucide, 24-grid, stroke in currentColor */
@@ -519,6 +520,8 @@ a.aura-icon-btn { text-decoration: none; }
519
520
  font-family: var(--font-sans); font-size: 12px; line-height: 1.5; pointer-events: none;
520
521
  animation: aura-fade-in var(--aura-duration-fast) var(--aura-ease);
521
522
  }
523
+ /* The Tooltip component's own tips can be hovered (WCAG 1.4.13, 5.1.1); rail labels and cell tips stay click-through. */
524
+ .aura-tooltip--hoverable { pointer-events: auto; }
522
525
  @keyframes aura-fade-in { from { opacity: 0; } }
523
526
 
524
527
  /* ---------- Dialog ---------- */
@@ -596,6 +599,9 @@ a.aura-tab { text-decoration: none; }
596
599
  }
597
600
  .aura-nav__header { padding: var(--aura-space-5) var(--aura-space-4) var(--aura-space-4); }
598
601
  .aura-nav__scroll { flex: 1; overflow-y: auto; padding: 0 var(--aura-space-3); }
602
+ /* No header: keep the first item off the top edge (5.0.2). */
603
+ .aura-nav > .aura-nav__scroll:first-child { padding-top: var(--aura-space-3); }
604
+ .aura-nav--borderless { border-right: 0; }
599
605
  .aura-nav__section + .aura-nav__section { margin-top: var(--aura-space-5); }
600
606
  .aura-nav__title { margin: 0 0 var(--aura-space-1); padding: 0 var(--aura-space-3); font-family: var(--font-mono); font-size: 11px; line-height: 20px; color: var(--aura-fg-tertiary); text-transform: uppercase; letter-spacing: 0.04em; }
601
607
  .aura-nav__list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 2px; }
@@ -742,7 +748,7 @@ a.aura-tab { text-decoration: none; }
742
748
  .aura-cal__day.is-outside { color: var(--aura-fg-tertiary); }
743
749
  .aura-cal__day.is-today { box-shadow: inset 0 0 0 1px var(--aura-border-control); font-weight: 600; }
744
750
  .aura-cal__day.is-selected { background: var(--aura-button-primary-bg); color: var(--aura-button-primary-fg); box-shadow: none; }
745
- .aura-cal__day:disabled { opacity: var(--aura-disabled-opacity); cursor: not-allowed; background: transparent; text-decoration: line-through; }
751
+ .aura-cal__day:disabled, .aura-cal__day[aria-disabled='true'] { opacity: var(--aura-disabled-opacity); cursor: not-allowed; background: transparent; text-decoration: line-through; }
746
752
  .aura-cal__day:focus-visible { outline: var(--aura-focus-ring-width) solid var(--aura-focus-ring); outline-offset: 1px; }
747
753
  .aura-cal__grid td.is-in-range { background: var(--aura-bg-selected); }
748
754
  .aura-cal__grid td.is-range-start { background: linear-gradient(to right, transparent 50%, var(--aura-bg-selected) 50%); }
@@ -1419,7 +1425,7 @@ button.aura-stepper__step:hover .aura-stepper__label { text-decoration: underlin
1419
1425
  /* ---------- 4.20: DataTable width queries and cards, one markup ---------- */
1420
1426
  /* Each .aura-table-q is the table's width × 10000 / its threshold (DataTable.tsx, Q), so `(width < 9999.5px)` is true
1421
1427
  * exactly when the table is narrower than stackBelow or a hideBelow width — before hydration, at any width. */
1422
- .aura-table-box { overflow-x: clip; }
1428
+ .aura-table-box { overflow-x: clip; width: 100%; } /* 5.1.1: container-type boxes have no content width; without this a table in a centred flex column collapsed to 0 */
1423
1429
  .aura-table-q { width: calc(100% * var(--aura-q-scale)); container-type: inline-size; }
1424
1430
  .aura-table-q--stack { container-name: aura-stack; }
1425
1431
  .aura-table-q--h1 { container-name: aura-h1; }
@@ -1481,3 +1487,17 @@ button.aura-stepper__step:hover .aura-stepper__label { text-decoration: underlin
1481
1487
  .aura-table__foot { border: 1px solid var(--aura-border-default); border-radius: var(--aura-radius-lg); margin-top: var(--aura-space-2); background: var(--aura-bg-surface); }
1482
1488
  .aura-table__empty { background: var(--aura-bg-surface); border: 1px solid var(--aura-border-default); border-radius: var(--aura-radius-lg); }
1483
1489
  }
1490
+
1491
+ /* ---------- 5.1.1: Windows High Contrast / forced colours ---------- */
1492
+ /* Backgrounds are replaced in forced colours, so controls that show state only by fill get borders and system colours. */
1493
+ @media (forced-colors: active) {
1494
+ .aura-switch { border: 1px solid CanvasText; }
1495
+ .aura-switch__thumb { background: CanvasText; forced-color-adjust: none; }
1496
+ .aura-switch.is-on { background: Highlight; forced-color-adjust: none; }
1497
+ .aura-switch.is-on .aura-switch__thumb { background: HighlightText; }
1498
+ .aura-progress__track, .aura-upload__bar { border: 1px solid CanvasText; }
1499
+ .aura-progress__bar, .aura-upload__bar > span { background: Highlight; forced-color-adjust: none; }
1500
+ .aura-segmented__option.is-selected { outline: 2px solid Highlight; outline-offset: -2px; }
1501
+ .aura-tab { border-bottom-color: Canvas; }
1502
+ .aura-tab.is-active { border-bottom-color: Highlight; }
1503
+ }
@@ -214,7 +214,7 @@ a.aura-btn { text-decoration: none; }
214
214
 
215
215
  /* Menu — popover list for column options and the column picker */
216
216
  .aura-menu {
217
- position: fixed; z-index: var(--aura-z-menu); min-width: 200px; padding: var(--aura-space-1);
217
+ position: fixed; z-index: var(--aura-z-menu); min-width: 200px; padding: var(--aura-space-1); overflow-y: auto; overscroll-behavior: contain;
218
218
  background: var(--aura-bg-surface); color: var(--aura-fg-primary);
219
219
  border: 1px solid var(--aura-border-default); border-radius: var(--aura-radius-md);
220
220
  box-shadow: var(--aura-shadow-enterprise);
@@ -336,6 +336,7 @@ a.aura-icon-btn { text-decoration: none; }
336
336
  }
337
337
  .aura-pill--progress { background: var(--aura-status-progress-bg); color: var(--aura-status-progress-fg); }
338
338
  .aura-pill--ready { background: var(--aura-status-ready-bg); color: var(--aura-status-ready-fg); }
339
+ .aura-pill--warning { background: var(--aura-status-warning-bg); color: var(--aura-status-warning-fg); }
339
340
  .aura-pill--blocked { background: var(--aura-status-blocked-bg); color: var(--aura-status-blocked-fg); }
340
341
 
341
342
  /* Icon — Lucide, 24-grid, stroke in currentColor */
@@ -521,6 +522,8 @@ a.aura-icon-btn { text-decoration: none; }
521
522
  font-family: var(--font-sans); font-size: 12px; line-height: 1.5; pointer-events: none;
522
523
  animation: aura-fade-in var(--aura-duration-fast) var(--aura-ease);
523
524
  }
525
+ /* The Tooltip component's own tips can be hovered (WCAG 1.4.13, 5.1.1); rail labels and cell tips stay click-through. */
526
+ .aura-tooltip--hoverable { pointer-events: auto; }
524
527
  @keyframes aura-fade-in { from { opacity: 0; } }
525
528
 
526
529
  /* ---------- Dialog ---------- */
@@ -598,6 +601,9 @@ a.aura-tab { text-decoration: none; }
598
601
  }
599
602
  .aura-nav__header { padding: var(--aura-space-5) var(--aura-space-4) var(--aura-space-4); }
600
603
  .aura-nav__scroll { flex: 1; overflow-y: auto; padding: 0 var(--aura-space-3); }
604
+ /* No header: keep the first item off the top edge (5.0.2). */
605
+ .aura-nav > .aura-nav__scroll:first-child { padding-top: var(--aura-space-3); }
606
+ .aura-nav--borderless { border-right: 0; }
601
607
  .aura-nav__section + .aura-nav__section { margin-top: var(--aura-space-5); }
602
608
  .aura-nav__title { margin: 0 0 var(--aura-space-1); padding: 0 var(--aura-space-3); font-family: var(--font-mono); font-size: 11px; line-height: 20px; color: var(--aura-fg-tertiary); text-transform: uppercase; letter-spacing: 0.04em; }
603
609
  .aura-nav__list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 2px; }
@@ -744,7 +750,7 @@ a.aura-tab { text-decoration: none; }
744
750
  .aura-cal__day.is-outside { color: var(--aura-fg-tertiary); }
745
751
  .aura-cal__day.is-today { box-shadow: inset 0 0 0 1px var(--aura-border-control); font-weight: 600; }
746
752
  .aura-cal__day.is-selected { background: var(--aura-button-primary-bg); color: var(--aura-button-primary-fg); box-shadow: none; }
747
- .aura-cal__day:disabled { opacity: var(--aura-disabled-opacity); cursor: not-allowed; background: transparent; text-decoration: line-through; }
753
+ .aura-cal__day:disabled, .aura-cal__day[aria-disabled='true'] { opacity: var(--aura-disabled-opacity); cursor: not-allowed; background: transparent; text-decoration: line-through; }
748
754
  .aura-cal__day:focus-visible { outline: var(--aura-focus-ring-width) solid var(--aura-focus-ring); outline-offset: 1px; }
749
755
  .aura-cal__grid td.is-in-range { background: var(--aura-bg-selected); }
750
756
  .aura-cal__grid td.is-range-start { background: linear-gradient(to right, transparent 50%, var(--aura-bg-selected) 50%); }
@@ -1421,7 +1427,7 @@ button.aura-stepper__step:hover .aura-stepper__label { text-decoration: underlin
1421
1427
  /* ---------- 4.20: DataTable width queries and cards, one markup ---------- */
1422
1428
  /* Each .aura-table-q is the table's width × 10000 / its threshold (DataTable.tsx, Q), so `(width < 9999.5px)` is true
1423
1429
  * exactly when the table is narrower than stackBelow or a hideBelow width — before hydration, at any width. */
1424
- .aura-table-box { overflow-x: clip; }
1430
+ .aura-table-box { overflow-x: clip; width: 100%; } /* 5.1.1: container-type boxes have no content width; without this a table in a centred flex column collapsed to 0 */
1425
1431
  .aura-table-q { width: calc(100% * var(--aura-q-scale)); container-type: inline-size; }
1426
1432
  .aura-table-q--stack { container-name: aura-stack; }
1427
1433
  .aura-table-q--h1 { container-name: aura-h1; }
@@ -1484,4 +1490,18 @@ button.aura-stepper__step:hover .aura-stepper__label { text-decoration: underlin
1484
1490
  .aura-table__empty { background: var(--aura-bg-surface); border: 1px solid var(--aura-border-default); border-radius: var(--aura-radius-lg); }
1485
1491
  }
1486
1492
 
1493
+ /* ---------- 5.1.1: Windows High Contrast / forced colours ---------- */
1494
+ /* Backgrounds are replaced in forced colours, so controls that show state only by fill get borders and system colours. */
1495
+ @media (forced-colors: active) {
1496
+ .aura-switch { border: 1px solid CanvasText; }
1497
+ .aura-switch__thumb { background: CanvasText; forced-color-adjust: none; }
1498
+ .aura-switch.is-on { background: Highlight; forced-color-adjust: none; }
1499
+ .aura-switch.is-on .aura-switch__thumb { background: HighlightText; }
1500
+ .aura-progress__track, .aura-upload__bar { border: 1px solid CanvasText; }
1501
+ .aura-progress__bar, .aura-upload__bar > span { background: Highlight; forced-color-adjust: none; }
1502
+ .aura-segmented__option.is-selected { outline: 2px solid Highlight; outline-offset: -2px; }
1503
+ .aura-tab { border-bottom-color: Canvas; }
1504
+ .aura-tab.is-active { border-bottom-color: Highlight; }
1505
+ }
1506
+
1487
1507
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jirawatpyk/aura-react",
3
- "version": "5.0.1",
3
+ "version": "5.1.1",
4
4
  "description": "AURA Design System — React components (Enterprise Standard, Human Creative). Thai-first: Buddhist-era dates, Thai collation.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -9,14 +9,24 @@
9
9
  "types": "./dist/index.d.ts",
10
10
  "exports": {
11
11
  ".": {
12
- "types": "./dist/index.d.ts",
13
- "import": "./dist/esm/index.js",
14
- "require": "./dist/cjs/index.cjs"
12
+ "import": {
13
+ "types": "./dist/index.d.ts",
14
+ "default": "./dist/esm/index.js"
15
+ },
16
+ "require": {
17
+ "types": "./dist/index.d.cts",
18
+ "default": "./dist/cjs/index.cjs"
19
+ }
15
20
  },
16
21
  "./server": {
17
- "types": "./dist/server/index.d.ts",
18
- "import": "./dist/server/index.js",
19
- "require": "./dist/server/index.cjs"
22
+ "import": {
23
+ "types": "./dist/server/index.d.ts",
24
+ "default": "./dist/server/index.js"
25
+ },
26
+ "require": {
27
+ "types": "./dist/server/index.d.cts",
28
+ "default": "./dist/server/index.cjs"
29
+ }
20
30
  },
21
31
  "./styles.css": "./dist/styles.css",
22
32
  "./styles.layer.css": "./dist/styles.layer.css",
@@ -30,7 +40,8 @@
30
40
  "LICENSE"
31
41
  ],
32
42
  "sideEffects": [
33
- "*.css"
43
+ "*.css",
44
+ "./dist/aura.bundle.js"
34
45
  ],
35
46
  "scripts": {
36
47
  "build": "node scripts/build.mjs && node scripts/sync-bundle.mjs",