@antscorp/ui 0.1.3 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (179) hide show
  1. package/README.md +25 -1
  2. package/dist/atoms/AddButton.d.ts +2 -5
  3. package/dist/atoms/Chip.d.ts +2 -5
  4. package/dist/atoms/Chip.js +1 -1
  5. package/dist/atoms/RemoveButton.d.ts +2 -5
  6. package/dist/atoms/TextAction.d.ts +2 -3
  7. package/dist/docs.json +1 -1
  8. package/dist/lib/iso.d.ts +2 -2
  9. package/dist/lib/iso.js +16 -8
  10. package/dist/lib/tokenEditorExtensions.js +1 -1
  11. package/dist/molecules/AccentCard.js +2 -2
  12. package/dist/molecules/CheckRow.d.ts +2 -7
  13. package/dist/molecules/ChoiceTiles.js +1 -1
  14. package/dist/molecules/CommitTextField.d.ts +1 -19
  15. package/dist/molecules/CommitTextField.js +21 -18
  16. package/dist/molecules/ConfirmDialog.d.ts +2 -7
  17. package/dist/molecules/DateTimeInput.d.ts +6 -3
  18. package/dist/molecules/DateTimeInput.js +82 -73
  19. package/dist/molecules/RemovableRow.js +32 -32
  20. package/dist/molecules/RevealRadioGroup.d.ts +2 -9
  21. package/dist/molecules/RevealSwitch.d.ts +2 -7
  22. package/dist/molecules/Select.d.ts +7 -23
  23. package/dist/molecules/Select.js +26 -20
  24. package/dist/molecules/StatusButton.d.ts +2 -7
  25. package/dist/molecules/TreeOptions.d.ts +3 -2
  26. package/dist/molecules/TreeOptions.js +67 -44
  27. package/dist/organisms/HourOfDayRow.js +2 -2
  28. package/dist/organisms/HourOfWeekGrid.js +2 -2
  29. package/dist/organisms/TreeSearchPanel.js +50 -47
  30. package/dist/ui.css +1 -1
  31. package/package.json +23 -17
  32. package/src/atoms/AddButton.tsx +2 -6
  33. package/src/atoms/Chip.tsx +5 -7
  34. package/src/atoms/RemoveButton.tsx +2 -6
  35. package/src/atoms/TextAction.tsx +2 -4
  36. package/src/lib/iso.ts +15 -3
  37. package/src/lib/tokenEditorExtensions.ts +1 -1
  38. package/src/molecules/AccentCard.tsx +4 -2
  39. package/src/molecules/CheckRow.tsx +2 -8
  40. package/src/molecules/ChoiceTiles.tsx +3 -1
  41. package/src/molecules/CommitTextField.tsx +15 -20
  42. package/src/molecules/ConfirmDialog.tsx +2 -8
  43. package/src/molecules/DateTimeInput.tsx +86 -68
  44. package/src/molecules/RemovableRow.tsx +1 -1
  45. package/src/molecules/RevealRadioGroup.tsx +5 -10
  46. package/src/molecules/RevealSwitch.tsx +2 -8
  47. package/src/molecules/Select.tsx +22 -22
  48. package/src/molecules/StatusButton.tsx +2 -8
  49. package/src/molecules/TreeOptions.tsx +86 -62
  50. package/src/organisms/HourOfDayRow.tsx +4 -2
  51. package/src/organisms/HourOfWeekGrid.tsx +4 -2
  52. package/src/organisms/TreeSearchPanel.tsx +1 -1
  53. package/dist/atoms/AddButton.doc.d.ts +0 -21
  54. package/dist/atoms/AddGlyph.doc.d.ts +0 -16
  55. package/dist/atoms/Chip.doc.d.ts +0 -29
  56. package/dist/atoms/ChipSkeletons.doc.d.ts +0 -21
  57. package/dist/atoms/FieldHeading.doc.d.ts +0 -15
  58. package/dist/atoms/HoverSwap.doc.d.ts +0 -25
  59. package/dist/atoms/InfoTip.doc.d.ts +0 -25
  60. package/dist/atoms/JointLabel.doc.d.ts +0 -15
  61. package/dist/atoms/LabeledDivider.doc.d.ts +0 -21
  62. package/dist/atoms/LogoImage.doc.d.ts +0 -21
  63. package/dist/atoms/PanelSearchInput.doc.d.ts +0 -25
  64. package/dist/atoms/PathMark.doc.d.ts +0 -16
  65. package/dist/atoms/RemoveButton.doc.d.ts +0 -16
  66. package/dist/atoms/RowSkeletons.doc.d.ts +0 -25
  67. package/dist/atoms/TextAction.doc.d.ts +0 -25
  68. package/dist/atoms/TruncatedOption.doc.d.ts +0 -24
  69. package/dist/atoms/TruncatedText.doc.d.ts +0 -15
  70. package/dist/molecules/AccentCard.doc.d.ts +0 -25
  71. package/dist/molecules/CheckGroup.doc.d.ts +0 -25
  72. package/dist/molecules/CheckRow.doc.d.ts +0 -25
  73. package/dist/molecules/ChoiceDialog.doc.d.ts +0 -21
  74. package/dist/molecules/ChoiceTiles.doc.d.ts +0 -21
  75. package/dist/molecules/CommitTextField.doc.d.ts +0 -29
  76. package/dist/molecules/ConfirmDialog.doc.d.ts +0 -21
  77. package/dist/molecules/DateTimeInput.doc.d.ts +0 -25
  78. package/dist/molecules/DurationInput.doc.d.ts +0 -25
  79. package/dist/molecules/FieldGroup.doc.d.ts +0 -25
  80. package/dist/molecules/FieldRow.doc.d.ts +0 -24
  81. package/dist/molecules/FieldSkeleton.doc.d.ts +0 -25
  82. package/dist/molecules/FrequencyLimitRow.doc.d.ts +0 -25
  83. package/dist/molecules/InlineEditableText.doc.d.ts +0 -25
  84. package/dist/molecules/LoadMoreRow.doc.d.ts +0 -21
  85. package/dist/molecules/LoadState.doc.d.ts +0 -21
  86. package/dist/molecules/MetaTable.doc.d.ts +0 -25
  87. package/dist/molecules/PercentRow.doc.d.ts +0 -25
  88. package/dist/molecules/PhoneFrame.doc.d.ts +0 -21
  89. package/dist/molecules/ProblemsButton.doc.d.ts +0 -25
  90. package/dist/molecules/RemovableRow.doc.d.ts +0 -25
  91. package/dist/molecules/RevealRadioGroup.doc.d.ts +0 -25
  92. package/dist/molecules/RevealSwitch.doc.d.ts +0 -25
  93. package/dist/molecules/RuleRow.doc.d.ts +0 -25
  94. package/dist/molecules/Select.doc.d.ts +0 -30
  95. package/dist/molecules/SideLabelRow.doc.d.ts +0 -20
  96. package/dist/molecules/SplitButton.doc.d.ts +0 -25
  97. package/dist/molecules/StatusButton.doc.d.ts +0 -25
  98. package/dist/molecules/TagSelect.doc.d.ts +0 -25
  99. package/dist/molecules/ToggleGrid.doc.d.ts +0 -25
  100. package/dist/molecules/TokenTextField.doc.d.ts +0 -29
  101. package/dist/molecules/TransferLayout.doc.d.ts +0 -25
  102. package/dist/molecules/TreeOptions.doc.d.ts +0 -25
  103. package/dist/organisms/ChipListAddPopover.doc.d.ts +0 -25
  104. package/dist/organisms/HourOfDayRow.doc.d.ts +0 -25
  105. package/dist/organisms/HourOfWeekGrid.doc.d.ts +0 -25
  106. package/dist/organisms/RepeatableList.doc.d.ts +0 -21
  107. package/dist/organisms/ResizableDrawer.doc.d.ts +0 -25
  108. package/dist/organisms/RuleGroups.doc.d.ts +0 -21
  109. package/dist/organisms/RuleList.doc.d.ts +0 -25
  110. package/dist/organisms/SearchableGroupedList.doc.d.ts +0 -25
  111. package/dist/organisms/TokenPickerDialog.doc.d.ts +0 -21
  112. package/dist/organisms/TransferPicker.doc.d.ts +0 -29
  113. package/dist/organisms/TreeSearchPanel.doc.d.ts +0 -25
  114. package/dist/organisms/TreeSelect.doc.d.ts +0 -29
  115. package/dist/theme/AntsomiTheme.doc.d.ts +0 -15
  116. package/dist/theme/AntsomiTheme.doc.js +0 -22
  117. package/src/atoms/AddButton.doc.ts +0 -36
  118. package/src/atoms/AddGlyph.doc.ts +0 -26
  119. package/src/atoms/Chip.doc.ts +0 -45
  120. package/src/atoms/ChipSkeletons.doc.ts +0 -31
  121. package/src/atoms/FieldHeading.doc.ts +0 -22
  122. package/src/atoms/HoverSwap.doc.ts +0 -39
  123. package/src/atoms/InfoTip.doc.ts +0 -37
  124. package/src/atoms/JointLabel.doc.ts +0 -23
  125. package/src/atoms/LabeledDivider.doc.ts +0 -35
  126. package/src/atoms/LogoImage.doc.ts +0 -42
  127. package/src/atoms/PanelSearchInput.doc.ts +0 -41
  128. package/src/atoms/PathMark.doc.ts +0 -25
  129. package/src/atoms/RemoveButton.doc.ts +0 -26
  130. package/src/atoms/RowSkeletons.doc.ts +0 -43
  131. package/src/atoms/TextAction.doc.ts +0 -40
  132. package/src/atoms/TruncatedOption.doc.ts +0 -39
  133. package/src/atoms/TruncatedText.doc.ts +0 -22
  134. package/src/molecules/AccentCard.doc.ts +0 -43
  135. package/src/molecules/CheckGroup.doc.ts +0 -40
  136. package/src/molecules/CheckRow.doc.ts +0 -43
  137. package/src/molecules/ChoiceDialog.doc.ts +0 -48
  138. package/src/molecules/ChoiceTiles.doc.ts +0 -42
  139. package/src/molecules/CommitTextField.doc.ts +0 -41
  140. package/src/molecules/ConfirmDialog.doc.ts +0 -43
  141. package/src/molecules/DateTimeInput.doc.ts +0 -48
  142. package/src/molecules/DurationInput.doc.ts +0 -36
  143. package/src/molecules/FieldGroup.doc.ts +0 -41
  144. package/src/molecules/FieldRow.doc.ts +0 -36
  145. package/src/molecules/FieldSkeleton.doc.ts +0 -38
  146. package/src/molecules/FrequencyLimitRow.doc.ts +0 -48
  147. package/src/molecules/InlineEditableText.doc.ts +0 -41
  148. package/src/molecules/LoadMoreRow.doc.ts +0 -36
  149. package/src/molecules/LoadState.doc.ts +0 -42
  150. package/src/molecules/MetaTable.doc.ts +0 -46
  151. package/src/molecules/PercentRow.doc.ts +0 -48
  152. package/src/molecules/PhoneFrame.doc.ts +0 -46
  153. package/src/molecules/ProblemsButton.doc.ts +0 -41
  154. package/src/molecules/RemovableRow.doc.ts +0 -48
  155. package/src/molecules/RevealRadioGroup.doc.ts +0 -41
  156. package/src/molecules/RevealSwitch.doc.ts +0 -38
  157. package/src/molecules/RuleRow.doc.ts +0 -43
  158. package/src/molecules/Select.doc.ts +0 -62
  159. package/src/molecules/SideLabelRow.doc.ts +0 -35
  160. package/src/molecules/SplitButton.doc.ts +0 -41
  161. package/src/molecules/StatusButton.doc.ts +0 -39
  162. package/src/molecules/TagSelect.doc.ts +0 -41
  163. package/src/molecules/ToggleGrid.doc.ts +0 -43
  164. package/src/molecules/TokenTextField.doc.ts +0 -41
  165. package/src/molecules/TransferLayout.doc.ts +0 -42
  166. package/src/molecules/TreeOptions.doc.ts +0 -38
  167. package/src/organisms/ChipListAddPopover.doc.ts +0 -54
  168. package/src/organisms/HourOfDayRow.doc.ts +0 -43
  169. package/src/organisms/HourOfWeekGrid.doc.ts +0 -48
  170. package/src/organisms/RepeatableList.doc.ts +0 -49
  171. package/src/organisms/ResizableDrawer.doc.ts +0 -48
  172. package/src/organisms/RuleGroups.doc.ts +0 -49
  173. package/src/organisms/RuleList.doc.ts +0 -43
  174. package/src/organisms/SearchableGroupedList.doc.ts +0 -49
  175. package/src/organisms/TokenPickerDialog.doc.ts +0 -54
  176. package/src/organisms/TransferPicker.doc.ts +0 -69
  177. package/src/organisms/TreeSearchPanel.doc.ts +0 -43
  178. package/src/organisms/TreeSelect.doc.ts +0 -56
  179. package/src/theme/AntsomiTheme.doc.ts +0 -23
