@jirawatpyk/aura-react 5.2.0 → 5.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -41,7 +41,7 @@ npm i @jirawatpyk/aura-react @jirawatpyk/aura-tokens # React 18 or 19; import
41
41
  npm i @aura/react@npm:@jirawatpyk/aura-react @aura/tokens@npm:@jirawatpyk/aura-tokens
42
42
  ```
43
43
 
44
- React 18.3 and 19 are both tested: the dev dependencies pin 18, and CI switches the whole workspace to 19 (`node scripts/use-react.mjs 19 && npm install`) and runs every suite again — contrast, token lint, SSR, types, build, hydration with 0 warnings, layout before hydration, the three pilot pages and Storybook (axe + behaviour).
44
+ React 18.3 and 19 are both tested: the dev dependencies pin 18, and CI switches the whole workspace to 19 (`node scripts/use-react.mts 19 && npm install`) and runs every suite again — contrast, token lint, SSR, types, build, hydration with 0 warnings, layout before hydration, the three pilot pages and Storybook (axe + behaviour).
45
45
 
46
46
  Public on npmjs; internal projects can use GitHub Packages instead ([repository README](https://github.com/Jirawatpyk/Aura-design#use-it-in-a-project)).
47
47
 
@@ -186,6 +186,20 @@ DataTable with sort and page in the URL (4.17): `onStateChange={({ sort, page })
186
186
  - **Time zone**: `timeZone` on AuraProvider, DatePicker, DateRangePicker and Calendar decides "today" (the marker, `min`/`max="today"`, the first month shown); or pass `today` as an ISO date. `todayIn('Asia/Bangkok')` is exported from the root and `/server`.
187
187
  - **Toasts** queue past three instead of dropping: six in a row all show, in order, three at a time.
188
188
 
189
+ ## 5.4 — types, and TypeScript across the repo
190
+
191
+ - **DataTable** takes rows of your own interface (`rows={orders}` with `interface Order {…}`; readonly arrays too), and `render`, `sortValue`, `getRowHref` and `onRowActivate` can be written with it: `render: (r: Order) => baht(r.amount)` — no cast from `Record<string, any>`.
192
+ - **FormErrorSummary** `errors` accepts a nested object written by hand (`{ address: { street: { message } } }`, arrays for field arrays), not only react-hook-form's `formState.errors`. New type `FormErrorTree`.
193
+ - **Select** `label` is optional when `aria-label` or `aria-labelledby` names the field (a toolbar, a table cell); development builds warn when it has no name at all. Every other field still requires `label`.
194
+ - The example pages (`examples/*`) are TypeScript and type-checked in CI, as are the stories and the repo's scripts; the pilot checks run on Playwright Test instead of Python.
195
+
196
+ ## 5.3 — Select opens AURA's own list
197
+
198
+ - **Select** no longer hands its list to the operating system (a white list in dark mode on Windows, a different look on every OS). The field is a button that opens an AURA list like Combobox: tokens in light and dark, a check on the chosen item, `optgroup` headings, disabled options skipped, type to jump (Thai too), Home/End/PageUp/PageDown, Escape closes the list before a dialog. The same list is used on phones (as in shadcn), not the native picker.
199
+ - **Nothing to change in your code.** A real `<select>` is still underneath: `name` and `required` in a form post, `ref`, `onChange`, react-hook-form `register` / `reset` / `setValue` / `setFocus`, a form's reset button. `options` is now optional, so `<option>` / `<optgroup>` children work on their own. `multiple` or `size > 1` keep the native list box. Before hydration (and with JavaScript off) the field is that `<select>` itself, so it works from the first paint.
200
+ - **Where props go**: `style`, `title`, `data-*`, `aria-label`, `aria-labelledby`, `autoFocus`, `onFocus`, `onKeyDown` and `onClick` go to the button people use; `name`, `form`, `value`, `defaultValue`, `disabled`, `onChange`, `onInput`, `onBlur` stay with the `<select>`. `id` names the button (the label points at it); the `<select>` is `` `${id}-select` ``, and `form.elements.namedItem(name)` still returns it. Read the value in `onChange` / `onBlur` (their `e.target` is the `<select>`); in `onFocus` / `onKeyDown` / `onClick` `e.target` is the button.
201
+ - **Tests**: the label now names the button (`getByRole('combobox', { name: 'Team' })`, then `getByRole('option', { name: 'Mobile' })`). `page.locator('select[name="team"]').selectOption('Mobile')` still works and updates the field; `getByLabel('Team').selectOption()` no longer does, because the label points at the button.
202
+
189
203
  ## 5.2 — the review's smaller items
190
204
 
191
205
  - **DataTable**: the totals row is part of the grid (arrow keys and Ctrl+End reach it); server paging without `totalRows` shows "1–25 of many · Page 1" while pages come back full; a page that no longer exists (a filter left one page) is reported back through `onPageChange` / `onStateChange`; a pinned column that `hideBelow` hides no longer pushes the next pinned column before hydration.
@@ -252,7 +266,7 @@ Tailwind's `dark:` variant keeps working: the `.dark` class on `<html>` is kept
252
266
 
253
267
  ## Refs and forms
254
268
 
255
- Every component forwards `ref` to its real element — fields to the `<input>`/`<select>`/`<textarea>`, buttons to the `<button>`, layouts to their root. react-hook-form: `register` for TextField/Textarea/Select, `Controller` (pass `field.ref`) for Combobox, DatePicker, TimePicker, FileUpload, Checkbox. See `examples/settings`.
269
+ Every component forwards `ref` to its real element — fields to the `<input>`/`<select>`/`<textarea>`, buttons to the `<button>`, layouts to their root. react-hook-form: `register` for TextField/Textarea/Select (Select's ref is its hidden `<select>`; `.focus()` on it moves to the visible button), `Controller` (pass `field.ref`) for Combobox, DatePicker, TimePicker, FileUpload, Checkbox. See `examples/settings`.
256
270
 
257
271
  ## Brand themes
258
272
 
@@ -304,11 +318,13 @@ Every optional prop takes `undefined` (4.16), so apps on `exactOptionalPropertyT
304
318
  ```bash
305
319
  npm run build # dist/ (ESM, CJS, IIFE, CSS, types)
306
320
  npm run test:ssr # server-render every component
307
- npm run typecheck # tsc --strict over src/, then types-test/usage.tsx against the public API
321
+ npm run typecheck # tsc --strict over src/, types-test/ against the published API, and the example pages
308
322
  npm run size # gzip size of what projects import, against size-budgets.json
309
- npm run test:pilots # builds the pilots + 4 brand themes, then 37 behaviour/axe checks at 1440/820/390px (Playwright for Python, axe-core)
323
+ npm run test:pilots # builds the pilots + 4 brand themes, then 44 behaviour/axe checks at 1440/820/390px (Playwright, axe-core)
310
324
  ```
311
325
 
326
+ From the repository root, `npm run typecheck` also checks the Storybook stories (strict) and every build, test and release script. The scripts are TypeScript that Node runs as is (type stripping), so working on the repo needs **Node 22.18 or later**; the published packages still run on Node 18+ (their CLI and checkers stay JavaScript, type-checked through `// @ts-check`).
327
+
312
328
  ## Source
313
329
 
314
330
  `src/` is TypeScript (strict) and JSX, formatted with Prettier (`npm run format`), **one file per component** (`Badge.tsx`, `Tooltip.tsx`, …) so a project that imports one component gets only that component's code. Public prop types live in `src/types.ts` with their docs; each component imports its props from there and `forwardRef`s with them, so the published `dist/index.d.ts` is generated from the code and can't drift from it. The build compiles JSX to `React.createElement` (classic runtime), so the `window.Aura` script needs only `window.React`.