@jirawatpyk/aura-react 4.8.0 → 4.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,15 +1,17 @@
1
1
  import * as React$1 from 'react';
2
2
 
3
+ /** Button look. */
4
+ export type ButtonVariant = "primary" | "secondary" | "creative" | "danger" | "danger-secondary";
3
5
  /** AURA pill button. Enterprise (`primary`, `secondary`) for product UI; `creative` for marketing moments only. */
4
6
  export interface ButtonProps extends React$1.ButtonHTMLAttributes<HTMLButtonElement> {
5
- /** Visual variant. Default `primary`. */
6
- variant?: "primary" | "secondary" | "creative";
7
+ /** Visual variant. Default `primary`. `danger` (filled) and `danger-secondary` (outline) are for irreversible or destructive actions only — typically the confirm button of a `Dialog role="alertdialog"`. */
8
+ variant?: ButtonVariant;
7
9
  /** Label text — short, Title Case English or Thai. */
8
10
  children: React$1.ReactNode;
9
11
  /** Leading icon name (see `IconName`). Hidden while loading. */
10
- icon?: IconName;
12
+ icon?: IconInput;
11
13
  /** Trailing icon name, e.g. `arrow-right` for forward actions. */
12
- iconRight?: IconName;
14
+ iconRight?: IconInput;
13
15
  /** Shows a spinner in place of the leading icon, sets aria-busy and swallows clicks. Keeps the label and width. */
14
16
  loading?: boolean;
15
17
  }
