@astryxdesign/core 0.7.3-canary.f94e962 → 0.7.3
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/CHANGELOG.md +88 -0
- package/dist/BottomSheet/BottomSheet.d.ts.map +1 -1
- package/dist/BottomSheet/BottomSheet.js +8 -4
- package/dist/BottomSheet/BottomSheetSwitcher.d.ts.map +1 -1
- package/dist/BottomSheet/BottomSheetSwitcher.js +7 -0
- package/dist/Button/Button.d.ts.map +1 -1
- package/dist/Button/Button.js +15 -2
- package/dist/Calendar/Calendar.js +3 -2
- package/dist/Chat/ChatComposer.d.ts.map +1 -1
- package/dist/Chat/ChatComposer.js +25 -2
- package/dist/Chat/ChatSystemMessage.d.ts +4 -0
- package/dist/Chat/ChatSystemMessage.d.ts.map +1 -1
- package/dist/Chat/ChatSystemMessage.js +4 -2
- package/dist/CodeBlock/CodeBlock.d.ts.map +1 -1
- package/dist/CodeBlock/CodeBlock.js +11 -1
- package/dist/DateRangeInput/DateRangeInput.d.ts +5 -5
- package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
- package/dist/DateRangeInput/DateRangeInput.js +27 -18
- package/dist/DateTimeInput/DateTimeInput.d.ts +5 -5
- package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
- package/dist/DateTimeInput/DateTimeInput.js +25 -27
- package/dist/DateTimeInput/NativeDateSegment.d.ts +3 -2
- package/dist/DateTimeInput/NativeDateSegment.d.ts.map +1 -1
- package/dist/DateTimeInput/NativeDateSegment.js +5 -5
- package/dist/DateTimeInput/NativeTimeSegment.d.ts +3 -2
- package/dist/DateTimeInput/NativeTimeSegment.d.ts.map +1 -1
- package/dist/DateTimeInput/NativeTimeSegment.js +5 -5
- package/dist/DateTimeInput/TouchDateTimeField.d.ts.map +1 -1
- package/dist/DateTimeInput/TouchDateTimeField.js +12 -9
- package/dist/Dialog/Dialog.d.ts.map +1 -1
- package/dist/Dialog/Dialog.js +9 -4
- package/dist/DropdownMenu/DropdownMenuRadioGroup.d.ts +9 -5
- package/dist/DropdownMenu/DropdownMenuRadioGroup.d.ts.map +1 -1
- package/dist/DropdownMenu/DropdownMenuRadioGroup.js +2 -0
- package/dist/Markdown/Markdown.d.ts.map +1 -1
- package/dist/Markdown/Markdown.js +48 -15
- package/dist/MultiSelector/MultiSelector.d.ts +4 -4
- package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
- package/dist/MultiSelector/MultiSelector.disabledFocus.a11y.chromium.spec.d.ts +2 -0
- package/dist/MultiSelector/MultiSelector.disabledFocus.a11y.chromium.spec.d.ts.map +1 -0
- package/dist/MultiSelector/MultiSelector.disabledFocus.a11y.chromium.spec.js +48 -0
- package/dist/MultiSelector/MultiSelector.js +25 -18
- package/dist/Pagination/Pagination.d.ts.map +1 -1
- package/dist/Pagination/Pagination.js +5 -2
- package/dist/Switch/Switch.d.ts.map +1 -1
- package/dist/Switch/Switch.js +13 -3
- package/dist/TimeInput/TimeInput.d.ts +5 -5
- package/dist/TimeInput/TimeInput.d.ts.map +1 -1
- package/dist/TimeInput/TimeInput.js +37 -20
- package/dist/TimeInput/TouchTimeField.d.ts.map +1 -1
- package/dist/TimeInput/TouchTimeField.js +17 -6
- package/dist/Timestamp/Timestamp.d.ts.map +1 -1
- package/dist/Timestamp/Timestamp.js +41 -8
- package/dist/TreeList/TreeListItem.d.ts.map +1 -1
- package/dist/TreeList/TreeListItem.js +8 -3
- package/dist/hooks/useGridFocus.d.ts.map +1 -1
- package/dist/hooks/useGridFocus.js +10 -1
- package/package.json +4 -4
- package/scripts/agent-doc-state.mjs +24 -2
- package/src/BottomSheet/BottomSheet.spec.md +26 -53
- package/src/BottomSheet/BottomSheet.test.tsx +29 -0
- package/src/BottomSheet/BottomSheet.tsx +8 -4
- package/src/BottomSheet/BottomSheetSwitcher.spec.md +45 -48
- package/src/BottomSheet/BottomSheetSwitcher.test.tsx +26 -0
- package/src/BottomSheet/BottomSheetSwitcher.tsx +6 -0
- package/src/Button/Button.test.tsx +13 -2
- package/src/Button/Button.tsx +23 -2
- package/src/Button/__tests__/Button.a11y.states.ts +4 -3
- package/src/Calendar/Calendar.test.tsx +68 -24
- package/src/Calendar/Calendar.tsx +2 -1
- package/src/Carousel/Carousel.spec.md +146 -0
- package/src/Chat/ChatComposer.spec.md +26 -26
- package/src/Chat/ChatComposer.test.tsx +58 -2
- package/src/Chat/ChatComposer.tsx +25 -1
- package/src/Chat/ChatSystemMessage.doc.mjs +1 -1
- package/src/Chat/ChatSystemMessage.test.tsx +25 -3
- package/src/Chat/ChatSystemMessage.tsx +6 -4
- package/src/Chat/__tests__/ChatSystemMessage.a11y.chromium.spec.ts +8 -9
- package/src/CheckboxList/__tests__/CheckboxList.a11y.chromium.spec.ts +7 -6
- package/src/CodeBlock/CodeBlock.highlightStyles.test.tsx +87 -0
- package/src/CodeBlock/CodeBlock.tsx +11 -1
- package/src/DateRangeInput/DateRangeInput.doc.mjs +6 -5
- package/src/DateRangeInput/DateRangeInput.test.tsx +82 -16
- package/src/DateRangeInput/DateRangeInput.tsx +40 -20
- package/src/DateTimeInput/DateTimeInput.doc.mjs +9 -8
- package/src/DateTimeInput/DateTimeInput.test.tsx +126 -11
- package/src/DateTimeInput/DateTimeInput.tsx +42 -26
- package/src/DateTimeInput/DateTimeInputTouch.test.tsx +24 -0
- package/src/DateTimeInput/NativeDateSegment.tsx +9 -6
- package/src/DateTimeInput/NativePickerSegments.test.tsx +31 -0
- package/src/DateTimeInput/NativeTimeSegment.tsx +9 -6
- package/src/DateTimeInput/TouchDateTimeField.tsx +22 -7
- package/src/Dialog/Dialog.test.tsx +39 -0
- package/src/Dialog/Dialog.tsx +9 -4
- package/src/DropdownMenu/DropdownMenuItem.doc.mjs +66 -7
- package/src/DropdownMenu/DropdownMenuItem.spec.md +209 -0
- package/src/DropdownMenu/DropdownMenuRadioGroup.doc.mjs +62 -7
- package/src/DropdownMenu/DropdownMenuRadioGroup.spec.md +190 -0
- package/src/DropdownMenu/DropdownMenuRadioGroup.tsx +10 -4
- package/src/DropdownMenu/DropdownMenuSelectable.test.tsx +93 -0
- package/src/DropdownMenu/__tests__/DropdownMenuItemAudit.a11y.chromium.spec.ts +366 -0
- package/src/DropdownMenu/__tests__/DropdownMenuRadioGroupAudit.a11y.chromium.spec.ts +327 -0
- package/src/FieldStatus/FieldStatus.spec.md +4 -4
- package/src/FieldStatus/__tests__/StatusMessage.a11y.renders.tsx +0 -18
- package/src/FieldStatus/__tests__/StatusMessage.a11y.states.ts +3 -18
- package/src/FieldStatus/__tests__/StatusMessage.a11y.test.tsx +1 -2
- package/src/Markdown/Markdown.helpers.perf.test.ts +25 -19
- package/src/Markdown/Markdown.rerender.test.tsx +143 -0
- package/src/Markdown/Markdown.tsx +89 -35
- package/src/MultiSelector/MultiSelector.disabledFocus.a11y.chromium.spec.ts +71 -0
- package/src/MultiSelector/MultiSelector.doc.mjs +5 -5
- package/src/MultiSelector/MultiSelector.focusableDisabled.test.tsx +121 -0
- package/src/MultiSelector/MultiSelector.test.tsx +49 -7
- package/src/MultiSelector/MultiSelector.tsx +53 -29
- package/src/Pagination/Pagination.test.tsx +5 -1
- package/src/Pagination/Pagination.tsx +3 -1
- package/src/Switch/Switch.test.tsx +56 -0
- package/src/Switch/Switch.tsx +13 -2
- package/src/Table/plugins/columnResize/useTableColumnResize.spec.md +11 -11
- package/src/Table/plugins/rowStatus/useTableRowStatus.spec.md +4 -3
- package/src/TimeInput/NativeTimeInput.test.tsx +25 -1
- package/src/TimeInput/Presentation.test.tsx +23 -0
- package/src/TimeInput/TimeInput.doc.mjs +8 -7
- package/src/TimeInput/TimeInput.test.tsx +119 -7
- package/src/TimeInput/TimeInput.tsx +51 -23
- package/src/TimeInput/TouchTimeField.tsx +27 -5
- package/src/Timestamp/Timestamp.doc.mjs +1 -1
- package/src/Timestamp/Timestamp.test.tsx +168 -0
- package/src/Timestamp/Timestamp.tsx +62 -11
- package/src/TreeList/TreeList.test.tsx +28 -0
- package/src/TreeList/TreeListItem.tsx +6 -2
- package/src/__tests__/DisabledTriggerFocus.a11y.chromium.spec.ts +86 -0
- package/src/hooks/useGridFocus.ts +16 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,93 @@
|
|
|
1
1
|
# @xds/core
|
|
2
2
|
|
|
3
|
+
# 0.7.3
|
|
4
|
+
|
|
5
|
+
#### New Features
|
|
6
|
+
|
|
7
|
+
- `DropdownMenuSubMenu` takes `header` and `footer`, as the root `DropdownMenu` does, so a sub-menu can have a filter field above its rows, or an action such as "New folder" below them, outside the sub-menu's menu itself. With either, the sub-menu's surface (the flyout, or the drilled-in view on a phone) is a modal dialog named by its row: the row says `aria-haspopup="dialog"`, Tab and Shift+Tab walk the header, the rows and the footer and wrap, Escape returns to the row, and a pointer leaving the flyout closes it only once focus leaves too. A `ContextMenu` does not show a sub-menu's `header` or `footer`. Without them nothing changes.
|
|
8
|
+
|
|
9
|
+
```diff
|
|
10
|
+
<DropdownMenuSubMenu
|
|
11
|
+
label="Move to"
|
|
12
|
+
+ header={<TextInput label="Filter folders" isLabelHidden value={query} onChange={setQuery} />}
|
|
13
|
+
+ footer={<Button label="New folder" onClick={createFolder} />}
|
|
14
|
+
>
|
|
15
|
+
<DropdownMenuItem label="Folder A" onClick={() => move('a')} />
|
|
16
|
+
</DropdownMenuSubMenu>
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
#### Fixes
|
|
20
|
+
|
|
21
|
+
- `TimeInput`'s arrow keys ignore a fractional increment instead of writing a malformed time such as "14:30.5": `adjustTime` returns the time unchanged for a fractional minute delta ([#7823](https://github.com/facebook/astryx/pull/7823)).
|
|
22
|
+
- Screen readers now announce a `Button` that is first rendered with `isLoading` (for example after a remount). Its visually hidden loading live region mounts empty and gets "Loading" on the next frame, because screen readers skip a live region that already holds its text when it appears. A Button that becomes loading after it mounts is unchanged, and a Button mounted idle does no extra render.
|
|
23
|
+
- `ChatComposer`: screen readers now announce a status message, errors assertively and warnings politely, once per occasion: a rerender does not repeat it, and a status that clears and then returns is announced again. Before, the status bar mounted as a `role="alert"` or `role="status"` region already holding its text, which screen readers often skip. The message now goes through the shared announcement channel, and the visible bar no longer carries a live role. No API changes.
|
|
24
|
+
- `ChatSystemMessage`: a new chat notice inside a `ChatMessageList` now has one live region announcing it, the list's polite log, instead of also being a second live region nested in it (WCAG 2.2 SC 4.1.3). Its root no longer forces `role="status"`, in either variant, so date and divider rows are no longer presented as status messages, and a `role` passed to the component reaches its root. Tests that found a system message by the `status` role should query it by its text instead.
|
|
25
|
+
- Keyboard and screen-reader users can now reach disabled `CheckboxInput`, `CheckboxList` items, `Switch`, `Slider` and `FileInput`, and hear that they are disabled. Before, they rendered the native `disabled` attribute unless a `disabledMessage` was set, so Tab skipped them. Now every disabled control exposes `aria-disabled="true"` and keeps the Tab stop it has when enabled, while toggling, selecting, dragging, opening the file picker and any `onClick` stay blocked, and its value is still left out of form submission. A focused disabled checkbox, switch, slider thumb or file input shows its keyboard focus indicator. No API changes.
|
|
26
|
+
- The agent guide that global mode writes to the home folder now tells agents to deliver a page built with Astryx, not only how to find things. Before, agents that found the right template could still build the page with a tool that cannot install packages and deliver a page with no Astryx in it. The guide now tells agents to work in a project folder (creating one if there is none); add `@astryxdesign/core` and `@astryxdesign/cli` to a new project or one without Core, or, in a project that already has `@astryxdesign/core`, the CLI at the same version; run `astryx init` there; follow the same template-first workflow and self-check the project agent docs give; and end by building the project and delivering that build. The guide stays version-free and names only commands every release keeps. The project agent docs are unchanged, and so is what `@astryxdesign/core`'s install script prints: its copy of the shared agent-docs file only gains the same workflow lines.
|
|
27
|
+
- Keyboard and screen-reader users can now reach a disabled `ComplexSelector` and hear that it is unavailable (WCAG 2.2 SC 2.1.1 and 4.1.2). Before, its trigger rendered the native `disabled` attribute, so Tab skipped it and a focused trigger lost focus when disabled; now it exposes `aria-disabled="true"`, keeps focus, shows its keyboard focus outline, and still opens nothing. A press or key on it reaches no handler: not the toggle, not a caller's `onClick` or `onKeyDown`, and not an ancestor's click handler.
|
|
28
|
+
- Keyboard and screen-reader users can now reach a disabled `Calendar` day or `Pagination` dot and hear that it is disabled. Disabled `TreeList` rows' expand toggle and action button, disabled `Pagination` dots and disabled `Calendar` days expose `aria-disabled="true"` instead of the native `disabled` attribute, while clicks, Enter and Space still do nothing and arrow keys still skip disabled days as before. No API changes.
|
|
29
|
+
- `DateInput`: keyboard and screen-reader users can now reach a disabled date field and hear that it is disabled. A disabled or busy field no longer renders native `disabled`: its input and calendar button keep their place in the focus order and expose `aria-disabled`, while typing and opening stay blocked, and a focused disabled field shows its focus ring. Tests that query a disabled DateInput with `toBeDisabled()` or `:disabled` should check `aria-disabled="true"` instead.
|
|
30
|
+
- `DateRangeInput`: keyboard and screen-reader users can now reach a disabled field or preset and hear that it is disabled. A disabled or busy field and a disabled preset no longer render native `disabled`: the trigger, calendar button and presets keep their place in the focus order and expose `aria-disabled`, while opening and selecting stay blocked, and a focused disabled field shows its focus ring. Tests that query them with `toBeDisabled()` or `:disabled` should check `aria-disabled="true"` instead ([#7866](https://github.com/facebook/astryx/pull/7866)).
|
|
31
|
+
- `DateTimeInput`: keyboard and screen-reader users can now reach a disabled or busy field and hear that it is disabled. It no longer renders native `disabled` on its text, native-picker or touch fields, or on its calendar and clock buttons: they keep their place in the focus order and expose `aria-disabled`, while typing, picking, opening and a caller's `onClick` stay blocked, and a focused disabled field shows its focus ring. `TimeInput`'s native picker button, which shares the time segment and stays out of the tab order, also moves from `disabled` to `aria-disabled` and stays inert. Tests that query a disabled DateTimeInput with `toBeDisabled()` or `:disabled` should check `aria-disabled="true"` instead.
|
|
32
|
+
- Apps that use Core's prebuilt CSS without a StyleX build step now get the default data colors: the prebuilt CSS defines the canonical `dataVars` defaults, so compiled imports and raw CSS references paint correctly.
|
|
33
|
+
- `Dialog`, `BottomSheet` and `BottomSheetSwitcher` stay open when a file picker inside them is dismissed. A file input fires a bubbling `cancel` event when its picker closes without a choice, and all three took that event for a close request of their own and closed (a switcher closed its whole flow). They now act only on a `cancel` aimed at their own `<dialog>`, so Escape and platform close requests (the Android back gesture) behave as before. No API changes.
|
|
34
|
+
- `DropdownMenuRadioGroup` now forwards `ref`, and its docs explain controlled selection, how to name the group, when the menu closes, and how it composes inside a `DropdownMenu`.
|
|
35
|
+
- `astryx init` writes the agent docs at the project root, in files the project commits, so Codex, Gemini CLI, Copilot CLI and Claude Code all read the block from the project root or any folder below it ([#7497](https://github.com/facebook/astryx/pull/7497)). It no longer writes agent docs into a project's subfolder, the home folder, or a settings folder in it such as `~/.gemini`.
|
|
36
|
+
- `AGENTS.md` holds the block, created when missing. Before, a project with only `CLAUDE.md` got the block only there, so Codex and Gemini CLI never saw it.
|
|
37
|
+
- Claude Code skips `AGENTS.md` in a folder that has a `CLAUDE.md` or `.claude/CLAUDE.md`, so the Claude Code file the project already has keeps a full copy: root `CLAUDE.md`, else `.claude/CLAUDE.md`. It keeps the copy even when it imports `AGENTS.md`, because Claude Code does not follow that import in a session started in a subfolder; started at the root, Claude Code then reads two. When both exist, the copy goes in root `CLAUDE.md`, which projects commit even when they ignore `.claude/`, and a block in `.claude/CLAUDE.md` is removed. Init creates no Claude file. `astryx upgrade` refreshes every copy, except in a project at the top of a home settings folder (see the next entry).
|
|
38
|
+
- Gemini CLI reads only `GEMINI.md`: init adds a one-line import, `@./AGENTS.md`, creating `GEMINI.md` when it is missing. It adds none when `GEMINI.md` already imports `AGENTS.md`, inline or on its own line. It adds the import even when the project's `.gemini/settings.json` has Gemini read `AGENTS.md` through `context.fileName`: Gemini loads those settings only when it starts at the project root, so a session started in a subfolder would otherwise get no copy. Started at the root, Gemini then reads two.
|
|
39
|
+
- The project root is the nearest folder at or above where init runs whose `package.json` declares an `@astryxdesign` package, else the nearest with any `package.json`. The search stops at a repository root and never counts the home folder. With no `package.json` found, init writes where it runs, as before. `docsWritten` still lists each file relative to where init ran, for example `../../AGENTS.md`.
|
|
40
|
+
- A `GEMINI.md` that resolves outside the project, for example a link to a shared file, is skipped and reported in `docsError` with one note (not an error line), in the default layout and in a project's own layout; the rest is written and init exits 0.
|
|
41
|
+
- The managed block belongs to Astryx: init and `astryx upgrade` write, refresh, and remove only the block, whatever ignore rules or generated markers say, as 0.7.1 did, and never change the text around it. Every write stays inside the project: run in the folder 0.7.1 wrote, an agent file 0.7.1 wrote there whose path leaves the project still refuses the run with exit 1. The project's Claude Code file (root `CLAUDE.md`, or `.claude/CLAUDE.md` when there is no root one) that resolves outside the project and is a block-less import of an existing `AGENTS.md`, which 0.7.1 left alone, is skipped and reported in `docsError` with one note, and init exits 0. Run from a folder below the project root, where 0.7.1 wrote in that folder instead, a project-root file whose path leaves the project is skipped and reported in `docsError` with one note, the rest is written, and init exits 0.
|
|
42
|
+
- While root `CLAUDE.md` is untracked and ignored by the repository's ignore rules (any ignore file from the repository root down, such as a monorepo's root `.gitignore`, the local exclude file, or configured excludes; init asks git, Sapling or Mercurial), a `.claude/CLAUDE.md` the project commits gets the copy too, so a fresh clone still gives Claude Code a copy; `--agent claude` and `--agent all` write it there as well. A file the repository tracks counts as committed whatever the ignore rules say, as git and Mercurial ignore only untracked files, and when the repository cannot answer, the copy is kept, on the first run as on later ones. Such a copy that resolves outside the project refuses the run with exit 1 where 0.7.1 wrote it too; one 0.7.1 did not write (the one `--agent claude` adds, or a block-less import of an existing `AGENTS.md`) is skipped and reported in `docsError` with one note, and init exits 0. So is a `.claude/CLAUDE.md` whose block `--agent claude` would remove beside a `CLAUDE.md`, since 0.7.1's `claude` preset wrote only `CLAUDE.md` there. Beside a committed root `CLAUDE.md`, with `.claude` linked outside the project, three cases that 0.7.1 refused now exit 0 with nothing written: the default with a `.claude/CLAUDE.md` of plain text, and `--agent all` with one of plain text or a block-less import of `AGENTS.md`; root `CLAUDE.md` holds the copy, so no write leaves the project. In a project that keeps its own layout, a `GEMINI.md` that imports no agent file now gets a copy, as the other agent files do.
|
|
43
|
+
- The copy in `.claude/CLAUDE.md` is removed only once root `CLAUDE.md` holds the same block, and only the managed block between its markers: the rest of the file stays, and the file is deleted only when nothing but whitespace is left. `astryx init --remove-agents` deletes a file it created only when nothing but whitespace or init's own heading is left; 0.7.0 also deleted a file whose remaining text had a heading and any line with the word "guidance".
|
|
44
|
+
- `astryx init --remove-agents` removes the block at the project root, where `init` writes it, and in the folder it runs in. Run from a subfolder, it removes what `init` wrote at the root, and a block an earlier version left in that subfolder; a root agent file with a block that resolves outside the project is left as it is with a note, and the run exits 0, as 0.7.1 did when it touched only the subfolder. Exit codes and the JSON shape are unchanged.
|
|
45
|
+
- `--agent claude` and `--agent all` never leave a block in both `CLAUDE.md` and `.claude/CLAUDE.md`, unless the project ignores `CLAUDE.md`: when `CLAUDE.md` gets the block, a block in `.claude/CLAUDE.md` is removed. `--agent all` keeps the `GEMINI.md` import. The `--agent` help and the working-with-AI guide say so. `--agent-docs-path` writes where init runs, as before.
|
|
46
|
+
- `astryx doctor` fails when the `GEMINI.md` import points at an `AGENTS.md` with no block. The setup check in the CLI and in `@astryxdesign/core` no longer counts that import as set up, and looks at `GEMINI.md`. The reminder to run `init` that commands print looks at the project root too, so it stops once `init` has run in a nested package.
|
|
47
|
+
- `astryx init` and `astryx upgrade` no longer write agent docs into your home folder, or into a settings folder in it such as `~/.gemini` or `~/.claude` outside a project. Agents read the files in those folders in every project, so a block there reached unrelated work. This follows the CLI's existing rules that no command writes agent docs into those folders and that a write outside a command's own folder is refused before anything is written.
|
|
48
|
+
- **Refused by `init`:** the home folder itself, and the top of any folder in it whose name starts with a dot (every such folder is a settings folder), even when it holds a `package.json`. A folder below it with its own `package.json` is a project and is set up normally, such as an agent worktree in `~/.codex/worktrees/` or `~/.cursor/worktrees/`, and `astryx upgrade` refreshes it. With `--agent-docs-path`, each file's own folder is checked: from the home folder, `notes/AI.md` is written as before, while `AI.md` or `.claude/CLAUDE.md` is refused.
|
|
49
|
+
- **What `init` does instead:** it writes no agent docs, reports `docsError` as `install-failed` with the reason, and exits 0, as before.
|
|
50
|
+
- **Refused by `upgrade`:** refreshing a block in a project whose root is the home folder or the top of a settings folder, such as `~/.dotfiles` with a `package.json`, with or without `--apply`. It leaves the block as it is, sets `agentDocs.action` to `error` (never `would-refresh`), and warns with the folder and why; its other steps and its exit status are as before. With no block there, it gives the same reason instead of suggesting `astryx init`. `astryx doctor`'s agent-docs fix does the same, and the setup reminder after each command stays quiet.
|
|
51
|
+
- **Migration:** run `astryx init` from the project's own folder, or add the block to the file by hand. Move a project rooted at the home folder or a settings folder into a folder of its own, or update or remove its block by hand. To remove a block an earlier version wrote into `~/.claude/CLAUDE.md`, run `astryx init --remove-agents` in the home folder.
|
|
52
|
+
- Keyboard and screen-reader users can now reach a disabled `MultiSelector` and hear that it is unavailable (WCAG 2.2 SC 2.1.1 and 4.1.2). Before, its trigger rendered the native `disabled` attribute and `tabIndex={-1}`, so Tab skipped it and a focused trigger lost focus when disabled; now it exposes `aria-disabled="true"`, keeps focus, still opens nothing, and submits no form value. Like a natively disabled button, it runs no caller event handler other than focus and blur, and a press on it reaches no handler. A focused disabled trigger shows a keyboard focus ring, dimmed with the rest of the control (WCAG 2.2 SC 2.4.7).
|
|
53
|
+
- Keyboard and screen-reader users can now reach a disabled `Link` or `ClickableCard`, and the buttons of a disabled `Token`. Before, they rendered the native `disabled` attribute or `tabIndex={-1}`, so Tab skipped them. Now each disabled control exposes `aria-disabled="true"` and keeps the Tab stop it has when enabled, while activation by click, Enter or Space, `onClick`, removal and navigation stay blocked; a disabled Link keeps no live destination and is exposed with the link role. A `Popover` no longer opens from a wrapped or `anchorRef` trigger marked `aria-disabled="true"` (for example a disabled `Button` with a `tooltip`), including for a click dispatched straight on the trigger; before, such a click opened it. No API changes.
|
|
54
|
+
- Keyboard and screen-reader users can now reach a disabled `Selector` and hear that it is unavailable (WCAG 2.2 SC 2.1.1 and 4.1.2). Before, its trigger rendered the native `disabled` attribute and `tabIndex={-1}`, so Tab skipped it and a focused trigger lost focus when disabled; now it exposes `aria-disabled="true"`, keeps focus, still opens nothing, and submits no form value. Like a natively disabled button, it runs no caller event handler other than focus and blur, and a press on it reaches no handler. A focused disabled trigger shows a keyboard focus ring, dimmed with the rest of the control (WCAG 2.2 SC 2.4.7).
|
|
55
|
+
- `Selector` options in a narrow list now shrink and truncate a long label with an ellipsis instead of being clipped past the list edge.
|
|
56
|
+
- `Switch`: a busy switch announces "Loading" once per busy start. Under React StrictMode the announcement used to be made twice.
|
|
57
|
+
- `TimeInput`: keyboard and screen-reader users can now reach a disabled field, or a busy bottom-sheet field, and hear that it is disabled. It no longer renders native `disabled` on its typed, native-picker or touch input or its picker button: they keep their place in the focus order and expose `aria-disabled`, while typing, arrow-key adjustment, opening, submitting a surrounding form with Enter, and a caller's `onClick` stay blocked, a draft typed before the field became disabled is dropped, and a focused disabled field shows its focus ring. Tests that query a disabled or busy TimeInput with `toBeDisabled()` or `:disabled` should check `aria-disabled="true"` instead.
|
|
58
|
+
- Pages that use `Timestamp` with an absolute format (`date`, `time`, `date_time` and the other fixed formats) now prerender in Next.js with `cacheComponents` turned on, where they used to fail the build: `Timestamp` no longer reads the current time while rendering on the server, and absolute formats never read the clock. `relative`, `relative_short` and `auto` read the clock on the client only: a server render or static prerender shows the full date and time in UTC, labelled, and the client switches to the format's normal output right after hydration, so server and client markup now always match. Client-only rendering is unchanged. No API changes ([#7883](https://github.com/facebook/astryx/pull/7883)).
|
|
59
|
+
- `Tooltip`: moving the pointer straight from the trigger onto the tooltip in one step no longer hides it, so it stays open while hovered (WCAG 2.2 SC 1.4.13).
|
|
60
|
+
- A `SideNavItem` in a collapsed `SideNav` now shows its tooltip on hover and gets `aria-describedby`, even when the item first appears inside an already-collapsed `SideNav`, the common case for saved collapse state. Before, only an item that collapsed after it appeared got a tooltip. Fixes [#7692](https://github.com/facebook/astryx/issues/7692).
|
|
61
|
+
|
|
62
|
+
A `Tooltip` with an `anchorRef` that renders inside the very element the ref points at, as `SideNavItem` does, now attaches however it mounted. The effect now re-checks the anchor once the commit has finished attaching refs; event listeners and the `aria-describedby` merge and restore are unchanged.
|
|
63
|
+
|
|
64
|
+
- `TopNav` on narrow screens: a long `TopNavHeading` now gives way (it truncates with an ellipsis, or wraps when the heading is a link) instead of pushing the end content and the menu toggle past the edge of the bar, and the mobile drawer's close button is back on screen.
|
|
65
|
+
- `Typeahead`: clearing the value while editing it now empties the input and reports `onChangeQuery('')`, instead of leaving the old label in a field with no value. Fixes [#7038](https://github.com/facebook/astryx/issues/7038).
|
|
66
|
+
|
|
67
|
+
#### Performance
|
|
68
|
+
|
|
69
|
+
- Pages with many code blocks, such as a long Markdown document, paint sooner on first load: `CodeBlock` inserts its syntax-highlight rules before the first layout read instead of after it, which cut first paint by 16–19% in 100–500 KB test documents ([#7875](https://github.com/facebook/astryx/pull/7875)). The rules and the highlighted output are unchanged.
|
|
70
|
+
- Pages that update around a long `Markdown` document stay responsive: Markdown skips re-rendering its document when a parent re-renders without changing the text or any rendering prop, and a link handler passed as a new function on each render no longer forces that work. The rendered output is unchanged.
|
|
71
|
+
|
|
72
|
+
#### Documentation
|
|
73
|
+
|
|
74
|
+
- The `DropdownMenuItem` docs now explain when an item is an action or a destination, disabled items, and supporting content.
|
|
75
|
+
|
|
76
|
+
#### Contributors
|
|
77
|
+
|
|
78
|
+
Thanks to everyone who contributed to this release:
|
|
79
|
+
|
|
80
|
+
- @aashish254
|
|
81
|
+
- @cixzhang
|
|
82
|
+
- @ejhammond
|
|
83
|
+
- @HelloOjasMutreja
|
|
84
|
+
- @josephfarina
|
|
85
|
+
- @kyu-rong
|
|
86
|
+
- @Pushpak731
|
|
87
|
+
- @vjeux
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
3
91
|
# 0.7.2
|
|
4
92
|
|
|
5
93
|
#### Experimental APIs
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BottomSheet.d.ts","sourceRoot":"","sources":["../../src/BottomSheet/BottomSheet.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,EAOL,KAAK,SAAS,EACd,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAEf,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAC5C,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,WAAW,CAAC;AAC7C,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,gBAAgB,CAAC;AAmBhD,YAAY,EAAC,iBAAiB,EAAE,oBAAoB,EAAC,MAAM,oBAAoB,CAAC;AAChF,OAAO,KAAK,EAAC,iBAAiB,EAAE,oBAAoB,EAAC,MAAM,oBAAoB,CAAC;AA0EhF,UAAU,sBAAuB,SAAQ,SAAS,CAAC,cAAc,CAAC;IAChE,qDAAqD;IACrD,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAEhC,sCAAsC;IACtC,KAAK,EAAE,MAAM,CAAC;IAEd,0EAA0E;IAC1E,QAAQ,EAAE,SAAS,CAAC;IAEpB;;;;;;;;OAQG;IACH,OAAO,CAAC,EAAE,WAAW,CAAC;IAEtB,wGAAwG;IACxG,MAAM,CAAC,EAAE,iBAAiB,GAAG,MAAM,GAAG,MAAM,CAAC;IAE7C;;;;;;;OAOG;IACH,UAAU,CAAC,EAAE,aAAa,CAAC,oBAAoB,CAAC,CAAC;IAEjD;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,aAAa,CAAC;CACzB;AAED,UAAU,0BAA2B,SAAQ,sBAAsB;IACjE,MAAM,EAAE,OAAO,CAAC;IAChB,YAAY,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;IACxC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,0DAA0D;IAC1D,aAAa,CAAC,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IAC9C,OAAO,CAAC,EAAE,KAAK,CAAC;CACjB;AAED,UAAU,wBAAyB,SAAQ,sBAAsB;IAC/D,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,KAAK,CAAC;IACf,YAAY,CAAC,EAAE,KAAK,CAAC;IACrB,QAAQ,CAAC,EAAE,KAAK,CAAC;CAClB;AAED,MAAM,MAAM,gBAAgB,GAC1B,0BAA0B,GAAG,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"BottomSheet.d.ts","sourceRoot":"","sources":["../../src/BottomSheet/BottomSheet.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,EAOL,KAAK,SAAS,EACd,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAEf,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAC5C,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,WAAW,CAAC;AAC7C,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,gBAAgB,CAAC;AAmBhD,YAAY,EAAC,iBAAiB,EAAE,oBAAoB,EAAC,MAAM,oBAAoB,CAAC;AAChF,OAAO,KAAK,EAAC,iBAAiB,EAAE,oBAAoB,EAAC,MAAM,oBAAoB,CAAC;AA0EhF,UAAU,sBAAuB,SAAQ,SAAS,CAAC,cAAc,CAAC;IAChE,qDAAqD;IACrD,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAEhC,sCAAsC;IACtC,KAAK,EAAE,MAAM,CAAC;IAEd,0EAA0E;IAC1E,QAAQ,EAAE,SAAS,CAAC;IAEpB;;;;;;;;OAQG;IACH,OAAO,CAAC,EAAE,WAAW,CAAC;IAEtB,wGAAwG;IACxG,MAAM,CAAC,EAAE,iBAAiB,GAAG,MAAM,GAAG,MAAM,CAAC;IAE7C;;;;;;;OAOG;IACH,UAAU,CAAC,EAAE,aAAa,CAAC,oBAAoB,CAAC,CAAC;IAEjD;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,aAAa,CAAC;CACzB;AAED,UAAU,0BAA2B,SAAQ,sBAAsB;IACjE,MAAM,EAAE,OAAO,CAAC;IAChB,YAAY,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;IACxC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,0DAA0D;IAC1D,aAAa,CAAC,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IAC9C,OAAO,CAAC,EAAE,KAAK,CAAC;CACjB;AAED,UAAU,wBAAyB,SAAQ,sBAAsB;IAC/D,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,KAAK,CAAC;IACf,YAAY,CAAC,EAAE,KAAK,CAAC;IACrB,QAAQ,CAAC,EAAE,KAAK,CAAC;CAClB;AAED,MAAM,MAAM,gBAAgB,GAC1B,0BAA0B,GAAG,wBAAwB,CAAC;AA0YxD;;;GAGG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,+BA6BlD;yBA7Be,WAAW"}
|
|
@@ -203,11 +203,15 @@ function StandaloneBottomSheet({
|
|
|
203
203
|
});
|
|
204
204
|
|
|
205
205
|
// The native `cancel` event is a close request the stack never saw a press
|
|
206
|
-
// for (Android back, the platform close watcher).
|
|
207
|
-
//
|
|
208
|
-
//
|
|
209
|
-
//
|
|
206
|
+
// for (Android back, the platform close watcher). One that bubbles up from
|
|
207
|
+
// inside is not: a file input fires it when its picker is dismissed, so it is
|
|
208
|
+
// left alone. Otherwise always preventDefault so the browser cannot close the
|
|
209
|
+
// controlled <dialog>, then answer with the stack's rules: only the top-most
|
|
210
|
+
// layer dismisses, and nothing dismisses during an IME composition.
|
|
210
211
|
const handleCancel = useCallback(event => {
|
|
212
|
+
if (event.target !== event.currentTarget) {
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
211
215
|
event.preventDefault();
|
|
212
216
|
if (shouldDismissOnCloseRequest()) {
|
|
213
217
|
dismissOnEscape();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BottomSheetSwitcher.d.ts","sourceRoot":"","sources":["../../src/BottomSheet/BottomSheetSwitcher.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,OAAO,EAQL,KAAK,SAAS,EACd,KAAK,cAAc,EACpB,MAAM,OAAO,CAAC;AAEf,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAwI5C,MAAM,WAAW,wBAAyB,SAAQ,SAAS,CAAC,iBAAiB,CAAC;IAC5E,iDAAiD;IACjD,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;IAEnC,oEAAoE;IACpE,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,cAAc,CAAC,iBAAiB,CAAC,KAAK,IAAI,CAAC;IAE9D;;;;;OAKG;IACH,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAE3B,iEAAiE;IACjE,mBAAmB,EAAE,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IAEtD;;;;OAIG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB,0DAA0D;IAC1D,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,mBAAmB,CAAC,EAClC,WAAW,EACX,mBAAmB,EACnB,QAAe,EACf,QAAQ,EACR,GAAG,EACH,MAAM,EACN,SAAS,EACT,KAAK,EACL,QAAQ,EACR,OAAO,EACP,SAAS,EACT,GAAG,KAAK,EACT,EAAE,wBAAwB,+
|
|
1
|
+
{"version":3,"file":"BottomSheetSwitcher.d.ts","sourceRoot":"","sources":["../../src/BottomSheet/BottomSheetSwitcher.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,OAAO,EAQL,KAAK,SAAS,EACd,KAAK,cAAc,EACpB,MAAM,OAAO,CAAC;AAEf,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAwI5C,MAAM,WAAW,wBAAyB,SAAQ,SAAS,CAAC,iBAAiB,CAAC;IAC5E,iDAAiD;IACjD,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;IAEnC,oEAAoE;IACpE,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,cAAc,CAAC,iBAAiB,CAAC,KAAK,IAAI,CAAC;IAE9D;;;;;OAKG;IACH,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAE3B,iEAAiE;IACjE,mBAAmB,EAAE,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IAEtD;;;;OAIG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB,0DAA0D;IAC1D,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,mBAAmB,CAAC,EAClC,WAAW,EACX,mBAAmB,EACnB,QAAe,EACf,QAAQ,EACR,GAAG,EACH,MAAM,EACN,SAAS,EACT,KAAK,EACL,QAAQ,EACR,OAAO,EACP,SAAS,EACT,GAAG,KAAK,EACT,EAAE,wBAAwB,+BAya1B;yBAtbe,mBAAmB"}
|
|
@@ -404,7 +404,14 @@ export function BottomSheetSwitcher({
|
|
|
404
404
|
onSheetScrimOpacityChange
|
|
405
405
|
}), [activeSheet, getSheetAlignmentOffset, getSheetPhase, hasScrim, onActiveSheetChange, onSheetEnterStart, onSheetScrimOpacityChange, onSheetTransitionComplete, registerSheetElement, registerSheetLabel, registerSheetPurpose]);
|
|
406
406
|
const activeLabel = (activeSheet == null ? null : sheetLabels.get(activeSheet)) ?? (visibleTransition.retainedSheet == null ? undefined : sheetLabels.get(visibleTransition.retainedSheet));
|
|
407
|
+
|
|
408
|
+
// A `cancel` that bubbles up from a step is not a close request for the
|
|
409
|
+
// flow: a file input fires one when its picker is dismissed, and a step
|
|
410
|
+
// renders no dialog of its own, so it lands here. It is left alone.
|
|
407
411
|
const handleCancel = useCallback(event => {
|
|
412
|
+
if (event.target !== event.currentTarget) {
|
|
413
|
+
return;
|
|
414
|
+
}
|
|
408
415
|
event.preventDefault();
|
|
409
416
|
if (shouldDismissOnCloseRequest()) {
|
|
410
417
|
dismissOnEscape();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Button.d.ts","sourceRoot":"","sources":["../../src/Button/Button.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,
|
|
1
|
+
{"version":3,"file":"Button.d.ts","sourceRoot":"","sources":["../../src/Button/Button.tsx"],"names":[],"mappings":"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"}
|
package/dist/Button/Button.js
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
*
|
|
18
18
|
* Last synced props: label, variant, size, isDisabled, isLoading, isInterruptible, clickAction, icon, isIconOnly, width, children, tooltip, endContent, href, as, target, rel
|
|
19
19
|
*/
|
|
20
|
-
import { useRef, useTransition } from 'react';
|
|
20
|
+
import { useEffect, useRef, useState, useTransition } from 'react';
|
|
21
21
|
import * as stylex from '@stylexjs/stylex';
|
|
22
22
|
import { useTooltip } from "../Tooltip/useTooltip.js";
|
|
23
23
|
import "../theme/tokens.stylex.js";
|
|
@@ -357,6 +357,19 @@ export function Button({
|
|
|
357
357
|
// re-click can land and interrupt the in-flight action with a fresh one.
|
|
358
358
|
const actionInFlightRef = useRef(false);
|
|
359
359
|
const isLoadingState = isLoading || isPending;
|
|
360
|
+
// The loading live region must exist empty before it receives "Loading":
|
|
361
|
+
// many screen readers skip a live region that mounts already holding its
|
|
362
|
+
// text, which is what a Button first rendered loading did (spec:AST-086
|
|
363
|
+
// FR3). Only that case holds the text back, until the frame after the
|
|
364
|
+
// region mounts; a Button mounted idle never re-renders for this.
|
|
365
|
+
const [isLiveRegionReady, setIsLiveRegionReady] = useState(() => !isLoadingState);
|
|
366
|
+
useEffect(() => {
|
|
367
|
+
if (isLiveRegionReady) {
|
|
368
|
+
return;
|
|
369
|
+
}
|
|
370
|
+
const frame = requestAnimationFrame(() => setIsLiveRegionReady(true));
|
|
371
|
+
return () => cancelAnimationFrame(frame);
|
|
372
|
+
}, [isLiveRegionReady]);
|
|
360
373
|
// Delay the spinner reveal for action-driven loading (clickAction's own
|
|
361
374
|
// transition) so a fast action that settles within the delay does not flash
|
|
362
375
|
// a spinner. Interruptible loading is delayed too, so rapid re-clicks settle
|
|
@@ -506,7 +519,7 @@ export function Button({
|
|
|
506
519
|
}), /*#__PURE__*/_jsx(VisuallyHidden, {
|
|
507
520
|
role: "status",
|
|
508
521
|
"aria-live": "polite",
|
|
509
|
-
children: isLoadingState ? t('@astryx.button.loading') : ''
|
|
522
|
+
children: isLoadingState && isLiveRegionReady ? t('@astryx.button.loading') : ''
|
|
510
523
|
})]
|
|
511
524
|
});
|
|
512
525
|
|
|
@@ -939,8 +939,9 @@ function DayCell({
|
|
|
939
939
|
// Mark today's cell programmatically (APG date-picker pattern), not just
|
|
940
940
|
// visually, so screen-reader users can identify the current date.
|
|
941
941
|
,
|
|
942
|
-
"aria-current": state.isToday ? 'date' : undefined
|
|
943
|
-
disabled:
|
|
942
|
+
"aria-current": state.isToday ? 'date' : undefined
|
|
943
|
+
// A disabled day stays focusable through aria-disabled (spec:AST-085
|
|
944
|
+
// FR1); arrows still skip it and its click and hover are guarded.
|
|
944
945
|
// Initial roving tab-stop seed; useGridFocus owns it after mount.
|
|
945
946
|
,
|
|
946
947
|
tabIndex: isTabbableDay ? 0 : -1,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChatComposer.d.ts","sourceRoot":"","sources":["../../src/Chat/ChatComposer.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"ChatComposer.d.ts","sourceRoot":"","sources":["../../src/Chat/ChatComposer.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EAAE,EAMZ,KAAK,SAAS,EAGf,MAAM,OAAO,CAAC;AACf,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAgC5C,MAAM,MAAM,kBAAkB,GAAG;IAC/B,IAAI,EAAE,OAAO,GAAG,SAAS,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG,SAAS,GAAG,UAAU,GAAG,UAAU,CAAC;AAEtE,MAAM,WAAW,iBAAkB,SAAQ,IAAI,CAC7C,SAAS,CAAC,cAAc,CAAC,EACzB,UAAU,GAAG,UAAU,CACxB;IACC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAChC,+CAA+C;IAC/C,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,kDAAkD;IAClD,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,kFAAkF;IAClF,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,oCAAoC;IACpC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0CAA0C;IAC1C,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,qCAAqC;IACrC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,uCAAuC;IACvC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,sBAAsB;IACtB,OAAO,CAAC,EAAE,mBAAmB,CAAC;IAC9B;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;IAI3B,6GAA6G;IAC7G,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,yHAAyH;IACzH,aAAa,CAAC,EAAE,SAAS,CAAC;IAC1B,yGAAyG;IACzG,aAAa,CAAC,EAAE,SAAS,CAAC;IAC1B,2DAA2D;IAC3D,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,gHAAgH;IAChH,aAAa,CAAC,EAAE,SAAS,CAAC;IAC1B,gHAAgH;IAChH,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,gDAAgD;IAChD,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB,iEAAiE;IACjE,MAAM,CAAC,EAAE,kBAAkB,CAAC;IAC5B,oDAAoD;IACpD,cAAc,CAAC,EAAE,KAAK,GAAG,QAAQ,CAAC;CACnC;AAkND;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,iBAAiB,qBAwOpD;yBAxOe,YAAY"}
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
* - /apps/storybook/stories/ChatComposer.stories.tsx
|
|
23
23
|
* - /packages/cli/assets/templates/blocks/components/ChatComposer/ (block examples)
|
|
24
24
|
*/
|
|
25
|
-
import React, { useState, useCallback, useRef, useMemo } from 'react';
|
|
25
|
+
import React, { useState, useCallback, useEffect, useRef, useMemo } from 'react';
|
|
26
26
|
import * as stylex from '@stylexjs/stylex';
|
|
27
27
|
import "../theme/tokens.stylex.js";
|
|
28
28
|
import { colorVars, spacingVars, radiusVars, shadowVars, durationVars, easeVars, borderVars, typeScaleVars, typographyVars } from "../theme/tokens.stylex.js";
|
|
@@ -33,6 +33,7 @@ import { ChatComposerContext } from "./ChatContext.js";
|
|
|
33
33
|
import { ChatSendButton } from "./ChatSendButton.js";
|
|
34
34
|
import { themeProps } from "../utils/themeProps.js";
|
|
35
35
|
import { useTranslator } from "../i18n/index.js";
|
|
36
|
+
import { useAnnounce } from "../hooks/useAnnounce.js";
|
|
36
37
|
import { focusOutlineStyles } from "../utils/focusOutline.stylex.js";
|
|
37
38
|
import { getInteractionModality, useInteractionModalityTracking } from "../utils/interactionModality.js";
|
|
38
39
|
|
|
@@ -191,8 +192,30 @@ export function ChatComposer(props) {
|
|
|
191
192
|
setHasKeyboardEditorFocus(false);
|
|
192
193
|
}
|
|
193
194
|
}, []);
|
|
195
|
+
|
|
196
|
+
// The status bar mounts together with its message, and a live region born
|
|
197
|
+
// holding its text is not reliably announced, so the message goes through
|
|
198
|
+
// the shared channel instead: errors assertively, warnings politely
|
|
199
|
+
// (spec:AST-086 FR2, FR5). The ref keeps a rerender or a StrictMode effect
|
|
200
|
+
// replay from repeating it; clearing the status re-arms it, so the same
|
|
201
|
+
// message shown again is a new occasion (FR6).
|
|
202
|
+
const announce = useAnnounce();
|
|
203
|
+
const statusType = status?.type;
|
|
204
|
+
const statusMessage = status?.message;
|
|
205
|
+
const announcedStatusRef = useRef(null);
|
|
206
|
+
useEffect(() => {
|
|
207
|
+
if (!statusMessage) {
|
|
208
|
+
announcedStatusRef.current = null;
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
const occasion = `${statusType}\u0000${statusMessage}`;
|
|
212
|
+
if (announcedStatusRef.current === occasion) {
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
announcedStatusRef.current = occasion;
|
|
216
|
+
announce(statusMessage, statusType === 'error' ? 'assertive' : 'polite');
|
|
217
|
+
}, [announce, statusType, statusMessage]);
|
|
194
218
|
const statusEl = status ? /*#__PURE__*/_jsxs("div", {
|
|
195
|
-
role: status.type === 'error' ? 'alert' : 'status',
|
|
196
219
|
...{
|
|
197
220
|
0: {
|
|
198
221
|
className: "x1n2onr6 x1ja2u2z x78zum5 x6s0dn4 x1txdalj x1pzlopt x141an7d x1ltkj2j x9ynric x1htvmrp xvpcij2 xckg3cf xkvxy4d x6k0y1c"
|
|
@@ -44,6 +44,10 @@ export interface ChatSystemMessageProps extends BaseProps<HTMLDivElement> {
|
|
|
44
44
|
* "user joined", status changes. Supports a divider variant with horizontal
|
|
45
45
|
* lines on each side of the text.
|
|
46
46
|
*
|
|
47
|
+
* It carries no live role: a notice added to a `ChatMessageList` is announced
|
|
48
|
+
* by the list's log, which owns content added inside it (`spec:AST-086` FR4),
|
|
49
|
+
* and a date or divider row is ordinary transcript content.
|
|
50
|
+
*
|
|
47
51
|
* @example
|
|
48
52
|
* ```
|
|
49
53
|
* <ChatSystemMessage>Conversation started</ChatSystemMessage>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChatSystemMessage.d.ts","sourceRoot":"","sources":["../../src/Chat/ChatSystemMessage.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,OAAO,CAAC;AAWrC,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAG5C,MAAM,MAAM,wBAAwB,GAAG,SAAS,GAAG,SAAS,CAAC;AAE7D,MAAM,WAAW,sBAAuB,SAAQ,SAAS,CAAC,cAAc,CAAC;IACvE,wCAAwC;IACxC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAEhC;;OAEG;IACH,QAAQ,EAAE,SAAS,CAAC;IAEpB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,wBAAwB,CAAC;IAEnC;;;OAGG;IACH,IAAI,CAAC,EAAE,SAAS,CAAC;CAClB;AAwCD
|
|
1
|
+
{"version":3,"file":"ChatSystemMessage.d.ts","sourceRoot":"","sources":["../../src/Chat/ChatSystemMessage.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,OAAO,CAAC;AAWrC,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAG5C,MAAM,MAAM,wBAAwB,GAAG,SAAS,GAAG,SAAS,CAAC;AAE7D,MAAM,WAAW,sBAAuB,SAAQ,SAAS,CAAC,cAAc,CAAC;IACvE,wCAAwC;IACxC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAEhC;;OAEG;IACH,QAAQ,EAAE,SAAS,CAAC;IAEpB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,wBAAwB,CAAC;IAEnC;;;OAGG;IACH,IAAI,CAAC,EAAE,SAAS,CAAC;CAClB;AAwCD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,iBAAiB,CAAC,EAChC,QAAQ,EACR,OAAmB,EACnB,IAAI,EACJ,MAAM,EACN,SAAS,EACT,KAAK,EAAE,SAAS,EAChB,GAAG,EACH,GAAG,IAAI,EACR,EAAE,sBAAsB,+BAiCxB;yBA1Ce,iBAAiB"}
|
|
@@ -60,6 +60,10 @@ const styles = {
|
|
|
60
60
|
* "user joined", status changes. Supports a divider variant with horizontal
|
|
61
61
|
* lines on each side of the text.
|
|
62
62
|
*
|
|
63
|
+
* It carries no live role: a notice added to a `ChatMessageList` is announced
|
|
64
|
+
* by the list's log, which owns content added inside it (`spec:AST-086` FR4),
|
|
65
|
+
* and a date or divider row is ordinary transcript content.
|
|
66
|
+
*
|
|
63
67
|
* @example
|
|
64
68
|
* ```
|
|
65
69
|
* <ChatSystemMessage>Conversation started</ChatSystemMessage>
|
|
@@ -84,7 +88,6 @@ export function ChatSystemMessage({
|
|
|
84
88
|
variant
|
|
85
89
|
}), stylex.props(styles.dividerWrap, xstyle), className, styleProp),
|
|
86
90
|
...rest,
|
|
87
|
-
role: "status",
|
|
88
91
|
children: /*#__PURE__*/_jsx(Divider, {
|
|
89
92
|
label: children
|
|
90
93
|
})
|
|
@@ -96,7 +99,6 @@ export function ChatSystemMessage({
|
|
|
96
99
|
variant
|
|
97
100
|
}), stylex.props(styles.root, xstyle), className, styleProp),
|
|
98
101
|
...rest,
|
|
99
|
-
role: "status",
|
|
100
102
|
children: /*#__PURE__*/_jsxs("span", {
|
|
101
103
|
...{
|
|
102
104
|
className: "x3nfvp2 x6s0dn4 x1s4dlld"
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CodeBlock.d.ts","sourceRoot":"","sources":["../../src/CodeBlock/CodeBlock.tsx"],"names":[],"mappings":"AAoBA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAgC5C,OAAO,EAAc,KAAK,qBAAqB,EAAC,MAAM,iBAAiB,CAAC;AAwcxE,MAAM,WAAW,cAAe,SAAQ,SAAS,CAAC,cAAc,CAAC;IAC/D,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B;;;;;;;OAOG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC5B,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IACnB;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;;;;OAQG;IACH,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,SAAS,CAAC,EAAE,CACV,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,KACb;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAC,EAAE,CAAC;IAClD,aAAa,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;IAC5C;;;;;;OAMG;IACH,WAAW,CAAC,EAAE,qBAAqB,CAAC;CACrC;
|
|
1
|
+
{"version":3,"file":"CodeBlock.d.ts","sourceRoot":"","sources":["../../src/CodeBlock/CodeBlock.tsx"],"names":[],"mappings":"AAoBA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAgC5C,OAAO,EAAc,KAAK,qBAAqB,EAAC,MAAM,iBAAiB,CAAC;AAwcxE,MAAM,WAAW,cAAe,SAAQ,SAAS,CAAC,cAAc,CAAC;IAC/D,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B;;;;;;;OAOG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC5B,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IACnB;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;;;;OAQG;IACH,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,SAAS,CAAC,EAAE,CACV,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,KACb;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAC,EAAE,CAAC;IAClD,aAAa,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;IAC5C;;;;;;OAMG;IACH,WAAW,CAAC,EAAE,qBAAqB,CAAC;CACrC;AA0SD;;;;;;;;GAQG;AACH,wBAAgB,SAAS,CAAC,EACxB,IAAI,EACJ,QAAsB,EACtB,KAAK,EACL,gBAAuB,EACvB,cAAsB,EACtB,cAAc,EACd,MAAc,EACd,aAAoB,EACpB,MAAM,EACN,SAAiB,EACjB,SAAS,EACT,aAAqB,EACrB,oBAAyB,EACzB,IAAW,EACX,KAAK,EAAE,SAAyB,EAChC,SAAkB,EAClB,SAAS,EAAE,eAAe,EAC1B,aAAsB,EACtB,WAAW,EACX,MAAM,EACN,SAAS,EACT,KAAK,EACL,GAAG,EACH,GAAG,KAAK,EACT,EAAE,cAAc,qBAmRhB;yBA5Se,SAAS"}
|
|
@@ -487,11 +487,21 @@ function RangeCodeContent({
|
|
|
487
487
|
maxDigits
|
|
488
488
|
}) {
|
|
489
489
|
const codeRef = useRef(null);
|
|
490
|
+
|
|
491
|
+
// Insert the ::highlight() rules before the commit's layout reads, as the
|
|
492
|
+
// span path does. Inserted later, the new rules restyle the whole document
|
|
493
|
+
// a second time after any layout read in the same commit has already
|
|
494
|
+
// styled it, which on a long page full of code blocks costs a full style
|
|
495
|
+
// recalculation.
|
|
496
|
+
useInsertionEffect(() => {
|
|
497
|
+
if (hasHighlightAPI()) {
|
|
498
|
+
ensureHighlightStyles();
|
|
499
|
+
}
|
|
500
|
+
}, []);
|
|
490
501
|
useEffect(() => {
|
|
491
502
|
if (!hasHighlightAPI()) {
|
|
492
503
|
return;
|
|
493
504
|
}
|
|
494
|
-
ensureHighlightStyles();
|
|
495
505
|
const codeEl = codeRef.current;
|
|
496
506
|
if (!codeEl || tokenLines.length === 0) {
|
|
497
507
|
return;
|
|
@@ -43,12 +43,12 @@ export interface DateRangeInputProps extends Omit<FieldInputBaseProps<HTMLButton
|
|
|
43
43
|
/**
|
|
44
44
|
* Explains why the input is disabled. When set together with
|
|
45
45
|
* `isDisabled`, the input shows a tooltip with this text on hover and
|
|
46
|
-
* keyboard focus, and the trigger
|
|
47
|
-
*
|
|
48
|
-
*
|
|
46
|
+
* keyboard focus, and the trigger is described by it, so the reason is
|
|
47
|
+
* discoverable by keyboard and assistive technology. Activation stays
|
|
48
|
+
* blocked.
|
|
49
49
|
*
|
|
50
|
-
* Use this instead of wrapping a disabled input in `Tooltip
|
|
51
|
-
*
|
|
50
|
+
* Use this instead of wrapping a disabled input in `Tooltip`, so the
|
|
51
|
+
* reason is tied to the field.
|
|
52
52
|
*
|
|
53
53
|
* @example
|
|
54
54
|
* ```
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DateRangeInput.d.ts","sourceRoot":"","sources":["../../src/DateRangeInput/DateRangeInput.tsx"],"names":[],"mappings":"AA4CA,OAAO,EAGL,KAAK,WAAW,EAKhB,KAAK,kBAAkB,EACxB,MAAM,UAAU,CAAC;AAIlB,OAAO,EAEL,KAAK,aAAa,EAClB,KAAK,SAAS,EACd,KAAK,SAAS,EACd,KAAK,aAAa,EACnB,MAAM,aAAa,CAAC;AAOrB,OAAO,EAEL,KAAK,mBAAmB,EACzB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,gBAAgB,CAAC;AAU9C,YAAY,EAAC,SAAS,EAAC,MAAM,aAAa,CAAC;AAE3C,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,SAAS,CAAC;CAC3B;AAED,MAAM,MAAM,kBAAkB,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAEpD,YAAY,EACV,WAAW,IAAI,oBAAoB,EACnC,eAAe,IAAI,wBAAwB,GAC5C,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"DateRangeInput.d.ts","sourceRoot":"","sources":["../../src/DateRangeInput/DateRangeInput.tsx"],"names":[],"mappings":"AA4CA,OAAO,EAGL,KAAK,WAAW,EAKhB,KAAK,kBAAkB,EACxB,MAAM,UAAU,CAAC;AAIlB,OAAO,EAEL,KAAK,aAAa,EAClB,KAAK,SAAS,EACd,KAAK,SAAS,EACd,KAAK,aAAa,EACnB,MAAM,aAAa,CAAC;AAOrB,OAAO,EAEL,KAAK,mBAAmB,EACzB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,gBAAgB,CAAC;AAU9C,YAAY,EAAC,SAAS,EAAC,MAAM,aAAa,CAAC;AAE3C,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,SAAS,CAAC;CAC3B;AAED,MAAM,MAAM,kBAAkB,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAEpD,YAAY,EACV,WAAW,IAAI,oBAAoB,EACnC,eAAe,IAAI,wBAAwB,GAC5C,MAAM,UAAU,CAAC;AAuLlB,MAAM,WAAW,mBAAoB,SAAQ,IAAI,CAC/C,mBAAmB,CAAC,iBAAiB,CAAC,EACtC,UAAU,GAAG,cAAc,CAC5B;IACC,0CAA0C;IAC1C,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;IAEnC;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IAExB;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB;;OAEG;IACH,KAAK,EAAE,SAAS,GAAG,IAAI,CAAC;IAExB;;;OAGG;IACH,QAAQ,EAAE,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI,KAAK,IAAI,CAAC;IAE5C;;OAEG;IACH,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEjE;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB;;OAEG;IACH,GAAG,CAAC,EAAE,aAAa,CAAC;IAEpB;;OAEG;IACH,GAAG,CAAC,EAAE,aAAa,CAAC;IAEpB;;;OAGG;IACH,eAAe,CAAC,EAAE,aAAa,CAAC,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,CAAC;IAEzD;;;;;;;;;;;;OAYG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB;;;;;;;;OAQG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,aAAa,CAAC,eAAe,CAAC,CAAC;IAEzC;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;;OAGG;IACH,IAAI,CAAC,EAAE,kBAAkB,CAAC;IAE1B;;OAEG;IACH,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,kBAAkB,CAAC;IAEnC;;;;OAIG;IACH,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB;;;OAGG;IACH,cAAc,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC;IAEvB;;;;;OAKG;IACH,YAAY,CAAC,EAAE,SAAS,GAAG,aAAa,CAAC;CAC1C;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,cAAc,CAAC,EAC7B,KAAK,EACL,aAAqB,EACrB,WAAW,EACX,UAAkB,EAClB,UAAkB,EAClB,UAAkB,EAClB,eAAe,EACf,KAAK,EACL,QAAQ,EACR,YAAY,EACZ,SAAiB,EACjB,GAAG,EACH,GAAG,EACH,eAAe,EACf,YAAY,EACZ,YAAY,EACZ,OAAO,EACP,QAAe,EACf,WAAW,EAAE,oBAAoB,EACjC,IAAI,EAAE,QAAQ,EACd,MAAM,EACN,aAA0B,EAC1B,YAAY,EACZ,cAAkB,EAClB,YAAY,EACZ,KAAK,EACL,eAAe,EACf,kBAAkB,EAClB,cAAc,EACd,aAAa,EACb,gBAAgB,EAChB,YAAY,EACZ,GAAG,EACH,GAAG,SAAS,EACb,EAAE,mBAAmB,+BAqVrB;yBAxXe,cAAc"}
|
|
@@ -41,6 +41,11 @@ import { focusOutlineStyles } from "../utils/focusOutline.stylex.js";
|
|
|
41
41
|
import { useLocale, useTranslator } from "../i18n/index.js";
|
|
42
42
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
43
43
|
const styles = {
|
|
44
|
+
disabledFocusRing: {
|
|
45
|
+
kVAM5u: "xvy26l8 x6q1khz",
|
|
46
|
+
kGVxlE: "x1gnnqk1 xuihb5h",
|
|
47
|
+
$$css: true
|
|
48
|
+
},
|
|
44
49
|
iconButton: {
|
|
45
50
|
k1xSpc: "x78zum5",
|
|
46
51
|
kGNEyG: "x6s0dn4",
|
|
@@ -234,12 +239,12 @@ export function DateRangeInput({
|
|
|
234
239
|
const isBusy = isLoading || optimisticValue !== value;
|
|
235
240
|
const isEffectivelyDisabled = isDisabled || isBusy;
|
|
236
241
|
|
|
237
|
-
//
|
|
238
|
-
//
|
|
239
|
-
//
|
|
240
|
-
// disabled
|
|
241
|
-
//
|
|
242
|
-
//
|
|
242
|
+
// A disabled or busy field never renders native `disabled` (spec:AST-085
|
|
243
|
+
// FR1): its buttons stay focusable via aria-disabled, and activation is
|
|
244
|
+
// blocked by the isEffectivelyDisabled guard in handleToggle. The
|
|
245
|
+
// disabled-reason tooltip's listeners attach to the trigger container. Only
|
|
246
|
+
// the persistent isDisabled state (not the transient busy state) surfaces a
|
|
247
|
+
// reason.
|
|
243
248
|
const showsDisabledMessage = isDisabled && !!disabledMessage;
|
|
244
249
|
const disabledMessageTooltip = useTooltip({
|
|
245
250
|
placement: 'above',
|
|
@@ -343,11 +348,11 @@ export function DateRangeInput({
|
|
|
343
348
|
size,
|
|
344
349
|
status: status?.type ?? null,
|
|
345
350
|
disabled: isDisabled ? 'disabled' : null
|
|
346
|
-
}), stylex.props(inputWrapperStyles.base, sizeStyles[size], isEffectivelyDisabled && inputWrapperStyles.disabled, status && inputStatusBorderStyles[status.type], status && !isEffectivelyDisabled && inputStatusHoverShadowStyles[status.type], status && inputStatusFocusWithinStyles[status.type], controlXstyle), controlClassName, controlStyle),
|
|
351
|
+
}), stylex.props(inputWrapperStyles.base, sizeStyles[size], isEffectivelyDisabled && inputWrapperStyles.disabled, isEffectivelyDisabled && styles.disabledFocusRing, status && inputStatusBorderStyles[status.type], status && !isEffectivelyDisabled && inputStatusHoverShadowStyles[status.type], status && inputStatusFocusWithinStyles[status.type], controlXstyle), controlClassName, controlStyle),
|
|
347
352
|
children: [/*#__PURE__*/_jsx("button", {
|
|
348
353
|
type: "button",
|
|
349
354
|
onClick: handleToggle,
|
|
350
|
-
disabled: isEffectivelyDisabled,
|
|
355
|
+
"aria-disabled": isEffectivelyDisabled || undefined,
|
|
351
356
|
"aria-label": popover.isOpen ? t('@astryx.dateInput.toggleCalendarClose') : t('@astryx.dateInput.openCalendar'),
|
|
352
357
|
tabIndex: -1,
|
|
353
358
|
...stylex.props(focusOutlineStyles.focusVisible, styles.iconButton, isEffectivelyDisabled && styles.iconButtonDisabled),
|
|
@@ -363,14 +368,12 @@ export function DateRangeInput({
|
|
|
363
368
|
...controlProps,
|
|
364
369
|
ref: triggerButtonRef,
|
|
365
370
|
id: id,
|
|
366
|
-
type: "button"
|
|
367
|
-
|
|
368
|
-
//
|
|
369
|
-
// aria-disabled so the reason is focus-discoverable; activation is
|
|
370
|
-
// still blocked by the isEffectivelyDisabled guard in handleToggle.
|
|
371
|
+
type: "button"
|
|
372
|
+
// The browser still dispatches a click on an aria-disabled button,
|
|
373
|
+
// so a caller's onClick is skipped too (spec:AST-085 FR2).
|
|
371
374
|
,
|
|
372
|
-
|
|
373
|
-
"aria-disabled":
|
|
375
|
+
onClick: isEffectivelyDisabled ? undefined : chainEventHandlers(handleToggle, onClickProp),
|
|
376
|
+
"aria-disabled": isEffectivelyDisabled ? 'true' : undefined
|
|
374
377
|
// A caller aria-label replaces the trigger's name; a caller
|
|
375
378
|
// aria-labelledby is read after it (label and selected range).
|
|
376
379
|
,
|
|
@@ -433,9 +436,15 @@ export function DateRangeInput({
|
|
|
433
436
|
// marked with aria-current (not aria-selected, a listbox
|
|
434
437
|
// concept that contradicted the Tab interaction) (forms-5).
|
|
435
438
|
,
|
|
436
|
-
"aria-current": isActive ? 'true' : undefined
|
|
437
|
-
disabled:
|
|
438
|
-
|
|
439
|
+
"aria-current": isActive ? 'true' : undefined
|
|
440
|
+
// Focusable while disabled (AR3, spec:AST-085 FR1).
|
|
441
|
+
,
|
|
442
|
+
"aria-disabled": isPresetDisabled || undefined,
|
|
443
|
+
onClick: () => {
|
|
444
|
+
if (!isPresetDisabled) {
|
|
445
|
+
handleRangeSelect(presetRange);
|
|
446
|
+
}
|
|
447
|
+
},
|
|
439
448
|
...mergeProps(themeProps('date-range-input-preset', {
|
|
440
449
|
selected: isActive ? 'selected' : null,
|
|
441
450
|
disabled: isPresetDisabled ? 'disabled' : null
|
|
@@ -54,12 +54,12 @@ export interface DateTimeInputProps extends Omit<FieldInputBaseProps<HTMLInputEl
|
|
|
54
54
|
/**
|
|
55
55
|
* Explains why the input is disabled. When set together with
|
|
56
56
|
* `isDisabled`, the input shows a tooltip with this text on hover and
|
|
57
|
-
* keyboard focus, and the date and time fields
|
|
58
|
-
*
|
|
59
|
-
*
|
|
57
|
+
* keyboard focus, and the date and time fields are described by it, so the
|
|
58
|
+
* reason is discoverable by keyboard and assistive technology. Typing and
|
|
59
|
+
* calendar activation stay blocked.
|
|
60
60
|
*
|
|
61
|
-
* Use this instead of wrapping a disabled input in `Tooltip
|
|
62
|
-
*
|
|
61
|
+
* Use this instead of wrapping a disabled input in `Tooltip`, so the
|
|
62
|
+
* reason is tied to the field.
|
|
63
63
|
*
|
|
64
64
|
* @example
|
|
65
65
|
* ```
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DateTimeInput.d.ts","sourceRoot":"","sources":["../../src/DateTimeInput/DateTimeInput.tsx"],"names":[],"mappings":"AA4CA,OAAO,EAGL,KAAK,WAAW,EAKjB,MAAM,UAAU,CAAC;AAIlB,OAAO,EAIL,KAAK,SAAS,EACd,KAAK,aAAa,EACnB,MAAM,aAAa,CAAC;AA6BrB,OAAO,EAEL,KAAK,mBAAmB,EACzB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,gBAAgB,CAAC;AAc9C,OAAO,EAGL,KAAK,kBAAkB,EACxB,MAAM,4BAA4B,CAAC;AAEpC,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG;IACvC,QAAQ,CAAC,OAAO,EAAE,mBAAmB,CAAC;CACvC,CAAC;AAEF,qFAAqF;AACrF,MAAM,MAAM,yBAAyB,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC;AAErE,uGAAuG;AACvG,MAAM,MAAM,yBAAyB,GAAG,kBAAkB,CAAC;AAE3D,MAAM,MAAM,uBAAuB,GAAG,KAAK,GAAG,KAAK,CAAC;AAEpD,MAAM,MAAM,iBAAiB,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAEnD,4EAA4E;AAC5E,MAAM,MAAM,0BAA0B,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;AAE9D;;;GAGG;AACH,MAAM,MAAM,+BAA+B,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;AAEpE,YAAY,EACV,WAAW,IAAI,mBAAmB,EAClC,eAAe,IAAI,uBAAuB,GAC3C,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"DateTimeInput.d.ts","sourceRoot":"","sources":["../../src/DateTimeInput/DateTimeInput.tsx"],"names":[],"mappings":"AA4CA,OAAO,EAGL,KAAK,WAAW,EAKjB,MAAM,UAAU,CAAC;AAIlB,OAAO,EAIL,KAAK,SAAS,EACd,KAAK,aAAa,EACnB,MAAM,aAAa,CAAC;AA6BrB,OAAO,EAEL,KAAK,mBAAmB,EACzB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,gBAAgB,CAAC;AAc9C,OAAO,EAGL,KAAK,kBAAkB,EACxB,MAAM,4BAA4B,CAAC;AAEpC,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG;IACvC,QAAQ,CAAC,OAAO,EAAE,mBAAmB,CAAC;CACvC,CAAC;AAEF,qFAAqF;AACrF,MAAM,MAAM,yBAAyB,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC;AAErE,uGAAuG;AACvG,MAAM,MAAM,yBAAyB,GAAG,kBAAkB,CAAC;AAE3D,MAAM,MAAM,uBAAuB,GAAG,KAAK,GAAG,KAAK,CAAC;AAEpD,MAAM,MAAM,iBAAiB,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAEnD,4EAA4E;AAC5E,MAAM,MAAM,0BAA0B,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;AAE9D;;;GAGG;AACH,MAAM,MAAM,+BAA+B,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;AAEpE,YAAY,EACV,WAAW,IAAI,mBAAmB,EAClC,eAAe,IAAI,uBAAuB,GAC3C,MAAM,UAAU,CAAC;AAiKlB,MAAM,WAAW,kBAAmB,SAAQ,IAAI,CAC9C,mBAAmB,CAAC,gBAAgB,CAAC,EACrC,UAAU,GAAG,cAAc,CAC5B;IACC,8CAA8C;IAC9C,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;IAElC;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IAExB;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB;;OAEG;IACH,KAAK,CAAC,EAAE,iBAAiB,CAAC;IAE1B;;;OAGG;IACH,QAAQ,EAAE,CAAC,KAAK,EAAE,iBAAiB,GAAG,SAAS,KAAK,IAAI,CAAC;IAEzD;;OAEG;IACH,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,iBAAiB,GAAG,SAAS,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE9E;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB;;;OAGG;IACH,GAAG,CAAC,EAAE,iBAAiB,CAAC;IAExB;;;OAGG;IACH,GAAG,CAAC,EAAE,iBAAiB,CAAC;IAExB;;;OAGG;IACH,eAAe,CAAC,EAAE,aAAa,CAAC,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,CAAC;IAEzD;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;;OAGG;IACH,UAAU,CAAC,EAAE,uBAAuB,CAAC;IAErC;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,0BAA0B,CAAC;IAE3C;;;;;;;;;;;;;;;OAeG;IACH,kBAAkB,CAAC,EAAE,+BAA+B,CAAC;IAErD;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;OAGG;IACH,IAAI,CAAC,EAAE,iBAAiB,CAAC;IAEzB;;OAEG;IACH,MAAM,CAAC,EAAE,WAAW,CAAC;IAErB;;;;OAIG;IACH,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB;;;;;OAKG;IACH,cAAc,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC;IAEvB;;;;;OAKG;IACH,YAAY,CAAC,EAAE,SAAS,GAAG,aAAa,CAAC;IAEzC;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;IACH,YAAY,CAAC,EAAE,yBAAyB,CAAC;IAEzC;;;;;;;;;;;;;;;;;OAiBG;IACH,YAAY,CAAC,EAAE,yBAAyB,CAAC;CAC1C;AA06CD;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,kBAAkB,+BAqCtD;yBArCe,aAAa"}
|