@jirawatpyk/aura-react 4.12.0 → 4.13.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 +15 -1
- package/dist/aura.bundle.js +938 -433
- package/dist/cjs/index.cjs +937 -432
- package/dist/esm/Command.js +213 -0
- package/dist/esm/FilterBar.js +112 -0
- package/dist/esm/FormErrorSummary.js +76 -0
- package/dist/esm/PasswordField.js +38 -0
- package/dist/esm/Toaster.js +60 -14
- package/dist/esm/index.js +8 -0
- package/dist/esm/locale.js +39 -0
- package/dist/index.d.ts +111 -1
- package/dist/styles.css +100 -0
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -268,6 +268,96 @@ export interface TextFieldProps extends FieldProps, Omit<React$1.InputHTMLAttrib
|
|
|
268
268
|
/** Trailing unit, e.g. "THB". */
|
|
269
269
|
suffix?: React$1.ReactNode;
|
|
270
270
|
}
|
|
271
|
+
/** A password input with a show/hide button. All TextField props; `ref` reaches the input (react-hook-form `register`). */
|
|
272
|
+
export interface PasswordFieldProps extends Omit<TextFieldProps, "type" | "suffix"> {
|
|
273
|
+
/** Set false to hide the show/hide button. Default true. */
|
|
274
|
+
toggle?: boolean;
|
|
275
|
+
}
|
|
276
|
+
/** One entry of a FormErrorSummary: the field's `id` (or `name`) and what to fix. */
|
|
277
|
+
export interface FormErrorItem {
|
|
278
|
+
field: string;
|
|
279
|
+
message: React$1.ReactNode;
|
|
280
|
+
}
|
|
281
|
+
/** The list of problems at the top of a form after a failed submit; each links to its field (GOV.UK pattern). */
|
|
282
|
+
export interface FormErrorSummaryProps {
|
|
283
|
+
/** A list, or react-hook-form's `formState.errors` as is (`{ name: { message } }`). Empty → renders nothing. */
|
|
284
|
+
errors: FormErrorItem[] | Record<string, {
|
|
285
|
+
message?: React$1.ReactNode;
|
|
286
|
+
} | undefined>;
|
|
287
|
+
/** Default "Fix N fields to continue" in the provider's language. */
|
|
288
|
+
title?: React$1.ReactNode;
|
|
289
|
+
/** Called with the field when a link is followed, e.g. react-hook-form's `setFocus`. Default: focus the element whose id (or name) is the field. */
|
|
290
|
+
onSelect?: (field: string) => void;
|
|
291
|
+
/** Change it on every submit (e.g. `formState.submitCount`) to move focus to the summary again. It also takes focus when errors first appear. */
|
|
292
|
+
focusKey?: unknown;
|
|
293
|
+
className?: string;
|
|
294
|
+
id?: string;
|
|
295
|
+
}
|
|
296
|
+
/** An applied filter, shown as a removable chip. */
|
|
297
|
+
export interface ActiveFilter {
|
|
298
|
+
id: string;
|
|
299
|
+
label: React$1.ReactNode;
|
|
300
|
+
onRemove: () => void;
|
|
301
|
+
}
|
|
302
|
+
/** The row above a table: search, filter controls, applied-filter chips, result count and actions. Wraps below md. */
|
|
303
|
+
export interface FilterBarProps {
|
|
304
|
+
/** Search text (controlled). Omit `onSearchChange` to hide the search field. */
|
|
305
|
+
search?: string;
|
|
306
|
+
/** Called after typing pauses (`searchDelay`), and at once on Enter or clear — ready to write to the URL. */
|
|
307
|
+
onSearchChange?: (value: string) => void;
|
|
308
|
+
/** ms to wait after the last keystroke. Default 300. */
|
|
309
|
+
searchDelay?: number;
|
|
310
|
+
searchLabel?: string;
|
|
311
|
+
searchPlaceholder?: string;
|
|
312
|
+
/** Filter controls beside the search: Select, SegmentedControl, a Popover of options… */
|
|
313
|
+
children?: React$1.ReactNode;
|
|
314
|
+
/** Applied filters as chips, each with its own remove button. */
|
|
315
|
+
filters?: ActiveFilter[];
|
|
316
|
+
/** Adds "Clear all" while any filter or search is set. */
|
|
317
|
+
onClearAll?: () => void;
|
|
318
|
+
/** A number ("312 results", announced politely) or your own node. */
|
|
319
|
+
resultCount?: number | React$1.ReactNode;
|
|
320
|
+
/** Trailing slot: export, a New button… */
|
|
321
|
+
actions?: React$1.ReactNode;
|
|
322
|
+
/** Accessible name of the region. Default "Filters". */
|
|
323
|
+
label?: string;
|
|
324
|
+
className?: string;
|
|
325
|
+
}
|
|
326
|
+
/** One command in the palette. */
|
|
327
|
+
export interface CommandItem {
|
|
328
|
+
id: string;
|
|
329
|
+
/** Text shown and searched. */
|
|
330
|
+
label: string;
|
|
331
|
+
/** Items with the same group are listed together under its heading, in first-seen order. */
|
|
332
|
+
group?: string;
|
|
333
|
+
icon?: IconInput;
|
|
334
|
+
description?: string;
|
|
335
|
+
/** Extra words that find it ("invoice" → Billing). */
|
|
336
|
+
keywords?: string[];
|
|
337
|
+
/** A shortcut shown at the right, e.g. "G I". Display only. */
|
|
338
|
+
shortcut?: string;
|
|
339
|
+
disabled?: boolean;
|
|
340
|
+
/** Runs when chosen (Enter or click); the palette then closes. */
|
|
341
|
+
onSelect?: () => void;
|
|
342
|
+
}
|
|
343
|
+
/** A command palette: a modal search over commands and pages, grouped, fully keyboard-driven. */
|
|
344
|
+
export interface CommandProps {
|
|
345
|
+
open: boolean;
|
|
346
|
+
onOpenChange: (open: boolean) => void;
|
|
347
|
+
items: CommandItem[];
|
|
348
|
+
/** Also called with the chosen item (after its own onSelect). */
|
|
349
|
+
onSelect?: (item: CommandItem) => void;
|
|
350
|
+
/** Accessible name. Default "Command menu". */
|
|
351
|
+
label?: string;
|
|
352
|
+
placeholder?: string;
|
|
353
|
+
/** Default "No matches". */
|
|
354
|
+
emptyText?: string;
|
|
355
|
+
/** ⌘K / Ctrl+K toggles the palette from anywhere on the page. Default true. */
|
|
356
|
+
hotkey?: boolean;
|
|
357
|
+
/** Replace the Thai-aware default filter. */
|
|
358
|
+
filter?: (item: CommandItem, query: string) => boolean;
|
|
359
|
+
className?: string;
|
|
360
|
+
}
|
|
271
361
|
export interface TextareaProps extends FieldProps, Omit<React$1.TextareaHTMLAttributes<HTMLTextAreaElement>, "required"> {
|
|
272
362
|
}
|
|
273
363
|
export type SelectOption = string | {
|
|
@@ -332,9 +422,11 @@ export interface ToastOptions {
|
|
|
332
422
|
};
|
|
333
423
|
/** ms before it closes itself. Default 5000; Infinity keeps it until dismissed. */
|
|
334
424
|
duration?: number;
|
|
335
|
-
/** Reuse an id to replace a toast in place. */
|
|
425
|
+
/** Reuse an id to replace a toast in place (same position, timer restarts) — never a second toast. */
|
|
336
426
|
id?: string;
|
|
337
427
|
}
|
|
428
|
+
/** Options for the shorthands (`toast.success(title, opts)` …): everything but the title and tone. */
|
|
429
|
+
export type ToastShorthandOptions = Omit<ToastOptions, "title" | "tone">;
|
|
338
430
|
export interface TooltipProps {
|
|
339
431
|
content: React$1.ReactNode;
|
|
340
432
|
/** One focusable element. */
|
|
@@ -979,6 +1071,11 @@ export declare const Alert: React$1.ForwardRefExoticComponent<AlertProps & React
|
|
|
979
1071
|
/** Show a toast; returns its id. Needs `<Toaster />` mounted once. */
|
|
980
1072
|
export declare function toast(opts: ToastOptions | string): string;
|
|
981
1073
|
export declare namespace toast {
|
|
1074
|
+
var success: (title: string, opts?: ToastShorthandOptions) => string;
|
|
1075
|
+
var error: (title: string, opts?: ToastShorthandOptions) => string;
|
|
1076
|
+
var warning: (title: string, opts?: ToastShorthandOptions) => string;
|
|
1077
|
+
var info: (title: string, opts?: ToastShorthandOptions) => string;
|
|
1078
|
+
var loading: (title: string, opts?: ToastShorthandOptions) => string;
|
|
982
1079
|
var dismiss: (id: string) => void;
|
|
983
1080
|
}
|
|
984
1081
|
export interface ToasterProps {
|
|
@@ -986,6 +1083,10 @@ export interface ToasterProps {
|
|
|
986
1083
|
position?: "bottom" | "top";
|
|
987
1084
|
}
|
|
988
1085
|
export declare function Toaster(props: ToasterProps): React$1.ReactElement | null;
|
|
1086
|
+
export declare const PasswordField: React$1.ForwardRefExoticComponent<PasswordFieldProps & React$1.RefAttributes<HTMLInputElement>>;
|
|
1087
|
+
export declare const FormErrorSummary: React$1.ForwardRefExoticComponent<FormErrorSummaryProps & React$1.RefAttributes<HTMLDivElement>>;
|
|
1088
|
+
export declare const FilterBar: React$1.ForwardRefExoticComponent<FilterBarProps & React$1.RefAttributes<HTMLDivElement>>;
|
|
1089
|
+
export declare function Command(props: CommandProps): React$1.ReactElement | null;
|
|
989
1090
|
export declare const Tooltip: React$1.ForwardRefExoticComponent<TooltipProps & React$1.RefAttributes<HTMLSpanElement>>;
|
|
990
1091
|
export declare const Dialog: React$1.ForwardRefExoticComponent<DialogProps & React$1.RefAttributes<HTMLDivElement>>;
|
|
991
1092
|
/** Side panel over the page: record detail, filters, mobile navigation. Modal (focus trap, scroll lock, focus restore). */
|
|
@@ -1032,6 +1133,15 @@ export interface AuraStrings {
|
|
|
1032
1133
|
close: string;
|
|
1033
1134
|
dismiss: string;
|
|
1034
1135
|
dismissToast: string;
|
|
1136
|
+
showPassword: string;
|
|
1137
|
+
filters: string;
|
|
1138
|
+
search: string;
|
|
1139
|
+
clearFilters: string;
|
|
1140
|
+
results: (n: number) => string;
|
|
1141
|
+
commandMenu: string;
|
|
1142
|
+
commandPlaceholder: string;
|
|
1143
|
+
commandHint: string;
|
|
1144
|
+
errorSummary: (n: number) => string;
|
|
1035
1145
|
notifications: string;
|
|
1036
1146
|
mainNav: string;
|
|
1037
1147
|
breadcrumb: string;
|
package/dist/styles.css
CHANGED
|
@@ -1141,3 +1141,103 @@ button.aura-stepper__step:hover .aura-stepper__label { text-decoration: underlin
|
|
|
1141
1141
|
.aura-radio-group__list { gap: 0; }
|
|
1142
1142
|
.aura-radio-group__list.is-horizontal { gap: 0 var(--aura-space-6); }
|
|
1143
1143
|
}
|
|
1144
|
+
|
|
1145
|
+
/* PasswordField: the show/hide IconButton sits in the suffix slot, 6px from the edge */
|
|
1146
|
+
.aura-password .aura-input__suffix { padding-right: 6px; display: flex; align-items: center; }
|
|
1147
|
+
|
|
1148
|
+
/* FormErrorSummary: a danger alert whose items link to their fields */
|
|
1149
|
+
.aura-error-summary:focus-visible, .aura-error-summary:focus { outline: var(--aura-focus-ring-width) solid var(--aura-focus-ring); outline-offset: var(--aura-focus-ring-offset); }
|
|
1150
|
+
.aura-error-summary h2.aura-alert__title { font-family: inherit; }
|
|
1151
|
+
.aura-error-summary__list { margin: var(--aura-space-2) 0 0; padding-left: var(--aura-space-5); display: grid; gap: var(--aura-space-1); font-size: 14px; line-height: 20px; }
|
|
1152
|
+
.aura-error-summary__list a { color: var(--aura-alert-danger-fg); text-decoration: underline; text-underline-offset: 2px; font-weight: 500; }
|
|
1153
|
+
.aura-error-summary__list a:hover { text-decoration-thickness: 2px; }
|
|
1154
|
+
.aura-error-summary__list a:focus-visible { outline: var(--aura-focus-ring-width) solid var(--aura-focus-ring); outline-offset: 2px; border-radius: var(--aura-radius-xs); }
|
|
1155
|
+
|
|
1156
|
+
/* aura-prose: sanitised rich text (editor output, e-mail previews). Styles exactly p, h1–h4, ul/ol/li, blockquote,
|
|
1157
|
+
* hr, a, strong, em, u with AURA type and spacing, in both themes. */
|
|
1158
|
+
.aura-prose { font-family: var(--font-sans); font-size: 14px; line-height: 1.7; color: var(--aura-fg-primary); overflow-wrap: anywhere; }
|
|
1159
|
+
.aura-prose > :first-child { margin-top: 0; }
|
|
1160
|
+
.aura-prose > :last-child { margin-bottom: 0; }
|
|
1161
|
+
.aura-prose p { margin: 0 0 var(--aura-space-4); }
|
|
1162
|
+
.aura-prose h1, .aura-prose h2, .aura-prose h3, .aura-prose h4 { color: var(--aura-fg-primary); margin: var(--aura-space-8) 0 var(--aura-space-3); }
|
|
1163
|
+
.aura-prose h1 { font-family: var(--font-display); font-weight: 600; font-size: 30px; line-height: 1.2; letter-spacing: -0.01em; }
|
|
1164
|
+
.aura-prose h2 { font-weight: 600; font-size: 22px; line-height: 1.3; }
|
|
1165
|
+
.aura-prose h3 { font-weight: 600; font-size: 17px; line-height: 1.45; }
|
|
1166
|
+
.aura-prose h4 { font-weight: 600; font-size: 15px; line-height: 1.5; }
|
|
1167
|
+
.aura-prose ul, .aura-prose ol { margin: 0 0 var(--aura-space-4); padding-left: var(--aura-space-6); }
|
|
1168
|
+
.aura-prose li { margin: var(--aura-space-1) 0; }
|
|
1169
|
+
.aura-prose li > ul, .aura-prose li > ol { margin: var(--aura-space-1) 0 0; }
|
|
1170
|
+
.aura-prose ul { list-style: disc; }
|
|
1171
|
+
.aura-prose ol { list-style: decimal; }
|
|
1172
|
+
.aura-prose li::marker { color: var(--aura-fg-secondary); }
|
|
1173
|
+
.aura-prose blockquote { margin: 0 0 var(--aura-space-4); padding: var(--aura-space-1) 0 var(--aura-space-1) var(--aura-space-4); border-left: 3px solid var(--aura-border-control); color: var(--aura-fg-secondary); }
|
|
1174
|
+
.aura-prose hr { margin: var(--aura-space-8) 0; border: 0; border-top: 1px solid var(--aura-border-default); }
|
|
1175
|
+
.aura-prose a { color: var(--aura-fg-accent); text-decoration: underline; text-underline-offset: 2px; }
|
|
1176
|
+
.aura-prose a:hover { text-decoration-thickness: 2px; }
|
|
1177
|
+
.aura-prose a:focus-visible { outline: var(--aura-focus-ring-width) solid var(--aura-focus-ring); outline-offset: 2px; border-radius: var(--aura-radius-xs); }
|
|
1178
|
+
.aura-prose strong { font-weight: 600; }
|
|
1179
|
+
.aura-prose em { font-style: italic; }
|
|
1180
|
+
.aura-prose u { text-decoration: underline; text-underline-offset: 2px; }
|
|
1181
|
+
|
|
1182
|
+
/* FilterBar: search + controls + count + actions on one row, applied-filter chips below; wraps on small screens */
|
|
1183
|
+
.aura-filterbar { display: flex; flex-direction: column; gap: var(--aura-space-3); font-family: var(--font-sans); }
|
|
1184
|
+
.aura-filterbar__row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--aura-space-3); }
|
|
1185
|
+
.aura-filterbar__search { flex: 1 1 240px; max-width: 360px; width: auto; }
|
|
1186
|
+
.aura-filterbar__search .aura-input__control::-webkit-search-cancel-button { display: none; }
|
|
1187
|
+
.aura-filterbar__clear-search { margin-right: 6px; }
|
|
1188
|
+
.aura-filterbar__controls { display: flex; flex-wrap: wrap; align-items: center; gap: var(--aura-space-3); }
|
|
1189
|
+
.aura-filterbar__spacer { flex: 1 1 0; }
|
|
1190
|
+
.aura-filterbar__count { font-size: 13px; color: var(--aura-fg-secondary); font-variant-numeric: tabular-nums; white-space: nowrap; }
|
|
1191
|
+
.aura-filterbar__actions { display: flex; align-items: center; gap: var(--aura-space-2); }
|
|
1192
|
+
.aura-filterbar__chips { display: flex; flex-wrap: wrap; align-items: center; gap: var(--aura-space-2); }
|
|
1193
|
+
.aura-filterbar__clear {
|
|
1194
|
+
border: 0; background: transparent; padding: 4px var(--aura-space-2); border-radius: var(--aura-radius-sm);
|
|
1195
|
+
font: inherit; font-size: 13px; font-weight: 500; color: var(--aura-fg-accent); cursor: pointer; text-decoration: underline; text-underline-offset: 2px;
|
|
1196
|
+
}
|
|
1197
|
+
.aura-filterbar__clear:hover { background: var(--aura-bg-surface-hover); }
|
|
1198
|
+
.aura-filterbar__clear:focus-visible { outline: var(--aura-focus-ring-width) solid var(--aura-focus-ring); outline-offset: var(--aura-focus-ring-offset); }
|
|
1199
|
+
@media (max-width: 767.98px) {
|
|
1200
|
+
.aura-filterbar__search { flex-basis: 100%; max-width: none; }
|
|
1201
|
+
.aura-filterbar__spacer { display: none; }
|
|
1202
|
+
}
|
|
1203
|
+
|
|
1204
|
+
/* Command palette: a search field over a grouped list, above everything else (it can open from a Dialog) */
|
|
1205
|
+
.aura-dialog-layer.aura-command-layer { z-index: var(--aura-z-menu); align-items: flex-start; padding: 12vh var(--aura-space-4) var(--aura-space-4); }
|
|
1206
|
+
.aura-command {
|
|
1207
|
+
position: relative; box-sizing: border-box; width: 100%; max-width: 640px; max-height: 70vh; display: flex; flex-direction: column; overflow: hidden;
|
|
1208
|
+
background: var(--aura-bg-surface); color: var(--aura-fg-primary); font-family: var(--font-sans);
|
|
1209
|
+
border: 1px solid var(--aura-border-default); border-radius: var(--aura-radius-xl); box-shadow: var(--aura-shadow-overlay);
|
|
1210
|
+
animation: aura-dialog-in var(--aura-duration-base) var(--aura-ease);
|
|
1211
|
+
}
|
|
1212
|
+
.aura-command:focus { outline: none; }
|
|
1213
|
+
.aura-command__search { display: flex; align-items: center; gap: var(--aura-space-3); padding: 0 var(--aura-space-4); border-bottom: 1px solid var(--aura-border-default); }
|
|
1214
|
+
.aura-command__search-icon { color: var(--aura-fg-secondary); }
|
|
1215
|
+
.aura-command__input {
|
|
1216
|
+
flex: 1; min-width: 0; height: 52px; border: 0; background: transparent; color: inherit; outline: none;
|
|
1217
|
+
font: inherit; font-size: max(16px, var(--aura-input-font-size));
|
|
1218
|
+
}
|
|
1219
|
+
.aura-command__input::placeholder { color: var(--aura-fg-tertiary); opacity: 1; }
|
|
1220
|
+
.aura-command__list { flex: 1 1 auto; overflow-y: auto; overscroll-behavior: contain; padding: var(--aura-space-2); }
|
|
1221
|
+
.aura-command__group + .aura-command__group { margin-top: var(--aura-space-2); }
|
|
1222
|
+
.aura-command__heading { padding: var(--aura-space-2) var(--aura-space-2) var(--aura-space-1); font-family: var(--font-mono); font-size: 11px; text-transform: uppercase; letter-spacing: 0.04em; color: var(--aura-fg-secondary); }
|
|
1223
|
+
.aura-command__item { display: flex; align-items: center; gap: var(--aura-space-3); min-height: 40px; padding: 6px var(--aura-space-2); border-radius: var(--aura-radius-sm); cursor: pointer; font-size: 14px; }
|
|
1224
|
+
.aura-command__item > .aura-icon { color: var(--aura-fg-secondary); }
|
|
1225
|
+
.aura-command__item.is-active { background: var(--aura-bg-surface-hover); outline: var(--aura-focus-ring-width) solid var(--aura-focus-ring); outline-offset: calc(-1 * var(--aura-focus-ring-width)); }
|
|
1226
|
+
.aura-command__item.is-disabled { opacity: var(--aura-disabled-opacity); cursor: default; }
|
|
1227
|
+
.aura-command__text { flex: 1; min-width: 0; display: flex; flex-direction: column; }
|
|
1228
|
+
.aura-command__label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
1229
|
+
.aura-command__desc { font-size: 12px; line-height: 1.5; color: var(--aura-fg-secondary); }
|
|
1230
|
+
.aura-command__kbd {
|
|
1231
|
+
flex: none; padding: 2px 6px; border: 1px solid var(--aura-border-default); border-radius: var(--aura-radius-xs);
|
|
1232
|
+
font-family: var(--font-mono); font-size: 11px; line-height: 16px; color: var(--aura-fg-secondary); background: var(--aura-bg-canvas);
|
|
1233
|
+
}
|
|
1234
|
+
.aura-command__empty { margin: 0; padding: var(--aura-space-6) var(--aura-space-2); text-align: center; font-size: 14px; color: var(--aura-fg-secondary); }
|
|
1235
|
+
.aura-command__foot { display: flex; justify-content: space-between; gap: var(--aura-space-3); padding: var(--aura-space-2) var(--aura-space-4); border-top: 1px solid var(--aura-border-default); font-size: 12px; color: var(--aura-fg-secondary); }
|
|
1236
|
+
@media (max-width: 639.98px) {
|
|
1237
|
+
.aura-dialog-layer.aura-command-layer { align-items: flex-start; padding: var(--aura-space-4); }
|
|
1238
|
+
.aura-command { max-height: 80vh; }
|
|
1239
|
+
.aura-command__foot { display: none; }
|
|
1240
|
+
.aura-command__item { min-height: 44px; }
|
|
1241
|
+
}
|
|
1242
|
+
@media (prefers-reduced-motion: reduce) { .aura-command { animation: none; } }
|
|
1243
|
+
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jirawatpyk/aura-react",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.13.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",
|