@@ -17,13 +19,13 @@ export interface ButtonProps extends React$1.ButtonHTMLAttributes<HTMLButtonElem
17
19
  export interface ButtonLinkProps extends Omit<React$1.AnchorHTMLAttributes<HTMLAnchorElement>, "children"> {
18
20
  /** Where the link goes. With `href`, Button renders an `<a>` and its ref is the `<a>`. */
19
21
  href: string;
20
- /** Visual variant. Default `primary`. */
21
- variant?: "primary" | "secondary" | "creative";
22
+ /** Visual variant. Default `primary`. `danger` (filled) and `danger-secondary` (outline) are for irreversible or destructive actions only — typically the confirm button of a `Dialog role="alertdialog"`. */
23
+ variant?: ButtonVariant;
22
24
  /** Label text — say where it goes ("View Orders"), not "Click here". */
23
25
  children: React$1.ReactNode;
24
- icon?: IconName;
26
+ icon?: IconInput;
25
27
  /** Trailing icon, e.g. `arrow-right`, or `external-link` with `target="_blank"`. */
26
- iconRight?: IconName;
28
+ iconRight?: IconInput;
27
29
  /** Looks unavailable and can't be followed: no href, `aria-disabled`, out of the Tab order. */
28
30
  disabled?: boolean;
29
31
  /** 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. */
@@ -61,6 +63,8 @@ export interface DataTableColumn {
61
63
  hideBelow?: number | "sm" | "md" | "lg" | "xl";
62
64
  /** Row actions (a DropdownMenu or IconButton). In stacked cards it sits top-right instead of in the field list. Give it an empty label. */
63
65
  actions?: boolean;
66
+ /** `end` right-aligns header and cells (amounts, counts) and uses tabular figures. Default `start`. */
67
+ align?: "start" | "end";
64
68
  }
65
69
  export interface DataTableSort {
66
70
  key: string;
@@ -68,7 +72,7 @@ export interface DataTableSort {
68
72
  }
69
73
  export interface DataTableEmpty {
70
74
  /** Default `inbox`; use `search` for "no matches". */
71
- icon?: IconName;
75
+ icon?: IconInput;
72
76
  /** Default "Nothing here yet". */
73
77
  title?: string;
74
78
  description?: string;
@@ -108,8 +112,20 @@ export interface DataTableProps {
108
112
  /** Adds drag/keyboard resize handles to every column that has a width. */
109
113
  resizable?: boolean;
110
114
  onColumnResize?: (key: string, width: number) => void;
111
- /** Shows skeleton rows and disables sorting, select-all and paging. */
115
+ /** Shows skeleton rows and disables sorting, select-all and paging. With `manual` and rows already shown, the rows stay (dimmed, with a progress bar) while the next page loads. */
112
116
  loading?: boolean;
117
+ /** Server mode: `rows` is already the current page, sorted by the server. The table doesn't sort or slice; it reports
118
+ * sort and page through onSortChange / onPageChange (or getPageHref links). Pair with `totalRows` and `pageSize`. */
119
+ manual?: boolean;
120
+ /** manual: rows across all pages (drives the page count, "1–25 of 312" and aria-rowcount). */
121
+ totalRows?: number;
122
+ /** Makes each row a link: the first column's content renders as the provider's linkComponent (or `<a>`), and a click
123
+ * or Enter anywhere on the row follows it. Ctrl/⌘-click opens a new tab as usual. */
124
+ getRowHref?: (row: Record<string, any>) => string;
125
+ /** Pager arrows become links to these URLs (search-param paging). Without onPageChange the link navigates. */
126
+ getPageHref?: (page: number) => string;
127
+ /** Router link for getRowHref / getPageHref. Default: AuraProvider's linkComponent, else `<a>`. */
128
+ linkComponent?: React$1.ElementType;
113
129
  /** Skeleton row count when there is no pageSize. Default 5. */
114
130
  skeletonRows?: number;
115
131
  /** Called on row click or Enter. */
@@ -133,10 +149,13 @@ export interface DataTableProps {
133
149
  stackBelow?: number;
134
150
  className?: string;
135
151
  }
152
+ /** An AURA icon name, or any icon element (e.g. `<Building />` from lucide-react). AURA sizes it and hides it from screen readers. */
153
+ export type IconInput = IconName | React$1.ReactElement;
136
154
  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";
137
155
  /** Lucide stroke icon drawn inline in currentColor. */
138
156
  export interface IconProps {
139
- name: IconName;
157
+ /** A name from the set, or an icon element of your own (sized and styled the same way). */
158
+ name: IconInput;
140
159
  /** `sm` 16 (default) · `md` 20 · `lg` 24, or a px number. */
141
160
  size?: "sm" | "md" | "lg" | number;
142
161
  /** Accessible name. Omit for decorative icons next to a text label (then aria-hidden). */
@@ -155,12 +174,14 @@ export interface SurfaceProps extends React$1.HTMLAttributes<HTMLElement> {
155
174
  }
156
175
  /** Sets the language of built-in labels (pagination, close buttons, empty states…) and the default date display for everything inside. */
157
176
  export interface AuraProviderProps {
158
- /** Default `en` strings when there is no provider (dates still default to Thai / พ.ศ.). */
159
- locale?: "th" | "en";
160
- /** Default calendar for DatePicker / DateRangePicker / Calendar / formatDate callers that read it. */
177
+ /** Built-in labels and date display. `sv` = Swedish labels, `sv-SE` dates, Monday weeks and the Gregorian calendar. Default `en` strings when there is no provider (dates still default to Thai / พ.ศ.). */
178
+ locale?: "th" | "en" | "sv";
179
+ /** Default calendar for DatePicker / DateRangePicker / Calendar / formatDate callers that read it. Unset: `buddhist` for `th` and `en` (unchanged), `gregory` for `sv`. */
161
180
  calendar?: "buddhist" | "gregory";
162
181
  /** Override individual strings. */
163
182
  strings?: Partial<Record<string, string | ((...args: any[]) => string)>>;
183
+ /** Your router's link (e.g. `Link` from `next/link`), used by every AURA component that renders a link: Button with `href`, SideNav, Breadcrumb, Stat, Pagination, DataTable row links. It gets `href`, `className`, `aria-current`, the children and the ref. A component's own `linkComponent` wins. */
184
+ linkComponent?: React$1.ElementType;
164
185
  children?: React$1.ReactNode;
165
186
  }
166
187
  export type StatusTone = "neutral" | "progress" | "ready" | "blocked";
@@ -191,7 +212,9 @@ export interface CheckboxProps extends Omit<React$1.InputHTMLAttributes<HTMLInpu
191
212
  }
192
213
  /** 32px round button holding one icon. */
193
214
  export interface IconButtonProps extends React$1.ButtonHTMLAttributes<HTMLButtonElement> {
194
- icon: IconName;
215
+ icon: IconInput;
216
+ /** `danger` colours the icon and hover for a destructive action (Delete, Revoke). */
217
+ tone?: "neutral" | "danger";
195
218
  /** Accessible name and tooltip (required). */
196
219
  label: string;
197
220
  /** Icon size. Default `sm` (16). */
@@ -199,7 +222,7 @@ export interface IconButtonProps extends React$1.ButtonHTMLAttributes<HTMLButton
199
222
  }
200
223
  export interface MenuItem {
201
224
  label?: string;
202
- icon?: IconName;
225
+ icon?: IconInput;
203
226
  /** Present = a checkable item (menuitemcheckbox). */
204
227
  checked?: boolean;
205
228
  disabled?: boolean;
@@ -237,7 +260,7 @@ export interface FieldProps {
237
260
  }
238
261
  export interface TextFieldProps extends FieldProps, Omit<React$1.InputHTMLAttributes<HTMLInputElement>, "required"> {
239
262
  /** Leading icon inside the field. */
240
- icon?: IconName;
263
+ icon?: IconInput;
241
264
  /** Trailing unit, e.g. "THB". */
242
265
  suffix?: React$1.ReactNode;
243
266
  }
@@ -252,7 +275,7 @@ export interface SelectProps extends FieldProps, Omit<React$1.SelectHTMLAttribut
252
275
  options: SelectOption[];
253
276
  /** A disabled first option shown in fg-tertiary until something is chosen. */
254
277
  placeholder?: string;
255
- icon?: IconName;
278
+ icon?: IconInput;
256
279
  }
257
280
  export type ChoiceOption = string | {
258
281
  value: string;
@@ -364,7 +387,7 @@ export interface CardProps {
364
387
  export interface TabItem {
365
388
  id: string;
366
389
  label: string;
367
- icon?: IconName;
390
+ icon?: IconInput;
368
391
  count?: number;
369
392
  disabled?: boolean;
370
393
  content?: React$1.ReactNode;
@@ -381,9 +404,15 @@ export interface TabsProps {
381
404
  export interface NavItem {
382
405
  id: string;
383
406
  label: string;
384
- icon?: IconName;
407
+ icon?: IconInput;
385
408
  count?: number;
409
+ /** Anything beside the label, e.g. a status dot or a `Badge`. */
410
+ badge?: React$1.ReactNode;
386
411
  href?: string;
412
+ /** Makes this item a collapsible group of links. The group header is a button, never a link. */
413
+ children?: NavItem[];
414
+ /** Start open. A group also opens by itself when one of its items is the current one. */
415
+ defaultOpen?: boolean;
387
416
  }
388
417
  export interface SideNavProps {
389
418
  sections?: Array<{
@@ -398,6 +427,8 @@ export interface SideNavProps {
398
427
  footer?: React$1.ReactNode;
399
428
  /** Default "Main". */
400
429
  label?: string;
430
+ /** Router link for items with `href`; defaults to the AuraProvider's `linkComponent`, then `<a>`. */
431
+ linkComponent?: React$1.ElementType;
401
432
  className?: string;
402
433
  }
403
434
  export interface BreadcrumbProps {
@@ -435,7 +466,19 @@ export interface ComboboxOption {
435
466
  keywords?: string[];
436
467
  disabled?: boolean;
437
468
  /** Leading icon in the list. */
438
- icon?: IconName;
469
+ icon?: IconInput;
470
+ }
471
+ /** Combobox with `multiple`: pick any number; the picks show as removable chips in the field. */
472
+ export interface ComboboxMultipleProps extends Omit<ComboboxProps, "value" | "defaultValue" | "onChange" | "clearable"> {
473
+ multiple: true;
474
+ /** Selected option values, in the order they were picked (controlled). */
475
+ value?: string[];
476
+ defaultValue?: string[];
477
+ onChange?: (value: string[]) => void;
478
+ /** Clear-all button while anything is selected. Default true. */
479
+ clearable?: boolean;
480
+ /** Most picks allowed; further options are disabled. */
481
+ max?: number;
439
482
  }
440
483
  export interface ComboboxProps extends FieldProps {
441
484
  options: Array<ComboboxOption | string>;
@@ -449,7 +492,7 @@ export interface ComboboxProps extends FieldProps {
449
492
  disabled?: boolean;
450
493
  readOnly?: boolean;
451
494
  /** Leading icon. Default `search`. */
452
- icon?: IconName;
495
+ icon?: IconInput;
453
496
  /** Clear button while a value is selected (Escape clears too). Default true. */
454
497
  clearable?: boolean;
455
498
  /** Server-side search: called with the typed text; the component stops filtering and shows `options` as given. */
@@ -463,12 +506,83 @@ export interface ComboboxProps extends FieldProps {
463
506
  filter?: (option: ComboboxOption, query: string) => boolean;
464
507
  className?: string;
465
508
  }
509
+ /** Number input: thousands separators, +/− buttons, arrow keys, min/max/step, prefix/suffix (฿, %). */
510
+ export interface NumberFieldProps extends FieldProps {
511
+ /** The number (controlled). `null` = empty. */
512
+ value?: number | null;
513
+ defaultValue?: number | null;
514
+ /** Called with the parsed number (or null when emptied) as the person types, and with the clamped value on blur. */
515
+ onChange?: (value: number | null) => void;
516
+ min?: number;
517
+ max?: number;
518
+ /** Arrow keys and buttons move by this. Default 1. PageUp/PageDown move 10×. */
519
+ step?: number;
520
+ /** Decimal places shown and kept. Default: 0 when step is whole, else step's decimals. */
521
+ decimals?: number;
522
+ /** Text before the number, e.g. `฿`. */
523
+ prefix?: React$1.ReactNode;
524
+ /** Text after the number, e.g. `%` or `ชิ้น`. */
525
+ suffix?: React$1.ReactNode;
526
+ /** +/− buttons beside the number. Default true. */
527
+ stepper?: boolean;
528
+ id?: string;
529
+ name?: string;
530
+ placeholder?: string;
531
+ disabled?: boolean;
532
+ readOnly?: boolean;
533
+ className?: string;
534
+ onBlur?: React$1.FocusEventHandler<HTMLInputElement>;
535
+ }
536
+ /** One step of a Stepper. */
537
+ export interface StepItem {
538
+ id: string;
539
+ label: React$1.ReactNode;
540
+ /** Short line under the label, e.g. what the step asks for. */
541
+ description?: React$1.ReactNode;
542
+ }
543
+ /** Progress through a multi-step flow (wizard, checkout, booking). */
544
+ export interface StepperProps {
545
+ steps: StepItem[];
546
+ /** id of the step the person is on. Steps before it are completed. */
547
+ current: string;
548
+ /** Accessible name of the list. Default: none (give one when the page has several). */
549
+ label?: string;
550
+ /** Makes completed steps buttons that go back to them. Upcoming steps never are. */
551
+ onStepClick?: (id: string) => void;
552
+ /** Default `horizontal`. Below `sm` a horizontal stepper shows only the current step ("Step 2 of 4"). */
553
+ orientation?: "horizontal" | "vertical";
554
+ className?: string;
555
+ }
556
+ export interface SegmentedOption {
557
+ value: string;
558
+ label: string;
559
+ icon?: IconInput;
560
+ /** Show only the icon; `label` becomes its accessible name and tooltip. */
561
+ iconOnly?: boolean;
562
+ disabled?: boolean;
563
+ }
564
+ /** A row of 2–5 mutually exclusive choices that apply at once (view, period, unit). A radio group underneath. */
565
+ export interface SegmentedControlProps {
566
+ /** Accessible name of the group, e.g. "View". Required. */
567
+ label: string;
568
+ options: Array<SegmentedOption | string>;
569
+ value?: string;
570
+ defaultValue?: string;
571
+ onChange?: (value: string) => void;
572
+ /** `md` (default, 36px) or `sm` (28px) for toolbars. */
573
+ size?: "sm" | "md";
574
+ /** Stretch across the container, segments equal width. */
575
+ fullWidth?: boolean;
576
+ disabled?: boolean;
577
+ id?: string;
578
+ className?: string;
579
+ }
466
580
  /** ISO date string, `YYYY-MM-DD` (Gregorian — the era is display only). */
467
581
  export type ISODate = string;
468
582
  export interface DateDisplayOptions {
469
- /** `th` (default) or `en`. */
470
- locale?: "th" | "en";
471
- /** `buddhist` (default, พ.ศ.) or `gregory` (ค.ศ.). */
583
+ /** `th` (default), `en` or `sv`. */
584
+ locale?: "th" | "en" | "sv";
585
+ /** `buddhist` (พ.ศ.; default for th and en) or `gregory` (ค.ศ.; default for sv). */
472
586
  calendar?: "buddhist" | "gregory";
473
587
  }
474
588
  export interface CalendarProps extends DateDisplayOptions {
@@ -590,7 +704,7 @@ export interface StatProps {
590
704
  unit?: React$1.ReactNode;
591
705
  change?: StatChange;
592
706
  caption?: React$1.ReactNode;
593
- icon?: IconName;
707
+ icon?: IconInput;
594
708
  /** Skeleton in place of the value. */
595
709
  loading?: boolean;
596
710
  /** Makes the whole card a link or a button (drill-down). */
@@ -657,11 +771,11 @@ export interface BadgeProps extends React$1.HTMLAttributes<HTMLSpanElement> {
657
771
  tone?: Tone;
658
772
  /** soft (default) · solid · outline */
659
773
  variant?: "soft" | "solid" | "outline";
660
- icon?: IconName;
774
+ icon?: IconInput;
661
775
  }
662
776
  export interface TagProps extends Omit<React$1.HTMLAttributes<HTMLElement>, "onClick"> {
663
777
  children: React$1.ReactNode;
664
- icon?: IconName;
778
+ icon?: IconInput;
665
779
  /** Adds a remove button (applied filters, chosen people). */
666
780
  onRemove?: () => void;
667
781
  removeLabel?: string;
@@ -698,7 +812,7 @@ export interface SkeletonProps {
698
812
  export interface EmptyStateProps {
699
813
  title: React$1.ReactNode;
700
814
  description?: React$1.ReactNode;
701
- icon?: IconName;
815
+ icon?: IconInput;
702
816
  /** One or two buttons. */
703
817
  action?: React$1.ReactNode;
704
818
  size?: "sm" | "md";
@@ -724,7 +838,7 @@ export interface AccordionItem {
724
838
  title: React$1.ReactNode;
725
839
  description?: React$1.ReactNode;
726
840
  content: React$1.ReactNode;
727
- icon?: IconName;
841
+ icon?: IconInput;
728
842
  disabled?: boolean;
729
843
  }
730
844
  export interface AccordionProps {
@@ -832,10 +946,16 @@ export declare const Textarea: React$1.ForwardRefExoticComponent<TextareaProps &
832
946
  export declare const Select: React$1.ForwardRefExoticComponent<SelectProps & React$1.RefAttributes<HTMLSelectElement>>;
833
947
  export declare const RadioGroup: React$1.ForwardRefExoticComponent<RadioGroupProps & React$1.RefAttributes<HTMLFieldSetElement>>;
834
948
  export declare const Switch: React$1.ForwardRefExoticComponent<SwitchProps & React$1.RefAttributes<HTMLButtonElement>>;
949
+ /** One value, or with `multiple` any number (chips). Two call signatures so value/onChange are typed for each. */
950
+ export interface ComboboxComponent {
951
+ (props: ComboboxMultipleProps & React$1.RefAttributes<HTMLInputElement>): React$1.ReactElement | null;
952
+ (props: ComboboxProps & React$1.RefAttributes<HTMLInputElement>): React$1.ReactElement | null;
953
+ displayName?: string;
954
+ }
835
955
  /** The Thai-aware default filter: label, description and keywords contain the query. */
836
956
  declare function defaultFilter(option: ComboboxOption, query: string): boolean;
837
- /** Text field that filters a list as you type (ARIA 1.2 combobox). One value. */
838
- export declare const Combobox: React$1.ForwardRefExoticComponent<ComboboxProps & React$1.RefAttributes<HTMLInputElement>>;
957
+ /** Text field that filters a list as you type (ARIA 1.2 combobox). One value, or any number with `multiple`. */
958
+ export declare const Combobox: ComboboxComponent;
839
959
  /** Options for formatDate: locale/calendar plus a preset or any Intl.DateTimeFormat options. */
840
960
  export type FormatDateOptions = DateDisplayOptions & {
841
961
  format?: "short" | "long" | "numeric" | Intl.DateTimeFormatOptions;
@@ -867,6 +987,7 @@ export declare const Drawer: React$1.ForwardRefExoticComponent<DrawerProps & Rea
867
987
  export declare const DataTable: React$1.ForwardRefExoticComponent<DataTableProps & React$1.RefAttributes<HTMLDivElement>>;
868
988
  export declare const Card: React$1.ForwardRefExoticComponent<CardProps & React$1.RefAttributes<HTMLElement>>;
869
989
  export declare const Tabs: React$1.ForwardRefExoticComponent<TabsProps & React$1.RefAttributes<HTMLDivElement>>;
990
+ /** Side navigation: sections of links or buttons, collapsible groups, counts and badges. Arrow keys move between items. */
870
991
  export declare const SideNav: React$1.ForwardRefExoticComponent<SideNavProps & React$1.RefAttributes<HTMLElement>>;
871
992
  export declare const Breadcrumb: React$1.ForwardRefExoticComponent<BreadcrumbProps & React$1.RefAttributes<HTMLElement>>;
872
993
  export declare const Avatar: React$1.ForwardRefExoticComponent<AvatarProps & React$1.RefAttributes<HTMLSpanElement>>;
@@ -953,6 +1074,10 @@ export interface AuraStrings {
953
1074
  fileWrongType: string;
954
1075
  tooManyFiles: (n: number | string) => string;
955
1076
  colorScheme: string;
1077
+ increase: string;
1078
+ decrease: string;
1079
+ stepDone: string;
1080
+ stepOf: (i: number, total: number) => string;
956
1081
  schemeLight: string;
957
1082
  schemeDark: string;
958
1083
  schemeSystem: string;
@@ -965,12 +1090,15 @@ export interface AuraStrings {
965
1090
  export declare const STRINGS: {
966
1091
  en: AuraStrings;
967
1092
  th: AuraStrings;
1093
+ sv: AuraStrings;
968
1094
  };
969
1095
  /** What useAuraLocale returns. `locale` and `calendar` are null outside an AuraProvider. */
970
1096
  export interface AuraLocaleValue {
971
- locale: "th" | "en" | null;
1097
+ locale: "th" | "en" | "sv" | null;
972
1098
  calendar: "buddhist" | "gregory" | null;
973
1099
  strings: AuraStrings;
1100
+ /** The router link set on AuraProvider, if any. */
1101
+ linkComponent?: React$1.ElementType | null;
974
1102
  }
975
1103
  /** Sets the language of built-in labels (and the default date locale) for everything inside. */
976
1104
  export declare function AuraProvider(props: AuraProviderProps): React$1.ReactElement;
@@ -1008,7 +1136,10 @@ export interface ColorSchemeOptions {
1008
1136
  /** The script ColorSchemeScript renders, as a string — for frameworks that want it in a raw <head> template. */
1009
1137
  export declare function colorSchemeScript(options?: ColorSchemeOptions): string;
1010
1138
  /** Put in <head>: applies the saved colour scheme before the page paints. Server-rendering safe. */
1011
- export declare function ColorSchemeScript(props: ColorSchemeOptions): React$1.ReactElement;
1139
+ export declare function ColorSchemeScript(props: ColorSchemeOptions & {
1140
+ /** Nonce for a nonce-based Content-Security-Policy (script-src 'nonce-…'). */
1141
+ nonce?: string;
1142
+ }): React$1.ReactElement;
1012
1143
  /** Current colour scheme and a setter. `resolved` is what is on screen (system resolved to light or dark). */
1013
1144
  export interface ColorSchemeState {
1014
1145
  scheme: ColorScheme;
@@ -1031,6 +1162,12 @@ export declare const EmptyState: React$1.ForwardRefExoticComponent<EmptyStatePro
1031
1162
  export declare const Pagination: React$1.ForwardRefExoticComponent<PaginationProps & React$1.RefAttributes<HTMLElement>>;
1032
1163
  export declare const Accordion: React$1.ForwardRefExoticComponent<AccordionProps & React$1.RefAttributes<HTMLDivElement>>;
1033
1164
  export declare const Popover: React$1.ForwardRefExoticComponent<PopoverProps & React$1.RefAttributes<HTMLDivElement>>;
1165
+ /** Number input with thousands separators, +/− buttons and arrow keys (ARIA spinbutton). */
1166
+ export declare const NumberField: React$1.ForwardRefExoticComponent<NumberFieldProps & React$1.RefAttributes<HTMLInputElement>>;
1167
+ /** Progress through a multi-step flow. Completed steps can link back; the current one has aria-current="step". */
1168
+ export declare const Stepper: React$1.ForwardRefExoticComponent<StepperProps & React$1.RefAttributes<HTMLElement>>;
1169
+ /** A row of mutually exclusive choices that apply at once. A radio group: one Tab stop, arrow keys move and select. */
1170
+ export declare const SegmentedControl: React$1.ForwardRefExoticComponent<SegmentedControlProps & React$1.RefAttributes<HTMLDivElement>>;
1034
1171
 
1035
1172
  export {
1036
1173
  defaultFilter as comboboxFilter,
package/dist/styles.css CHANGED
@@ -43,6 +43,11 @@ a.aura-btn { text-decoration: none; }
43
43
 
44
44
  .aura-btn--secondary { border: 1px solid var(--aura-button-secondary-border); color: var(--aura-fg-primary); }
45
45
  .aura-btn--secondary:hover { background: var(--aura-bg-surface-hover); }
46
+ /* Destructive: filled for the confirm step, outline beside other actions. Loading keeps the colour (busy, not unavailable). */
47
+ .aura-btn--danger { background: var(--aura-button-danger-bg); color: var(--aura-button-danger-fg); }
48
+ .aura-btn--danger:hover { background: var(--aura-button-danger-bg-hover); }
49
+ .aura-btn--danger-secondary { border: 1px solid var(--aura-border-danger); color: var(--aura-fg-danger); background: transparent; }
50
+ .aura-btn--danger-secondary:hover { background: var(--aura-alert-danger-bg); }
46
51
 
47
52
  .aura-btn--creative {
48
53
  border: 2px solid var(--aura-button-creative-border);
@@ -82,6 +87,28 @@ a.aura-btn { text-decoration: none; }
82
87
  .aura-table__row--skeleton:hover { background: var(--aura-bg-surface); }
83
88
  .aura-table__row--skeleton .aura-table__td { display: flex; align-items: center; }
84
89
  .aura-table__row.is-selected { background: var(--aura-bg-selected); }
90
+ /* Right-aligned (numeric) columns */
91
+ .aura-table__th.is-end { padding-right: var(--aura-space-4); }
92
+ .aura-table__th.is-end .aura-table__th-inner { justify-content: flex-end; }
93
+ .aura-table__th.is-end .aura-table__sort { flex-direction: row-reverse; }
94
+ .aura-table__td.is-end { text-align: end; font-variant-numeric: tabular-nums; }
95
+ .aura-table__row--skeleton .aura-table__td.is-end { justify-content: flex-end; }
96
+ /* Row links (getRowHref): the first cell's text is the link; the whole row is the click target */
97
+ .aura-table__row-link { color: inherit; text-decoration: none; }
98
+ .aura-table__row-link:hover, .aura-table__row:hover .aura-table__row-link, .aura-table__card:hover .aura-table__row-link { text-decoration: underline; text-underline-offset: 2px; }
99
+ .aura-table__row-link:focus-visible { outline: var(--aura-focus-ring-width) solid var(--aura-focus-ring); outline-offset: 2px; border-radius: var(--aura-radius-xs); }
100
+ /* Server mode refresh: the previous page stays, inactive, under a progress bar until the next one arrives */
101
+ .aura-table.is-refreshing .aura-table__row, .aura-table.is-refreshing .aura-table__card { opacity: 0.6; pointer-events: none; }
102
+ .aura-table__busy-bar {
103
+ position: absolute; z-index: 6; top: calc(var(--aura-space-12) - 2px); left: 0; right: 0; height: 2px; overflow: hidden;
104
+ border-radius: var(--aura-radius-full); pointer-events: none;
105
+ }
106
+ .aura-table--stacked .aura-table__busy-bar { top: 0; }
107
+ .aura-table__busy-bar::after {
108
+ content: ''; position: absolute; top: 0; bottom: 0; width: 35%; background: var(--aura-fg-accent);
109
+ animation: aura-progress-slide var(--aura-duration-pulse) var(--aura-ease) infinite;
110
+ }
111
+ @media (prefers-reduced-motion: reduce) { .aura-table__busy-bar::after { animation-duration: calc(var(--aura-duration-pulse) * 3); } }
85
112
 
86
113
  /* Cells: text cells stay block so long values end in an ellipsis */
87
114
  .aura-table__td {
@@ -212,11 +239,13 @@ a.aura-btn { text-decoration: none; }
212
239
  cursor: pointer; transition: background var(--aura-duration-fast) var(--aura-ease);
213
240
  }
214
241
  .aura-icon-btn:hover { background: var(--aura-bg-surface-hover); }
242
+ .aura-icon-btn--danger { color: var(--aura-fg-danger); }
243
+ .aura-icon-btn--danger:hover { background: var(--aura-alert-danger-bg); }
215
244
  .aura-icon-btn:disabled { opacity: var(--aura-disabled-opacity); pointer-events: none; }
216
245
  .aura-icon-btn:focus-visible { outline: var(--aura-focus-ring-width) solid var(--aura-focus-ring); outline-offset: var(--aura-focus-ring-offset); }
217
246
 
218
247
  /* Skeleton */
219
- @keyframes aura-pulse { 50% { opacity: 0.45; } }
248
+ @keyframes aura-pulse { 50% { opacity: 0.6; } }
220
249
  .aura-skel {
221
250
  display: block; height: 10px; width: 60%; border-radius: var(--aura-radius-full);
222
251
  background: var(--aura-bg-skeleton); animation: aura-pulse var(--aura-duration-pulse) var(--aura-ease) infinite;
@@ -275,6 +304,9 @@ a.aura-btn { text-decoration: none; }
275
304
 
276
305
  /* Icon — Lucide, 24-grid, stroke in currentColor */
277
306
  .aura-icon { flex: none; display: inline-block; vertical-align: middle; }
307
+ /* A consumer's own icon element (e.g. lucide-react) fills the same box, strokes in currentColor at width 2. */
308
+ .aura-icon--custom { display: inline-flex; align-items: center; justify-content: center; color: inherit; line-height: 0; }
309
+ .aura-icon--custom > svg { width: 100%; height: 100%; stroke-width: var(--aura-icon-stroke, 2); }
278
310
 
279
311
  /* Loading spinner */
280
312
  @keyframes aura-spin { to { transform: rotate(360deg); } }
@@ -543,6 +575,14 @@ a.aura-btn { text-decoration: none; }
543
575
  .aura-nav__item:focus-visible { outline: var(--aura-focus-ring-width) solid var(--aura-focus-ring); outline-offset: -2px; }
544
576
  .aura-nav__label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
545
577
  .aura-nav__count { font-size: 11px; font-variant-numeric: tabular-nums; color: var(--aura-fg-secondary); }
578
+ .aura-nav__badge { display: inline-flex; align-items: center; flex: none; }
579
+ /* Groups: a disclosure button, its items indented one step per level. */
580
+ .aura-nav__item { padding-left: calc(var(--aura-space-3) + var(--aura-nav-depth, 0) * (var(--aura-icon-sm) + var(--aura-space-3))); }
581
+ .aura-nav__item--group.has-active { color: var(--aura-fg-primary); }
582
+ .aura-nav__chevron { color: var(--aura-fg-secondary); transition: transform var(--aura-duration-fast) var(--aura-ease); }
583
+ .aura-nav__chevron.is-open { transform: rotate(180deg); }
584
+ .aura-nav__sub { margin-top: 2px; }
585
+ .aura-nav__sub[hidden] { display: none; }
546
586
  .aura-nav__footer { padding: var(--aura-space-3); border-top: 1px solid var(--aura-border-default); }
547
587
 
548
588
  /* ---------- Breadcrumb ---------- */
@@ -775,7 +815,8 @@ button.aura-stat { font: inherit; width: 100%; cursor: pointer; }
775
815
  .aura-stat__head { display: flex; align-items: center; justify-content: space-between; gap: var(--aura-space-2); }
776
816
  .aura-stat__label { font-size: 13px; font-weight: 500; color: var(--aura-fg-secondary); }
777
817
  .aura-stat__icon { display: inline-flex; color: var(--aura-fg-secondary); }
778
- .aura-stat__value { display: flex; align-items: baseline; gap: var(--aura-space-1); font-size: 28px; line-height: 1.2; font-weight: 600; letter-spacing: -0.01em; font-variant-numeric: tabular-nums; min-height: 34px; }
818
+ .aura-stat__value { display: flex; align-items: baseline; gap: var(--aura-space-1); font-size: 28px; line-height: 1.2; font-weight: 600; letter-spacing: -0.01em; min-height: 34px; }
819
+ .aura-stat__value.is-numeric { font-variant-numeric: tabular-nums; }
779
820
  .aura-stat__unit { font-size: 14px; font-weight: 500; color: var(--aura-fg-secondary); letter-spacing: 0; }
780
821
  .aura-stat__skel { width: 55%; height: 24px; align-self: center; }
781
822
  .aura-stat__foot { display: flex; flex-wrap: wrap; align-items: center; gap: var(--aura-space-1) var(--aura-space-2); font-size: 12px; }
@@ -944,6 +985,107 @@ button.aura-stat { font: inherit; width: 100%; cursor: pointer; }
944
985
  .aura-popover__head + .aura-popover__body { padding-top: var(--aura-space-2); }
945
986
  @media (prefers-reduced-motion: reduce) { .aura-popover { animation: none; } }
946
987
 
988
+ /* ---------- Combobox, multiple: picks as chips in the field ---------- */
989
+ .aura-combo.is-multi { flex-wrap: wrap; align-items: center; gap: var(--aura-space-1); padding: 5px calc(var(--aura-space-2) + 2 * var(--aura-control-sm)) 5px calc(var(--aura-space-3) + var(--aura-icon-sm) + var(--aura-space-2)); }
990
+ .aura-combo.is-multi .aura-input__icon { top: calc(var(--aura-input-height) / 2 - var(--aura-icon-sm) / 2 - 1px); }
991
+ .aura-combo.is-multi .aura-input__control { flex: 1 0 4ch; height: 32px; padding: 0 var(--aura-space-1); }
992
+ /* Wrapped chips grow the field: keep the icon and buttons on the first line. */
993
+ .aura-combo.is-multi .aura-combo__clear, .aura-combo.is-multi .aura-combo__toggle { top: calc((var(--aura-input-height) - 2px - var(--aura-control-sm)) / 2); }
994
+ .aura-combo__chips { display: contents; }
995
+ .aura-combo__chip {
996
+ display: inline-flex; align-items: center; gap: 2px; max-width: 100%; height: 28px; box-sizing: border-box;
997
+ padding: 0 2px 0 var(--aura-space-2); border-radius: var(--aura-radius-full);
998
+ background: var(--aura-bg-selected); color: var(--aura-fg-primary); font-size: 13px; font-weight: 500;
999
+ }
1000
+ .aura-combo__chip-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 24ch; }
1001
+ .aura-combo__chip-remove {
1002
+ display: inline-flex; align-items: center; justify-content: center; width: 24px; height: 24px; padding: 0;
1003
+ border: 0; border-radius: var(--aura-radius-full); background: transparent; color: var(--aura-fg-secondary); cursor: pointer;
1004
+ }
1005
+ .aura-combo__chip-remove:hover { background: var(--aura-bg-surface-hover); color: var(--aura-fg-primary); }
1006
+ .aura-combo__chip-remove .aura-icon { width: 14px; height: 14px; }
1007
+
1008
+ /* ---------- NumberField ---------- */
1009
+ .aura-number .aura-input__control { font-variant-numeric: tabular-nums; }
1010
+ .aura-number__affix { padding-left: var(--aura-space-3); color: var(--aura-fg-secondary); font-size: 14px; white-space: nowrap; }
1011
+ .aura-number__affix + .aura-input__control { padding-left: var(--aura-space-2); }
1012
+ .aura-input__control + .aura-number__affix { padding: 0 var(--aura-space-2) 0 0; }
1013
+ .aura-number__steps { display: flex; align-self: stretch; border-left: 1px solid var(--aura-border-default); }
1014
+ .aura-number__step {
1015
+ display: inline-flex; align-items: center; justify-content: center; width: 36px; padding: 0;
1016
+ border: 0; background: transparent; color: var(--aura-fg-secondary); cursor: pointer;
1017
+ transition: background-color var(--aura-duration-fast) var(--aura-ease), color var(--aura-duration-fast) var(--aura-ease);
1018
+ }
1019
+ .aura-number__step + .aura-number__step { border-left: 1px solid var(--aura-border-default); }
1020
+ .aura-number__step:last-child { border-radius: 0 calc(var(--aura-radius-md) - 1px) calc(var(--aura-radius-md) - 1px) 0; }
1021
+ .aura-number__step:hover:not(:disabled) { background: var(--aura-bg-surface-hover); color: var(--aura-fg-primary); }
1022
+ .aura-number__step:disabled { opacity: var(--aura-disabled-opacity); cursor: default; }
1023
+
1024
+ /* ---------- Stepper ---------- */
1025
+ .aura-stepper { font-family: var(--font-sans); }
1026
+ .aura-stepper__list { display: flex; list-style: none; margin: 0; padding: 0; }
1027
+ .aura-stepper--vertical .aura-stepper__list { flex-direction: column; }
1028
+ .aura-stepper__item { position: relative; flex: 1 1 0; min-width: 0; }
1029
+ .aura-stepper__step {
1030
+ display: flex; align-items: flex-start; gap: var(--aura-space-3); width: 100%; box-sizing: border-box; padding: 0 var(--aura-space-3) 0 0;
1031
+ border: 0; background: none; color: inherit; font: inherit; text-align: left; border-radius: var(--aura-radius-md);
1032
+ }
1033
+ button.aura-stepper__step { cursor: pointer; }
1034
+ button.aura-stepper__step:hover .aura-stepper__label { text-decoration: underline; }
1035
+ .aura-stepper__marker {
1036
+ position: relative; z-index: 1; flex: none; display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; box-sizing: border-box;
1037
+ border-radius: var(--aura-radius-full); border: 1px solid var(--aura-border-control); background: var(--aura-bg-surface);
1038
+ color: var(--aura-fg-secondary); font-size: 13px; font-weight: 600; font-variant-numeric: tabular-nums;
1039
+ }
1040
+ .aura-stepper__marker .aura-icon { width: 16px; height: 16px; }
1041
+ .aura-stepper__item.is-done .aura-stepper__marker { background: var(--aura-button-primary-bg); border-color: var(--aura-button-primary-bg); color: var(--aura-button-primary-fg); }
1042
+ .aura-stepper__item.is-current .aura-stepper__marker { border: 2px solid var(--aura-fg-accent); color: var(--aura-fg-accent); }
1043
+ .aura-stepper__text { display: flex; flex-direction: column; min-width: 0; padding-top: 4px; }
1044
+ .aura-stepper__label { font-size: 13px; font-weight: 500; line-height: 1.4; color: var(--aura-fg-secondary); }
1045
+ .aura-stepper__item.is-current .aura-stepper__label, .aura-stepper__item.is-done .aura-stepper__label { color: var(--aura-fg-primary); }
1046
+ .aura-stepper__item.is-current .aura-stepper__label { font-weight: 600; }
1047
+ .aura-stepper__desc { font-size: 12px; line-height: 1.5; color: var(--aura-fg-secondary); }
1048
+ /* Connector: a line from each marker to the next (labels sit under the markers), or down the left when vertical. */
1049
+ .aura-stepper--horizontal .aura-stepper__item:not(:last-child)::after {
1050
+ content: ""; position: absolute; top: 14px; left: 36px; right: var(--aura-space-2); height: 1px; background: var(--aura-border-control); pointer-events: none;
1051
+ }
1052
+ .aura-stepper--horizontal .aura-stepper__step { flex-direction: column; gap: var(--aura-space-2); }
1053
+ .aura-stepper--horizontal .aura-stepper__text { padding-top: 0; }
1054
+ .aura-stepper--horizontal .aura-stepper__item.is-done::after { background: var(--aura-button-primary-bg); }
1055
+ .aura-stepper--vertical .aura-stepper__item { flex: none; padding-bottom: var(--aura-space-5); }
1056
+ .aura-stepper--vertical .aura-stepper__item:not(:last-child)::after {
1057
+ content: ""; position: absolute; left: 14px; top: 32px; bottom: 4px; width: 1px; background: var(--aura-border-control);
1058
+ }
1059
+ .aura-stepper--vertical .aura-stepper__item.is-done::after { background: var(--aura-button-primary-bg); }
1060
+ .aura-stepper__compact { display: none; margin: var(--aura-space-2) 0 0; font-size: 13px; }
1061
+ .aura-stepper__count { color: var(--aura-fg-secondary); margin-right: var(--aura-space-2); }
1062
+ .aura-stepper__compact-label { font-weight: 600; }
1063
+
1064
+ /* ---------- SegmentedControl ---------- */
1065
+ .aura-segmented {
1066
+ display: inline-flex; gap: 2px; padding: 2px; box-sizing: border-box; max-width: 100%;
1067
+ border: 1px solid var(--aura-border-default); border-radius: var(--aura-radius-full); background: var(--aura-bg-surface-hover);
1068
+ font-family: var(--font-sans);
1069
+ }
1070
+ .aura-segmented:not(.is-full) { width: fit-content; justify-self: start; align-self: flex-start; }
1071
+ .aura-segmented.is-full { display: flex; width: 100%; }
1072
+ .aura-segmented__option {
1073
+ flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; gap: 6px;
1074
+ height: 32px; padding: 0 var(--aura-space-4); box-sizing: border-box;
1075
+ border: 0; border-radius: var(--aura-radius-full); background: transparent; color: var(--aura-fg-secondary);
1076
+ font: inherit; font-size: 13px; font-weight: 500; white-space: nowrap; cursor: pointer;
1077
+ transition: background-color var(--aura-duration-fast) var(--aura-ease), color var(--aura-duration-fast) var(--aura-ease), box-shadow var(--aura-duration-fast) var(--aura-ease);
1078
+ }
1079
+ .aura-segmented.is-full .aura-segmented__option { flex: 1 1 0; min-width: 0; }
1080
+ .aura-segmented__option.is-icon { padding: 0; width: 36px; }
1081
+ .aura-segmented__option:hover:not(:disabled):not(.is-selected) { color: var(--aura-fg-primary); }
1082
+ .aura-segmented__option.is-selected { background: var(--aura-bg-surface); color: var(--aura-fg-primary); box-shadow: var(--aura-shadow-enterprise); }
1083
+ .aura-segmented__option:focus-visible { outline: var(--aura-focus-ring-width) solid var(--aura-focus-ring); outline-offset: 1px; }
1084
+ .aura-segmented__option:disabled { opacity: var(--aura-disabled-opacity); cursor: default; }
1085
+ .aura-segmented--sm .aura-segmented__option { height: 24px; padding: 0 var(--aura-space-3); font-size: 12px; }
1086
+ .aura-segmented--sm .aura-segmented__option.is-icon { width: 28px; padding: 0; }
1087
+ .aura-segmented.is-disabled { opacity: var(--aura-disabled-opacity); }
1088
+
947
1089
  /* A field inside a row Stack takes the remaining width (a search box beside its button). */
948
1090
  .aura-stack > .aura-field { flex: 1 1 auto; min-width: 0; }
949
1091
 
@@ -951,10 +1093,16 @@ button.aura-stat { font: inherit; width: 100%; cursor: pointer; }
951
1093
  @media (pointer: coarse) {
952
1094
  .aura-cal { --aura-cal-cell: 40px; }
953
1095
  .aura-combo__option { min-height: 44px; }
1096
+ .aura-segmented__option, .aura-segmented--sm .aura-segmented__option { height: 40px; }
1097
+ .aura-number__step { width: 44px; }
954
1098
  }
955
1099
 
956
1100
  /* ---------- Small screens (< 640px) ---------- */
957
1101
  @media (max-width: 639.98px) {
1102
+ /* Horizontal stepper on phones: markers only (names kept for screen readers), the current step named underneath. */
1103
+ .aura-stepper--horizontal .aura-stepper__text { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; padding: 0; }
1104
+ .aura-stepper--horizontal .aura-stepper__item:not(:last-child)::after { right: 8px; }
1105
+ .aura-stepper--horizontal .aura-stepper__compact { display: block; }
958
1106
  .aura-dialog-layer:not(.aura-drawer-layer) { align-items: flex-end; padding: 0; }
959
1107
  .aura-dialog { max-width: none !important; max-height: 92vh; border-radius: var(--aura-radius-2xl) var(--aura-radius-2xl) 0 0; border-bottom: 0;
960
1108
  padding-bottom: calc(var(--aura-space-6) + env(safe-area-inset-bottom)); animation-name: aura-sheet-in; }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jirawatpyk/aura-react",
3
- "version": "4.8.0",
3
+ "version": "4.10.0",
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",