@@ -1,19 +1,13 @@
1
- import { Switch } from "@astryxdesign/core/Switch";
1
+ import { Switch, type SwitchProps } from "@astryxdesign/core/Switch";
2
2
  import { VStack } from "@astryxdesign/core/VStack";
3
3
  import type { ReactNode } from "react";
4
4
 
5
5
  /** What `RevealSwitch` takes. */
6
- export type RevealSwitchProps = {
7
- /** What the switch turns on. */
8
- readonly label: string;
9
- /** Whether the switch is on. */
10
- readonly value: boolean;
6
+ export type RevealSwitchProps = Pick<SwitchProps, "label" | "isDisabled" | "value"> & {
11
7
  /** Called with the new state. */
12
8
  readonly onChange: (value: boolean) => void;
13
9
  /** The switch's size, `md` by default. */
14
10
  readonly size?: "sm" | "md" | undefined;
15
- /** Dims the switch and blocks it. */
16
- readonly isDisabled?: boolean | undefined;
17
11
  /** Shows the value, not dimmed, and ignores changes. */
18
12
  readonly isReadOnly?: boolean | undefined;
19
13
  /** What shows below the switch while it is on. */
@@ -2,6 +2,7 @@ import {
2
2
  Selector,
3
3
  type SelectorOptionData,
4
4
  type SelectorOptionType,
5
+ type SelectorProps,
5
6
  } from "@astryxdesign/core/Selector";
6
7
  import type { ReactNode } from "react";
7
8
 
@@ -13,13 +14,20 @@ import { useLoadingShown } from "../lib/useLoadingShown";
13
14
  export type SelectOption = SelectorOptionType;
14
15
 
15
16
  /** What `Select` takes. */
16
- export type SelectProps = {
17
- /** Names the control for assistive tech; shown above it unless `isLabelHidden`. */
18
- readonly label: string;
19
- /** Hides the label, as in a rule row. */
20
- readonly isLabelHidden?: boolean | undefined;
21
- /** A line under the label that explains the choice. */
22
- readonly description?: string | undefined;
17
+ export type SelectProps = Pick<
18
+ SelectorProps,
19
+ | "label"
20
+ | "isLabelHidden"
21
+ | "description"
22
+ | "placeholder"
23
+ | "hasSearch"
24
+ | "width"
25
+ | "isDisabled"
26
+ | "isReadOnly"
27
+ | "isRequired"
28
+ | "controlXstyle"
29
+ | "containerXstyle"
30
+ > & {
23
31
  /** The list, in order. */
24
32
  readonly options: readonly SelectOption[];
25
33
  /** The picked option's value; `null` or none shows the placeholder. */
@@ -28,22 +36,10 @@ export type SelectProps = {
28
36
  readonly onChange: (value: string) => void;
29
37
  /** Called by the clear button, which shows only when this is given and an option is picked. */
30
38
  readonly onClear?: (() => void) | undefined;
31
- /** Shown in the trigger while nothing is picked. */
32
- readonly placeholder?: string | undefined;
33
- /** A search box over the list, filtering it as it is typed. */
34
- readonly hasSearch?: boolean | undefined;
35
39
  /** The trigger's look: an underlined field (`input`, the default) or a bare text button (`ghost`). */
36
40
  readonly variant?: "input" | "ghost" | undefined;
37
- /** The trigger's size, `md` by default (the theme's 30px control height). */
38
- readonly size?: "sm" | "md" | undefined;
39
- /** The trigger's width, in pixels or any CSS length such as `"100%"`. */
40
- readonly width?: number | string | undefined;
41
- /** Dims the trigger and blocks it. */
42
- readonly isDisabled?: boolean | undefined;
43
- /** Shows the picked label without the chevron; the list does not open. */
44
- readonly isReadOnly?: boolean | undefined;
45
- /** Marks the field as required. */
46
- readonly isRequired?: boolean | undefined;
41
+ /** The trigger's size, md by default; the kit narrows the upstream sizes to sm and md. */
42
+ readonly size?: Extract<SelectorProps["size"], "sm" | "md"> | undefined;
47
43
  /**
48
44
  * The options are loading: a spinner in place of the chevron and the trigger busy from 300 ms
49
45
  * on, for at least 300 ms (`useLoadingShown`), and the list does not open meanwhile. The picked
@@ -53,7 +49,7 @@ export type SelectProps = {
53
49
  readonly isLoading?: boolean | undefined;
54
50
  /** A problem with the pick, already in the user's language, shown under the trigger. */
55
51
  readonly error?: string | undefined;
56
- /** The texts the view shows; the host translates them. Astryx's English stands in for a missing one. */
52
+ /** Host texts; missing strings use the facade's InternationalizationProvider locale (English by default). */
57
53
  readonly labels?:
58
54
  | {
59
55
  /** The search box's placeholder, such as "Search". */
@@ -72,6 +68,8 @@ export type SelectProps = {
72
68
  * The kit's select on Astryx's `Selector`: the list is as wide as the
73
69
  * trigger (the theme) and a long option label ends in an ellipsis with the whole label in a
74
70
  * tooltip. Every select is one rather than Astryx's `Selector` (lint-enforced). It holds no state.
71
+ * Localize upstream search, clear and empty text with `InternationalizationProvider` from
72
+ * `@antscorp/ui/astryx/i18n`; `labels` overrides individual kit captions.
75
73
  */
76
74
  export function Select(props: SelectProps): ReactNode {
77
75
  const { labels = {}, onClear, onChange } = props;
@@ -106,6 +104,8 @@ export function Select(props: SelectProps): ReactNode {
106
104
  ...(props.isDisabled !== undefined && { isDisabled: props.isDisabled }),
107
105
  ...(props.isReadOnly !== undefined && !isBusy && { isReadOnly: props.isReadOnly }),
108
106
  ...(props.isRequired !== undefined && { isRequired: props.isRequired }),
107
+ ...(props.controlXstyle !== undefined && { controlXstyle: props.controlXstyle }),
108
+ ...(props.containerXstyle !== undefined && { containerXstyle: props.containerXstyle }),
109
109
  ...(labels.search !== undefined && { searchPlaceholder: labels.search }),
110
110
  ...(labels.noMatch !== undefined && { emptySearchText: labels.noMatch }),
111
111
  };
@@ -1,4 +1,4 @@
1
- import { Button } from "@astryxdesign/core/Button";
1
+ import { Button, type ButtonProps } from "@astryxdesign/core/Button";
2
2
  import { StatusDot } from "@astryxdesign/core/StatusDot";
3
3
  import type { ComponentProps, ReactNode } from "react";
4
4
 
@@ -6,9 +6,7 @@ import type { ComponentProps, ReactNode } from "react";
6
6
  export type StatusTone = ComponentProps<typeof StatusDot>["variant"];
7
7
 
8
8
  /** What `StatusButton` takes. */
9
- export type StatusButtonProps = {
10
- /** The button's text. */
11
- readonly label: string;
9
+ export type StatusButtonProps = Pick<ButtonProps, "label" | "icon" | "isDisabled"> & {
12
10
  /** The dot's tone: neutral, accent, success, warning or error. */
13
11
  readonly status: StatusTone;
14
12
  /** The texts the view shows; the host translates them. */
@@ -16,14 +14,10 @@ export type StatusButtonProps = {
16
14
  /** What the dot means, read out for it, e.g. "Connected". */
17
15
  readonly status: string;
18
16
  };
19
- /** A glyph before the text. */
20
- readonly icon?: ReactNode;
21
17
  /** Called when the button is pressed. */
22
18
  readonly onClick: () => void;
23
19
  /** The button's height, `md` by default. */
24
20
  readonly size?: "sm" | "md" | undefined;
25
- /** Dimmed and not pressable. */
26
- readonly isDisabled?: boolean | undefined;
27
21
  };
28
22
 
29
23
  /** A button whose dot shows a state beside its text, such as a connection. */
@@ -1,3 +1,4 @@
1
+ import { useTreeFocus } from "@astryxdesign/core/hooks";
1
2
  import { Icon } from "@astryxdesign/core/Icon";
2
3
  import { useIndicator } from "@astryxdesign/core/Indicator";
3
4
  import { Text } from "@astryxdesign/core/Text";
@@ -9,7 +10,7 @@ import {
9
10
  } from "@astryxdesign/core/theme/tokens.stylex";
10
11
  import { themeProps } from "@astryxdesign/core/utils";
11
12
  import * as stylex from "@stylexjs/stylex";
12
- import { type KeyboardEvent, type ReactNode, useState } from "react";
13
+ import { Fragment, type ReactNode, useId, useState } from "react";
13
14
 
14
15
  /** One row of a two-level tree to pick from: a leaf, or a group of leaves. */
15
16
  export type TreeItem = {
@@ -58,12 +59,15 @@ type Row = {
58
59
  * disabled row does neither. Rows are the Selector's option rows (its styles, its option-row and
59
60
  * check theme targets, its check on the picked leaf at the end, where a group shows its chevron),
60
61
  * so a theme styles both alike: the picked row's look and whether a check shows are the theme's.
61
- * Tab reaches the picked leaf (else the first enabled row), Up and Down move between rows, Enter
62
- * and Space act. Its state is which groups are open.
62
+ * Tab initially reaches the picked leaf (else the first enabled row); arrows, Home and End move
63
+ * through enabled rows, Right opens or enters a group, Left collapses or returns to its parent,
64
+ * and Enter and Space act. Its state is which groups are open and which row has focus.
63
65
  */
64
66
  export function TreeOptions(props: TreeOptionsProps): ReactNode {
65
67
  const { items, value } = props;
66
68
  const size = props.size ?? "md";
69
+ const id = useId();
70
+ const [active, setActive] = useState<string>();
67
71
  const [open, setOpen] = useState<ReadonlySet<string>>(
68
72
  () =>
69
73
  new Set(
@@ -87,7 +91,9 @@ export function TreeOptions(props: TreeOptionsProps): ReactNode {
87
91
  const Check = useIndicator("check");
88
92
  const enabled = rows.filter((row) => row.item.isDisabled !== true);
89
93
  const tabbable =
90
- enabled.find((row) => row.isOpen === undefined && row.item.value === value) ?? enabled[0];
94
+ enabled.find((row) => row.item.value === active) ??
95
+ enabled.find((row) => row.isOpen === undefined && row.item.value === value) ??
96
+ enabled[0];
91
97
  const act = (row: Row): void => {
92
98
  if (row.item.isDisabled === true) return;
93
99
  if (row.isOpen === undefined) {
@@ -98,56 +104,84 @@ export function TreeOptions(props: TreeOptionsProps): ReactNode {
98
104
  if (!next.delete(row.item.value)) next.add(row.item.value);
99
105
  setOpen(next);
100
106
  };
101
- return (
102
- // Raw elements: a flat tree (rows with `aria-level`), which Astryx's TreeList is not: it puts
103
- // a group's chevron first; this tree puts it at the end.
104
- <div role="tree" aria-label={props.label} onKeyDown={moveFocus}>
105
- {rows.map((row) => (
106
- <div
107
- key={row.item.value}
108
- role="treeitem"
109
- aria-level={row.level}
110
- aria-expanded={row.isOpen}
111
- aria-selected={row.isOpen === undefined ? row.item.value === value : undefined}
112
- aria-disabled={row.item.isDisabled === true || undefined}
113
- tabIndex={row === tabbable ? 0 : -1}
114
- onClick={() => {
115
- act(row);
116
- }}
117
- onKeyDown={(event) => {
118
- if (event.key !== "Enter" && event.key !== " ") return;
119
- event.preventDefault();
120
- act(row);
121
- }}
122
- {...rowProps(row, size, value)}
123
- >
124
- {/* The option's content and mark column, as `Selector.tsx:1407-1431`. */}
125
- {/* One line cut with an ellipsis, with Text's tooltip for the whole label;
107
+ const activate = (key: string | undefined): void => {
108
+ const row = rows.find((candidate) => candidate.item.value === key);
109
+ if (row !== undefined) act(row);
110
+ };
111
+ const { treeRef, handleKeyDown } = useTreeFocus({
112
+ itemSelector: '[role="treeitem"]:not([aria-disabled="true"])',
113
+ onToggleExpand: activate,
114
+ onActivate: (_item, key) => {
115
+ activate(key);
116
+ return true;
117
+ },
118
+ });
119
+ const groupId = (row: Row): string => `${id}-${encodeURIComponent(row.item.value)}`;
120
+ const renderRow = (row: Row): ReactNode => (
121
+ <div
122
+ key={row.item.value}
123
+ role="treeitem"
124
+ aria-label={row.item.label}
125
+ data-tree-id={row.item.value}
126
+ aria-level={row.level}
127
+ aria-expanded={row.isOpen}
128
+ aria-owns={row.isOpen === true ? groupId(row) : undefined}
129
+ aria-selected={row.isOpen === undefined ? row.item.value === value : undefined}
130
+ aria-disabled={row.item.isDisabled === true || undefined}
131
+ tabIndex={row.item === tabbable?.item ? 0 : -1}
132
+ onFocus={() => {
133
+ setActive(row.item.value);
134
+ }}
135
+ onClick={() => {
136
+ act(row);
137
+ }}
138
+ {...rowProps(row, size, value)}
139
+ >
140
+ {/* The option's content and mark column, as `Selector.tsx:1407-1431`. */}
141
+ {/* One line cut with an ellipsis, with Text's tooltip for the whole label;
126
142
  Astryx's SelectorOption would run under the mark. */}
127
- <span {...stylex.props(styles.content)}>
128
- <Text type="inherit" color="inherit" maxLines={1}>
129
- {row.item.label}
130
- </Text>
131
- </span>
132
- {/* A leaf's column sets no display of its own: the theme may hide it with its check. */}
133
- <span {...stylex.props(styles.mark, row.isOpen !== undefined && styles.markCentred)}>
134
- {row.isOpen === undefined ? (
135
- <Check
136
- state={row.item.value === value ? "checked" : "unchecked"}
137
- size="sm"
138
- isDisabled={row.item.isDisabled === true}
139
- {...themeProps("selector-check")}
140
- />
141
- ) : (
142
- <Icon
143
- icon={row.isOpen ? "chevronDown" : "chevronRight"}
144
- size="sm"
145
- color="secondary"
146
- />
143
+ <span {...stylex.props(styles.content)}>
144
+ <Text type="inherit" color="inherit" maxLines={1}>
145
+ {row.item.label}
146
+ </Text>
147
+ </span>
148
+ {/* A leaf's column sets no display of its own: the theme may hide it with its check. */}
149
+ <span {...stylex.props(styles.mark, row.isOpen !== undefined && styles.markCentred)}>
150
+ {row.isOpen === undefined ? (
151
+ <Check
152
+ state={row.item.value === value ? "checked" : "unchecked"}
153
+ size="sm"
154
+ isDisabled={row.item.isDisabled === true}
155
+ {...themeProps("selector-check")}
156
+ />
157
+ ) : (
158
+ <Icon icon={row.isOpen ? "chevronDown" : "chevronRight"} size="sm" color="secondary" />
159
+ )}
160
+ </span>
161
+ </div>
162
+ );
163
+ return (
164
+ // Raw tree roles preserve the trailing chevron layout; each parent owns its sibling group.
165
+ <div
166
+ role="tree"
167
+ aria-label={props.label}
168
+ ref={(element) => {
169
+ treeRef.current = element;
170
+ }}
171
+ onKeyDown={handleKeyDown}
172
+ >
173
+ {rows
174
+ .filter((row) => row.level === 1)
175
+ .map((row) => (
176
+ <Fragment key={row.item.value}>
177
+ {renderRow(row)}
178
+ {row.isOpen === true && (
179
+ <div role="group" id={groupId(row)}>
180
+ {row.item.children?.map((child) => renderRow({ item: child, level: 2 }))}
181
+ </div>
147
182
  )}
148
- </span>
149
- </div>
150
- ))}
183
+ </Fragment>
184
+ ))}
151
185
  </div>
152
186
  );
153
187
  }
@@ -178,16 +212,6 @@ function rowProps(
178
212
  };
179
213
  }
180
214
 
181
- // Up and Down move the keyboard to the row above or below.
182
- function moveFocus(event: KeyboardEvent<HTMLDivElement>): void {
183
- const step = event.key === "ArrowDown" ? 1 : event.key === "ArrowUp" ? -1 : 0;
184
- if (step === 0) return;
185
- event.preventDefault();
186
- const rows = [...event.currentTarget.querySelectorAll<HTMLElement>('[role="treeitem"]')];
187
- const at = rows.findIndex((row) => row === event.target);
188
- rows[Math.min(Math.max(at + step, 0), rows.length - 1)]?.focus();
189
- }
190
-
191
215
  // Astryx `Selector/Selector.tsx` styles: `item` (345-366, without its radius), `itemContent`
192
216
  // (367-373), `itemMarkColumn` (379-389), `itemHighlighted` (395-397, here on hover and keyboard
193
217
  // focus, as the rows take focus, never on the picked row), `itemDisabled` (401-404) and
@@ -1,3 +1,4 @@
1
+ import type { AccentRole } from "@antscorp/astryx-theme-antsomi/palette";
1
2
  import { FieldStatus } from "@astryxdesign/core/FieldStatus";
2
3
  import { ScrollableArea } from "@astryxdesign/core/ScrollableArea";
3
4
  import { colorVars } from "@astryxdesign/core/theme/tokens.stylex";
@@ -115,6 +116,7 @@ export function HourOfDayRow(props: HourOfDayRowProps): ReactNode {
115
116
  }
116
117
 
117
118
  // As the week grid's: 24px cells, 11px text.
119
+ const accentHover: AccentRole = "var(--ants-accent-hover)";
118
120
  const styles = stylex.create({
119
121
  grid: { width: "max-content", userSelect: "none", cursor: "pointer" },
120
122
  locked: { cursor: "default" },
@@ -138,13 +140,13 @@ const styles = stylex.create({
138
140
  liveOn: {
139
141
  backgroundColor: {
140
142
  default: colorVars["--color-accent"],
141
- ":hover": { default: null, "@media (hover: hover)": "var(--ants-mh-blue-50)" },
143
+ ":hover": { default: null, "@media (hover: hover)": accentHover },
142
144
  },
143
145
  },
144
146
  liveOff: {
145
147
  backgroundColor: {
146
148
  default: colorVars["--color-neutral"],
147
- ":hover": { default: null, "@media (hover: hover)": "var(--ants-mh-blue-50)" },
149
+ ":hover": { default: null, "@media (hover: hover)": accentHover },
148
150
  },
149
151
  },
150
152
  axis: { color: colorVars["--color-text-secondary"], fontSize: 11, whiteSpace: "nowrap" },
@@ -1,3 +1,4 @@
1
+ import type { AccentRole } from "@antscorp/astryx-theme-antsomi/palette";
1
2
  import { FieldStatus } from "@astryxdesign/core/FieldStatus";
2
3
  import { ScrollableArea } from "@astryxdesign/core/ScrollableArea";
3
4
  import { Text } from "@astryxdesign/core/Text";
@@ -239,6 +240,7 @@ export function HourOfWeekGrid(props: HourOfWeekGridProps): ReactNode {
239
240
  }
240
241
 
241
242
  // Sizes follow the form it came from: 24px cells, a 76px column of day names, 11px text.
243
+ const accentHover: AccentRole = "var(--ants-accent-hover)";
242
244
  const styles = stylex.create({
243
245
  // Every cell picks, as in the form it came from; the cells inherit it.
244
246
  grid: { width: "max-content", userSelect: "none", cursor: "pointer" },
@@ -288,13 +290,13 @@ const styles = stylex.create({
288
290
  liveOn: {
289
291
  backgroundColor: {
290
292
  default: colorVars["--color-accent"],
291
- ":hover": { default: null, "@media (hover: hover)": "var(--ants-mh-blue-50)" },
293
+ ":hover": { default: null, "@media (hover: hover)": accentHover },
292
294
  },
293
295
  },
294
296
  liveOff: {
295
297
  backgroundColor: {
296
298
  default: colorVars["--color-neutral"],
297
- ":hover": { default: null, "@media (hover: hover)": "var(--ants-mh-blue-50)" },
299
+ ":hover": { default: null, "@media (hover: hover)": accentHover },
298
300
  },
299
301
  },
300
302
  axis: {
@@ -64,7 +64,7 @@ export function TreeSearchPanel(props: TreeSearchPanelProps): ReactNode {
64
64
  const { rootRef, sentinelRef } = useLoadMore({
65
65
  ...more,
66
66
  hasLoadMoreError: labels.loadMoreError !== undefined,
67
- itemCount: shown.length,
67
+ itemCount: shown.reduce((count, item) => count + 1 + (item.children?.length ?? 0), 0),
68
68
  });
69
69
  const groups = shown.filter((item) => item.children !== undefined).length;
70
70
  return (
@@ -1,21 +0,0 @@
1
- /** Usage guidance for AddButton. */
2
- export declare const doc: {
3
- category: "Inputs";
4
- keywords: string[];
5
- usage: {
6
- description: string;
7
- bestPractices: ({
8
- guidance: true;
9
- description: string;
10
- } | {
11
- guidance: false;
12
- description: string;
13
- })[];
14
- anatomy: {
15
- name: string;
16
- required: true;
17
- description: string;
18
- }[];
19
- };
20
- accessibility: string[];
21
- };
@@ -1,16 +0,0 @@
1
- /** Usage guidance for AddGlyph. */
2
- export declare const doc: {
3
- category: "Data display";
4
- keywords: string[];
5
- usage: {
6
- description: string;
7
- bestPractices: ({
8
- guidance: true;
9
- description: string;
10
- } | {
11
- guidance: false;
12
- description: string;
13
- })[];
14
- };
15
- accessibility: string[];
16
- };
@@ -1,29 +0,0 @@
1
- /** Usage guidance for Chip. */
2
- export declare const doc: {
3
- category: "Data display";
4
- keywords: string[];
5
- related: {
6
- name: string;
7
- when: string;
8
- }[];
9
- usage: {
10
- description: string;
11
- bestPractices: ({
12
- guidance: true;
13
- description: string;
14
- } | {
15
- guidance: false;
16
- description: string;
17
- })[];
18
- anatomy: ({
19
- name: string;
20
- required: true;
21
- description: string;
22
- } | {
23
- name: string;
24
- required: false;
25
- description: string;
26
- })[];
27
- };
28
- accessibility: string[];
29
- };
@@ -1,21 +0,0 @@
1
- /** Usage guidance for ChipSkeletons. */
2
- export declare const doc: {
3
- category: "Feedback";
4
- keywords: string[];
5
- usage: {
6
- description: string;
7
- bestPractices: ({
8
- guidance: true;
9
- description: string;
10
- } | {
11
- guidance: false;
12
- description: string;
13
- })[];
14
- anatomy: {
15
- name: string;
16
- required: true;
17
- description: string;
18
- }[];
19
- };
20
- accessibility: string[];
21
- };
@@ -1,15 +0,0 @@
1
- /** Usage guidance for FieldHeading. */
2
- export declare const doc: {
3
- category: "Data display";
4
- keywords: string[];
5
- usage: {
6
- description: string;
7
- bestPractices: ({
8
- guidance: true;
9
- description: string;
10
- } | {
11
- guidance: false;
12
- description: string;
13
- })[];
14
- };
15
- };
@@ -1,25 +0,0 @@
1
- /** Usage guidance for HoverSwap. */
2
- export declare const doc: {
3
- category: "Layout";
4
- keywords: string[];
5
- usage: {
6
- description: string;
7
- bestPractices: ({
8
- guidance: true;
9
- description: string;
10
- } | {
11
- guidance: false;
12
- description: string;
13
- })[];
14
- anatomy: ({
15
- name: string;
16
- required: false;
17
- description: string;
18
- } | {
19
- name: string;
20
- required: true;
21
- description: string;
22
- })[];
23
- };
24
- accessibility: string[];
25
- };
@@ -1,25 +0,0 @@
1
- /** Usage guidance for InfoTip. */
2
- export declare const doc: {
3
- category: "Feedback";
4
- keywords: string[];
5
- usage: {
6
- description: string;
7
- bestPractices: ({
8
- guidance: true;
9
- description: string;
10
- } | {
11
- guidance: false;
12
- description: string;
13
- })[];
14
- anatomy: ({
15
- name: string;
16
- required: true;
17
- description: string;
18
- } | {
19
- name: string;
20
- required: false;
21
- description: string;
22
- })[];
23
- };
24
- accessibility: string[];
25
- };
@@ -1,15 +0,0 @@
1
- /** Usage guidance for JointLabel. */
2
- export declare const doc: {
3
- category: "Data display";
4
- keywords: string[];
5
- usage: {
6
- description: string;
7
- bestPractices: ({
8
- guidance: true;
9
- description: string;
10
- } | {
11
- guidance: false;
12
- description: string;
13
- })[];
14
- };
15
- };
@@ -1,21 +0,0 @@
1
- /** Usage guidance for LabeledDivider. */
2
- export declare const doc: {
3
- category: "Layout";
4
- keywords: string[];
5
- usage: {
6
- description: string;
7
- bestPractices: ({
8
- guidance: true;
9
- description: string;
10
- } | {
11
- guidance: false;
12
- description: string;
13
- })[];
14
- anatomy: {
15
- name: string;
16
- required: true;
17
- description: string;
18
- }[];
19
- };
20
- accessibility: string[];
21
- };
@@ -1,21 +0,0 @@
1
- /** Usage guidance for LogoImage. */
2
- export declare const doc: {
3
- category: "Data display";
4
- keywords: string[];
5
- usage: {
6
- description: string;
7
- bestPractices: ({
8
- guidance: true;
9
- description: string;
10
- } | {
11
- guidance: false;
12
- description: string;
13
- })[];
14
- anatomy: {
15
- name: string;
16
- required: false;
17
- description: string;
18
- }[];
19
- };
20
- accessibility: string[];
21
- };
@@ -1,25 +0,0 @@
1
- /** Usage guidance for PanelSearchInput. */
2
- export declare const doc: {
3
- category: "Inputs";
4
- keywords: string[];
5
- usage: {
6
- description: string;
7
- bestPractices: ({
8
- guidance: true;
9
- description: string;
10
- } | {
11
- guidance: false;
12
- description: string;
13
- })[];
14
- anatomy: ({
15
- name: string;
16
- required: true;
17
- description: string;
18
- } | {
19
- name: string;
20
- required: false;
21
- description: string;
22
- })[];
23
- };
24
- accessibility: string[];
25
- };