@tensor_1/react 2.42.0 → 2.43.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -762,6 +762,30 @@ The layout grid for dashboard widgets (HAR-1555; TENSOR's role dashboards). Pure
762
762
  - Refs reach the grid and item `<div>`s, and other props pass through. For an element you render yourself (a drag-and-drop library's sortable node, a server template), use `dashboardGridClassName(columns, gap)` and `dashboardGridItemClassName(span)`.
763
763
  - Plain HTML: `.uix-dashboard-grid` with `--cols-N` / `--{sm,md,lg,xl}-cols-N` and `--gap-sm|lg`, items `.uix-dashboard-grid__item` with `--span-2` / `--full`. Every direct child of the grid is a cell.
764
764
 
765
+ ### OrgChart
766
+
767
+ Reporting lines as a top-down chart (HAR-1807; TENSOR's People directory). Managers sit above their direct reports, joined by lines; each person is a card with photo or initials, name, title, team, location and the number of direct reports, which is also the control that shows or hides them. Data fetching stays in the product: the chart asks for a person's reports through `loadChildren` the first time they are opened.
768
+
769
+ ```tsx
770
+ <OrgChart
771
+ aria-label="Organisation"
772
+ nodes={roots} // OrgChartNode[]: { id, name, title?, team?, location?, photo?, badge?, reportCount?, children? }
773
+ loadChildren={(node) => api.reports(node.id)}
774
+ expanded={expanded} onToggle={(id, open) => setExpanded(next(expanded, id, open))}
775
+ selected={personId} onSelect={openPerson}
776
+ revealId={searchHit} onReveal={() => setSearchHit(null)}
777
+ />
778
+ ```
779
+
780
+ - **Lazy reports:** a person with `reportCount > 0` and no `children` is expandable; on expand a loading row stands in for the reports, and a rejection shows an error row whose Enter, Space or click retries. Results are kept for the life of the chart. Expanding through a controlled `expanded` (a whole reporting line at once) loads each level as it appears.
781
+ - **Search:** set `expanded` to the person's reporting line and `revealId` to the person; once their card exists the chart scrolls it into view, focuses it and calls `onReveal`. Set `revealId` back to null there, so the same person can be revealed again.
782
+ - **Stacked rows:** a row of people without reports of their own is a column under their manager (`stackLeaves`, default true), so a team of eight takes one card width.
783
+ - **Frame:** zoom out / in (25–150 %, around the frame's centre), Fit (the chart's width into the frame), the level button resets to 100 %; drag the background to pan (mouse and pen; touch scrolls). Opening a manager keeps their card where it was while their reports appear. Until the reader moves the view, a chart wider than the frame stays centred on its top, and `defaultZoom={'fit'}` keeps fitting as reports load. `--org-chart-max-height` (default 70vh) caps the frame. The root is an inline-size container: give it a width (a block, or `flex: 1` in a flex row).
784
+ - **Narrow:** below 48rem of the chart's **own** width (a container query: a side panel counts as much as a phone) it is an indented vertical tree with guide lines; the toolbar steps aside.
785
+ - **Keyboard:** one tab stop (roving tabindex). In the chart ↑ is the manager, ↓ the first report (↓ on a closed manager opens them first), ← → the previous and next person on the same level across teams; in a stacked column ↑ ↓ move along it. In the list the tree keys apply (↑ ↓ visible order, → open / first report, ← close / manager). From a stacked column, ← → go to the next column. Home / End, a letter jumps to the next visible person whose name starts with it, Enter opens the person (`onSelect`), Space shows or hides their reports. A failed load is announced.
786
+ - **Words:** `labels` or `UixLabelsProvider` `orgChart` (`DEFAULT_ORG_CHART_LABELS`): the tree's default name (`chart`), loading, error, retry, `reportsOne` / `reportsMany` (`{count}`), expand / collapse, the toolbar and its buttons, `zoomLevel` / `resetZoom` (`{percent}`).
787
+ - Plain HTML: `.uix-org-chart` > `__toolbar`, `__viewport` > `__canvas` > `ul.__tree[role=tree]` > `li.__item[role=treeitem]` > `.__node` (+ `ul.__group[role=group]`, `[data-stack]` for a column). The ARIA state on the item drives the styling.
788
+
765
789
  ### Select draws its own list
766
790
 
767
791
  `Select` (HAR-1572) no longer opens the browser's dropdown. It is the WAI-ARIA select-only combobox: a `<button role="combobox">` trigger and a UIx-drawn listbox in the top layer (a bottom sheet on phones). The props did not change, so existing call sites keep working:
@@ -0,0 +1,121 @@
1
+ import * as react from 'react';
2
+ import { HTMLAttributes } from 'react';
3
+
4
+ /** One person (or position) in an {@link OrgChart}. */
5
+ interface OrgChartNode {
6
+ id: string;
7
+ /** The person's name; also the card's accessible name. */
8
+ name: string;
9
+ /** Job title, under the name. */
10
+ title?: string;
11
+ team?: string;
12
+ location?: string;
13
+ /** Photo URL. Without one the card shows {@link OrgChartNode.initials}, else the name's initials. */
14
+ photo?: string;
15
+ initials?: string;
16
+ /** A short marker on the card, such as "You". It is read with the person's description. */
17
+ badge?: string;
18
+ /**
19
+ * How many people report directly to this one. With `loadChildren`, a count above 0 shows the
20
+ * count on the card and makes the person expandable before {@link OrgChartNode.children} is
21
+ * known. Once the reports are known, their number wins.
22
+ */
23
+ reportCount?: number;
24
+ /** The direct reports, when known. Otherwise `loadChildren` loads them on the first expand. */
25
+ children?: OrgChartNode[];
26
+ }
27
+ /** The words of an {@link OrgChart}. `{count}` and `{percent}` are filled in. */
28
+ interface OrgChartLabels {
29
+ /** The tree's name when the chart gets no `aria-label` / `aria-labelledby`. */
30
+ chart: string;
31
+ /** The row in place of reports that are loading. */
32
+ loading: string;
33
+ /** The row in place of reports that could not be loaded; also announced. */
34
+ error: string;
35
+ /** The action in that row. Enter, Space or a click on the row runs it. */
36
+ retry: string;
37
+ /** Read after the person: one direct report. */
38
+ reportsOne: string;
39
+ /** Read after the person: `{count}` direct reports. */
40
+ reportsMany: string;
41
+ /** The report count's tooltip while the reports are hidden. */
42
+ expand: string;
43
+ /** The report count's tooltip while the reports are shown. */
44
+ collapse: string;
45
+ /** The zoom controls' group name. */
46
+ toolbar: string;
47
+ zoomIn: string;
48
+ zoomOut: string;
49
+ /** Fit the chart's width into the frame. */
50
+ fit: string;
51
+ /** The current zoom, shown on the reset button: `{percent}`. */
52
+ zoomLevel: string;
53
+ /** The reset button's name; it should start with the visible level. `{percent}`. */
54
+ resetZoom: string;
55
+ }
56
+ declare const DEFAULT_ORG_CHART_LABELS: OrgChartLabels;
57
+ interface OrgChartProps extends Omit<HTMLAttributes<HTMLDivElement>, 'onSelect' | 'onToggle' | 'children'> {
58
+ /** The top of the chart: the people without a manager, or wherever the chart should start. */
59
+ nodes: OrgChartNode[];
60
+ /** Expanded people (controlled). Expanding one whose reports are not known loads them. */
61
+ expanded?: ReadonlySet<string>;
62
+ /** Expanded people at first render (uncontrolled). */
63
+ defaultExpanded?: ReadonlySet<string>;
64
+ /** A person was expanded or collapsed, by a click on the report count or by the keyboard. */
65
+ onToggle?: (id: string, expanded: boolean) => void;
66
+ /** The chosen person: highlighted, and the tree's entry point for the Tab key. */
67
+ selected?: string | null;
68
+ /** A card was clicked, or Enter pressed on it: open the person. */
69
+ onSelect?: (id: string) => void;
70
+ /**
71
+ * Loads a person's direct reports the first time they are expanded, for a chart that grows on
72
+ * demand. While it runs a loading row stands in for the reports; a rejection shows an error row
73
+ * whose Enter, Space or click retries, and is announced. The result is kept for the life of the
74
+ * chart.
75
+ */
76
+ loadChildren?: (node: OrgChartNode) => Promise<OrgChartNode[]>;
77
+ /**
78
+ * Bring this person into view and focus them once they are rendered: the target of a search.
79
+ * Expand their reporting line first (`expanded`); the chart waits until the card exists. Set it
80
+ * back to null in `onReveal`, so the same person can be revealed again later.
81
+ */
82
+ revealId?: string | null;
83
+ /** Called once the {@link OrgChartProps.revealId} person has been scrolled to and focused. */
84
+ onReveal?: (id: string) => void;
85
+ /**
86
+ * Stack a row of people who have no reports of their own in one column under their manager,
87
+ * instead of side by side. Default true: a team of eight then takes one card's width.
88
+ */
89
+ stackLeaves?: boolean;
90
+ /**
91
+ * Start at this zoom (0.25–1.5), or `'fit'` to fit the chart's width into the frame; the fit is
92
+ * kept as reports load until the reader zooms, pans or opens someone. Default 1.
93
+ */
94
+ defaultZoom?: number | 'fit';
95
+ /** Words of the chart. Default: `UixLabelsProvider` `orgChart`, then English. */
96
+ labels?: Partial<OrgChartLabels>;
97
+ }
98
+ /** The next zoom step above (`dir` 1) or below (`dir` -1) `zoom`. */
99
+ declare const orgChartZoomStep: (zoom: number, dir: 1 | -1) => number;
100
+ /** "Mira Kovač" → "MK"; one word → its first letter. */
101
+ declare const orgChartInitials: (name: string) => string;
102
+ /**
103
+ * An org chart over `.uix-org-chart` (HAR-1807): managers above their direct reports, joined by
104
+ * lines, each person a card with photo or initials, name, title, team, location and their number
105
+ * of direct reports. Reports load on expand (`loadChildren`); a person can be revealed by id for
106
+ * search. The frame zooms (buttons, and Fit for the chart's width) around its centre, pans by
107
+ * dragging its background, scrolls, and keeps an opened manager's card in place while their
108
+ * reports appear. Below 48rem of its own width it becomes an indented vertical tree.
109
+ *
110
+ * A WAI-ARIA tree with one tab stop. In the chart: ↑ manager, ↓ first report (expanding them
111
+ * first), ← → the previous and next person on the same level (from a stacked column, the next
112
+ * column); in a stacked column ↑ ↓ move along it. In the list: the tree keys (↑ ↓ visible order,
113
+ * → expand / first report, ← collapse / manager). Both: Home / End, a letter jumps to the next
114
+ * visible person whose name starts with it, Enter opens the person (`onSelect`), Space shows or
115
+ * hides their reports.
116
+ *
117
+ * The root is an inline-size container: give it a width (a block, or `flex: 1` in a flex row).
118
+ */
119
+ declare function OrgChart({ nodes, expanded: controlledExpanded, defaultExpanded, onToggle, selected, onSelect, loadChildren, revealId, onReveal, stackLeaves, defaultZoom, labels: labelOverrides, className, 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledby, ...props }: OrgChartProps): react.JSX.Element;
120
+
121
+ export { DEFAULT_ORG_CHART_LABELS, OrgChart, type OrgChartLabels, type OrgChartNode, type OrgChartProps, orgChartInitials, orgChartZoomStep };