@tensor_1/react 2.19.2 → 2.21.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 +14 -0
- package/dist/{ChartCore-Do6gRBN3.d.cts → ChartCore-DzWe10bN.d.cts} +16 -1
- package/dist/chart-preset.cjs +25 -13
- package/dist/chart-preset.d.cts +2 -2
- package/dist/chart-preset.d.ts +1 -1
- package/dist/chart-preset.js +2 -1
- package/dist/chart.cjs +25 -13
- package/dist/chart.d.cts +2 -2
- package/dist/chart.d.ts +1 -1
- package/dist/chart.js +2 -1
- package/dist/components/AppShell.d.ts +5 -1
- package/dist/components/AppShell.js +4 -2
- package/dist/components/Avatar.d.ts +3 -1
- package/dist/components/Avatar.js +2 -2
- package/dist/components/BrandProfiles.d.ts +29 -2
- package/dist/components/BrandProfiles.js +45 -20
- package/dist/components/BuilderCanvas.d.ts +27 -2
- package/dist/components/BuilderCanvas.js +45 -22
- package/dist/components/Chart.d.ts +1 -1
- package/dist/components/Chart.js +2 -1
- package/dist/components/ChartCore.d.ts +17 -2
- package/dist/components/ChartCore.js +24 -13
- package/dist/components/ColorPicker.d.ts +24 -2
- package/dist/components/ColorPicker.js +38 -20
- package/dist/components/CommandPalette.d.ts +3 -1
- package/dist/components/CommandPalette.js +2 -2
- package/dist/components/CopyButton.d.ts +25 -0
- package/dist/components/CopyButton.js +52 -0
- package/dist/components/DateRangePicker.d.ts +21 -2
- package/dist/components/DateRangePicker.js +26 -6
- package/dist/components/DetailPage.d.ts +22 -3
- package/dist/components/DetailPage.js +33 -3
- package/dist/components/DiffViewer.d.ts +34 -3
- package/dist/components/DiffViewer.js +60 -40
- package/dist/components/Drawer.d.ts +3 -1
- package/dist/components/Drawer.js +2 -2
- package/dist/components/Inbox.d.ts +3 -1
- package/dist/components/Inbox.js +2 -2
- package/dist/components/MatchReview.d.ts +49 -2
- package/dist/components/MatchReview.js +72 -30
- package/dist/components/Meter.d.ts +3 -1
- package/dist/components/Meter.js +3 -2
- package/dist/components/Pagination.d.ts +10 -2
- package/dist/components/Pagination.js +11 -4
- package/dist/components/Peek.d.ts +7 -1
- package/dist/components/Peek.js +4 -4
- package/dist/components/RelationshipGraph.js +6 -2
- package/dist/components/RuleBuilder.d.ts +42 -2
- package/dist/components/RuleBuilder.js +71 -37
- package/dist/components/SchedulingCalendar.d.ts +25 -2
- package/dist/components/SchedulingCalendar.js +38 -15
- package/dist/components/Stat.d.ts +24 -3
- package/dist/components/Stat.js +51 -10
- package/dist/components/Table.d.ts +11 -3
- package/dist/components/Table.js +5 -8
- package/dist/components/Tabs.d.ts +14 -1
- package/dist/components/Tabs.js +88 -19
- package/dist/components/Toast.d.ts +6 -2
- package/dist/components/Toast.js +4 -4
- package/dist/components/Tree.d.ts +9 -1
- package/dist/components/Tree.js +55 -8
- package/dist/copy-model.d.ts +12 -0
- package/dist/copy-model.js +12 -0
- package/dist/fill-label.d.ts +7 -0
- package/dist/fill-label.js +9 -0
- package/dist/index.cjs +1480 -1004
- package/dist/index.d.cts +387 -30
- package/dist/index.d.ts +11 -10
- package/dist/index.js +20 -9
- package/package.json +1 -1
|
@@ -3,8 +3,24 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
3
3
|
import { useEffect, useId, useMemo, useRef, useState } from "react";
|
|
4
4
|
import { addCalendarDays, addCalendarMonths, buildMonthGrid, isDateInRange, isDateUnavailable, selectRangeDate, startOfMonth } from "../calendar-model.js";
|
|
5
5
|
import { cx } from "../cx.js";
|
|
6
|
+
const DEFAULT_DATE_RANGE_PICKER_LABELS = {
|
|
7
|
+
previous: "Previous",
|
|
8
|
+
previousMonth: "Show previous month",
|
|
9
|
+
next: "Next",
|
|
10
|
+
nextMonth: "Show next month",
|
|
11
|
+
noneSelected: "No date range selected.",
|
|
12
|
+
startSelected: "Start date {start} selected. Choose an end date.",
|
|
13
|
+
rangeSelected: "{start} to {end} selected.",
|
|
14
|
+
rangeStart: "start of selected range",
|
|
15
|
+
rangeEnd: "end of selected range",
|
|
16
|
+
inRange: "in selected range"
|
|
17
|
+
};
|
|
6
18
|
const monthLabel = (date, locale) => new Intl.DateTimeFormat(locale, { month: "long", year: "numeric", timeZone: "UTC" }).format(/* @__PURE__ */ new Date(`${date}T00:00:00Z`));
|
|
7
19
|
const dateLabel = (date, locale) => new Intl.DateTimeFormat(locale, { dateStyle: "full", timeZone: "UTC" }).format(/* @__PURE__ */ new Date(`${date}T00:00:00Z`));
|
|
20
|
+
const weekdayNames = (locale) => {
|
|
21
|
+
const fmt = new Intl.DateTimeFormat(locale, { weekday: "short", timeZone: "UTC" });
|
|
22
|
+
return Array.from({ length: 7 }, (_, i) => fmt.format(new Date(Date.UTC(2024, 0, 1 + i))));
|
|
23
|
+
};
|
|
8
24
|
function DateRangePicker({
|
|
9
25
|
value,
|
|
10
26
|
onChange,
|
|
@@ -19,9 +35,12 @@ function DateRangePicker({
|
|
|
19
35
|
invalid,
|
|
20
36
|
invalidMessage = "The selected date range is invalid.",
|
|
21
37
|
disabled,
|
|
22
|
-
className
|
|
38
|
+
className,
|
|
39
|
+
labels: labelOverrides
|
|
23
40
|
}) {
|
|
24
41
|
const id = useId();
|
|
42
|
+
const labels = { ...DEFAULT_DATE_RANGE_PICKER_LABELS, ...labelOverrides };
|
|
43
|
+
const weekdays = useMemo(() => weekdayNames(locale), [locale]);
|
|
25
44
|
const [internalMonth, setInternalMonth] = useState(() => startOfMonth(controlledMonth ?? value.start ?? (/* @__PURE__ */ new Date()).toISOString().slice(0, 10)));
|
|
26
45
|
const visibleMonth = startOfMonth(controlledMonth ?? internalMonth);
|
|
27
46
|
const [activeDate, setActiveDate] = useState(value.end ?? value.start ?? visibleMonth);
|
|
@@ -76,18 +95,18 @@ function DateRangePicker({
|
|
|
76
95
|
focusDate(addCalendarMonths(date, event.key === "PageUp" ? -1 : 1));
|
|
77
96
|
}
|
|
78
97
|
};
|
|
79
|
-
const announcement = !value.start ?
|
|
98
|
+
const announcement = !value.start ? labels.noneSelected : !value.end ? labels.startSelected.replace("{start}", dateLabel(value.start, locale)) : labels.rangeSelected.replace("{start}", dateLabel(value.start, locale)).replace("{end}", dateLabel(value.end, locale));
|
|
80
99
|
return /* @__PURE__ */ jsxs("section", { className: cx("uix-date-range-picker", rangeInvalid && "uix-date-range-picker--invalid", className), "aria-labelledby": `${id}-label`, children: [
|
|
81
100
|
/* @__PURE__ */ jsxs("div", { className: "uix-date-range-picker__header", children: [
|
|
82
101
|
/* @__PURE__ */ jsx("h3", { id: `${id}-label`, children: label }),
|
|
83
102
|
/* @__PURE__ */ jsxs("div", { children: [
|
|
84
|
-
/* @__PURE__ */ jsx("button", { type: "button", className: "uix-btn uix-btn--ghost uix-btn--sm", onClick: () => setMonth(addCalendarMonths(visibleMonth, -1)), "aria-label":
|
|
85
|
-
/* @__PURE__ */ jsx("button", { type: "button", className: "uix-btn uix-btn--ghost uix-btn--sm", onClick: () => setMonth(addCalendarMonths(visibleMonth, 1)), "aria-label":
|
|
103
|
+
/* @__PURE__ */ jsx("button", { type: "button", className: "uix-btn uix-btn--ghost uix-btn--sm", onClick: () => setMonth(addCalendarMonths(visibleMonth, -1)), "aria-label": labels.previousMonth, children: labels.previous }),
|
|
104
|
+
/* @__PURE__ */ jsx("button", { type: "button", className: "uix-btn uix-btn--ghost uix-btn--sm", onClick: () => setMonth(addCalendarMonths(visibleMonth, 1)), "aria-label": labels.nextMonth, children: labels.next })
|
|
86
105
|
] })
|
|
87
106
|
] }),
|
|
88
107
|
/* @__PURE__ */ jsx("div", { ref: rootRef, className: "uix-date-range-picker__months", children: calendars.map(({ month, days }) => /* @__PURE__ */ jsxs("div", { className: "uix-date-range-picker__month", children: [
|
|
89
108
|
/* @__PURE__ */ jsx("h4", { children: monthLabel(month, locale) }),
|
|
90
|
-
/* @__PURE__ */ jsx("div", { className: "uix-date-range-picker__weekdays", "aria-hidden": "true", children:
|
|
109
|
+
/* @__PURE__ */ jsx("div", { className: "uix-date-range-picker__weekdays", "aria-hidden": "true", children: weekdays.map((day, index) => /* @__PURE__ */ jsx("span", { children: day }, index)) }),
|
|
91
110
|
/* @__PURE__ */ jsxs("div", { className: "uix-date-range-picker__grid", role: "group", "aria-label": monthLabel(month, locale), children: [
|
|
92
111
|
Array.from({ length: ((/* @__PURE__ */ new Date(`${month}T00:00:00Z`)).getUTCDay() + 6) % 7 }, (_, index) => /* @__PURE__ */ jsx("span", { "aria-hidden": "true" }, `blank-${index}`)),
|
|
93
112
|
days.map((day) => {
|
|
@@ -101,7 +120,7 @@ function DateRangePicker({
|
|
|
101
120
|
"data-range-edge": edge,
|
|
102
121
|
"data-in-range": isDateInRange(day.date, value) || void 0,
|
|
103
122
|
"aria-pressed": edge != null || isDateInRange(day.date, value),
|
|
104
|
-
"aria-label": `${dateLabel(day.date, locale)}${edge ? `, ${edge
|
|
123
|
+
"aria-label": `${dateLabel(day.date, locale)}${edge ? `, ${edge === "start" ? labels.rangeStart : labels.rangeEnd}` : isDateInRange(day.date, value) ? `, ${labels.inRange}` : ""}`,
|
|
105
124
|
tabIndex: activeDate === day.date ? 0 : -1,
|
|
106
125
|
disabled: unavailable,
|
|
107
126
|
onFocus: () => setActiveDate(day.date),
|
|
@@ -119,5 +138,6 @@ function DateRangePicker({
|
|
|
119
138
|
] });
|
|
120
139
|
}
|
|
121
140
|
export {
|
|
141
|
+
DEFAULT_DATE_RANGE_PICKER_LABELS,
|
|
122
142
|
DateRangePicker
|
|
123
143
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
|
-
import { HTMLAttributes, ReactNode } from 'react';
|
|
2
|
+
import { HTMLAttributes, ReactNode, MouseEvent } from 'react';
|
|
3
3
|
|
|
4
4
|
interface DetailPageTab {
|
|
5
5
|
id: string;
|
|
@@ -12,6 +12,14 @@ interface DetailPageMetric {
|
|
|
12
12
|
label: ReactNode;
|
|
13
13
|
value: ReactNode;
|
|
14
14
|
}
|
|
15
|
+
/** What `renderLink` receives: render it as your router's link (TENSOR RX-125, UIX-10). */
|
|
16
|
+
interface DetailPageLinkProps {
|
|
17
|
+
href: string;
|
|
18
|
+
className: string;
|
|
19
|
+
children: ReactNode;
|
|
20
|
+
'aria-current'?: 'page';
|
|
21
|
+
onClick?: (event: MouseEvent<HTMLAnchorElement>) => void;
|
|
22
|
+
}
|
|
15
23
|
interface DetailPageProps extends Omit<HTMLAttributes<HTMLElement>, 'title'> {
|
|
16
24
|
back?: {
|
|
17
25
|
href: string;
|
|
@@ -26,8 +34,19 @@ interface DetailPageProps extends Omit<HTMLAttributes<HTMLElement>, 'title'> {
|
|
|
26
34
|
side?: ReactNode;
|
|
27
35
|
children?: ReactNode;
|
|
28
36
|
tabsLabel?: string;
|
|
37
|
+
/**
|
|
38
|
+
* Renders the back link and every tab link. Default: a plain `<a>`. Pass your
|
|
39
|
+
* router's link (e.g. next/link) so switching tabs never reloads the page.
|
|
40
|
+
*/
|
|
41
|
+
renderLink?: (props: DetailPageLinkProps) => ReactNode;
|
|
42
|
+
/**
|
|
43
|
+
* Controlled tabs: called with the tab id on a plain left click, which then does
|
|
44
|
+
* not navigate. `href` stays the progressive-enhancement fallback (new tab,
|
|
45
|
+
* modified click, no JS).
|
|
46
|
+
*/
|
|
47
|
+
onTabSelect?: (id: string) => void;
|
|
29
48
|
}
|
|
30
49
|
/** Framework-neutral record-detail scaffold; routing and data policy stay with the application. */
|
|
31
|
-
declare function DetailPage({ back, eyebrow, title, subtitle, actions, tabs, metrics, side, children, tabsLabel, className, ...props }: DetailPageProps): react.JSX.Element;
|
|
50
|
+
declare function DetailPage({ back, eyebrow, title, subtitle, actions, tabs, metrics, side, children, tabsLabel, renderLink, onTabSelect, className, ...props }: DetailPageProps): react.JSX.Element;
|
|
32
51
|
|
|
33
|
-
export { DetailPage, type DetailPageMetric, type DetailPageProps, type DetailPageTab };
|
|
52
|
+
export { DetailPage, type DetailPageLinkProps, type DetailPageMetric, type DetailPageProps, type DetailPageTab };
|
|
@@ -1,16 +1,46 @@
|
|
|
1
1
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Fragment } from "react";
|
|
2
3
|
import { cx } from "../cx.js";
|
|
3
4
|
import { DetailLayout } from "./DetailLayout.js";
|
|
4
5
|
import { PageHeader } from "./PageHeader.js";
|
|
5
|
-
|
|
6
|
+
const plainLink = ({ href, className, children, onClick, ...rest }) => /* @__PURE__ */ jsx("a", { href, className, onClick, ...rest, children });
|
|
7
|
+
const isPlainLeftClick = (e) => e.button === 0 && !e.metaKey && !e.ctrlKey && !e.shiftKey && !e.altKey;
|
|
8
|
+
function DetailPage({
|
|
9
|
+
back,
|
|
10
|
+
eyebrow,
|
|
11
|
+
title,
|
|
12
|
+
subtitle,
|
|
13
|
+
actions,
|
|
14
|
+
tabs,
|
|
15
|
+
metrics,
|
|
16
|
+
side,
|
|
17
|
+
children,
|
|
18
|
+
tabsLabel,
|
|
19
|
+
renderLink = plainLink,
|
|
20
|
+
onTabSelect,
|
|
21
|
+
className,
|
|
22
|
+
...props
|
|
23
|
+
}) {
|
|
6
24
|
return /* @__PURE__ */ jsxs("section", { className: cx("uix-detail-page", className), ...props, children: [
|
|
7
|
-
back &&
|
|
25
|
+
back && renderLink({ href: back.href, className: "uix-link uix-link--quiet uix-detail-page__back", children: back.label }),
|
|
8
26
|
/* @__PURE__ */ jsx(PageHeader, { eyebrow, title, subtitle, actions }),
|
|
9
27
|
metrics && metrics.length > 0 && /* @__PURE__ */ jsx("dl", { className: "uix-detail-page__metrics", children: metrics.map((metric) => /* @__PURE__ */ jsxs("div", { children: [
|
|
10
28
|
/* @__PURE__ */ jsx("dt", { children: metric.label }),
|
|
11
29
|
/* @__PURE__ */ jsx("dd", { children: metric.value })
|
|
12
30
|
] }, metric.id)) }),
|
|
13
|
-
tabs && tabs.length > 0 && /* @__PURE__ */ jsx("nav", { className: "uix-tabs", "aria-label": tabsLabel, children: tabs.map((tab) => /* @__PURE__ */ jsx(
|
|
31
|
+
tabs && tabs.length > 0 && /* @__PURE__ */ jsx("nav", { className: "uix-tabs", "aria-label": tabsLabel, children: tabs.map((tab) => /* @__PURE__ */ jsx(Fragment, { children: renderLink({
|
|
32
|
+
href: tab.href,
|
|
33
|
+
className: "uix-tab",
|
|
34
|
+
children: tab.label,
|
|
35
|
+
...tab.active ? { "aria-current": "page" } : {},
|
|
36
|
+
...onTabSelect ? {
|
|
37
|
+
onClick: (e) => {
|
|
38
|
+
if (!isPlainLeftClick(e)) return;
|
|
39
|
+
e.preventDefault();
|
|
40
|
+
onTabSelect(tab.id);
|
|
41
|
+
}
|
|
42
|
+
} : {}
|
|
43
|
+
}) }, tab.id)) }),
|
|
14
44
|
/* @__PURE__ */ jsx(DetailLayout, { side, children })
|
|
15
45
|
] });
|
|
16
46
|
}
|
|
@@ -2,6 +2,37 @@ import * as react from 'react';
|
|
|
2
2
|
import { JsonValue } from '../json-value.js';
|
|
3
3
|
import { DiffEntry, DiffResolution } from '../diff-model.js';
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Every word the diff viewer renders (TENSOR RX-125, UIX-12). `base` / `current` /
|
|
7
|
+
* `incoming` keep their meaning from before; `{path}`, `{version}`, `{resolved}` and
|
|
8
|
+
* `{total}` are placeholders.
|
|
9
|
+
*/
|
|
10
|
+
interface DiffViewerLabels {
|
|
11
|
+
base: string;
|
|
12
|
+
current: string;
|
|
13
|
+
incoming: string;
|
|
14
|
+
region: string;
|
|
15
|
+
summary: string;
|
|
16
|
+
noDifferences: string;
|
|
17
|
+
noDifferencesDetail: string;
|
|
18
|
+
conflicted: string;
|
|
19
|
+
changed: string;
|
|
20
|
+
added: string;
|
|
21
|
+
removed: string;
|
|
22
|
+
resolved: string;
|
|
23
|
+
pending: string;
|
|
24
|
+
valueFor: string;
|
|
25
|
+
resolve: string;
|
|
26
|
+
acceptIncoming: string;
|
|
27
|
+
keepCurrent: string;
|
|
28
|
+
markPending: string;
|
|
29
|
+
resolutionAccept: string;
|
|
30
|
+
resolutionSkip: string;
|
|
31
|
+
resolutionPending: string;
|
|
32
|
+
notPresent: string;
|
|
33
|
+
progress: string;
|
|
34
|
+
}
|
|
35
|
+
declare const DEFAULT_DIFF_VIEWER_LABELS: DiffViewerLabels;
|
|
5
36
|
interface DiffViewerProps {
|
|
6
37
|
base?: JsonValue;
|
|
7
38
|
current?: JsonValue;
|
|
@@ -9,10 +40,10 @@ interface DiffViewerProps {
|
|
|
9
40
|
entries?: DiffEntry[];
|
|
10
41
|
resolutions?: Record<string, DiffResolution>;
|
|
11
42
|
onResolutionChange?: (path: string, resolution: DiffResolution) => void;
|
|
12
|
-
labels?: Partial<
|
|
43
|
+
labels?: Partial<DiffViewerLabels>;
|
|
13
44
|
className?: string;
|
|
14
45
|
}
|
|
15
46
|
/** Three-way configuration diff with per-entry keyboard-operable resolution. */
|
|
16
|
-
declare function DiffViewer({ base, current, incoming, entries: providedEntries, resolutions: controlledResolutions, onResolutionChange, labels, className, }: DiffViewerProps): react.JSX.Element;
|
|
47
|
+
declare function DiffViewer({ base, current, incoming, entries: providedEntries, resolutions: controlledResolutions, onResolutionChange, labels: labelOverrides, className, }: DiffViewerProps): react.JSX.Element;
|
|
17
48
|
|
|
18
|
-
export { DiffViewer, type DiffViewerProps };
|
|
49
|
+
export { DEFAULT_DIFF_VIEWER_LABELS, DiffViewer, type DiffViewerLabels, type DiffViewerProps };
|
|
@@ -4,14 +4,34 @@ import { useId, useMemo, useState } from "react";
|
|
|
4
4
|
import { buildThreeWayDiff, summarizeDiff } from "../diff-model.js";
|
|
5
5
|
import { cx } from "../cx.js";
|
|
6
6
|
import { StatusPill } from "./StatusPill.js";
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
7
|
+
import { fillLabel } from "../fill-label.js";
|
|
8
|
+
const DEFAULT_DIFF_VIEWER_LABELS = {
|
|
9
|
+
base: "Base",
|
|
10
|
+
current: "Current",
|
|
11
|
+
incoming: "Incoming",
|
|
12
|
+
region: "Configuration differences",
|
|
13
|
+
summary: "Difference summary",
|
|
14
|
+
noDifferences: "No differences",
|
|
15
|
+
noDifferencesDetail: "Base, current, and incoming values are aligned.",
|
|
16
|
+
conflicted: "Conflicted",
|
|
17
|
+
changed: "Changed",
|
|
18
|
+
added: "Added",
|
|
19
|
+
removed: "Removed",
|
|
20
|
+
resolved: "resolved",
|
|
21
|
+
pending: "pending",
|
|
22
|
+
valueFor: "{version} value for {path}",
|
|
23
|
+
resolve: "Resolve {path}",
|
|
24
|
+
acceptIncoming: "Accept incoming",
|
|
25
|
+
keepCurrent: "Keep current",
|
|
26
|
+
markPending: "Mark pending",
|
|
27
|
+
resolutionAccept: "accepted",
|
|
28
|
+
resolutionSkip: "kept",
|
|
29
|
+
resolutionPending: "pending",
|
|
30
|
+
notPresent: "Not present",
|
|
31
|
+
progress: "{resolved} of {total} differences resolved."
|
|
32
|
+
};
|
|
33
|
+
const GROUPS = ["conflicted", "changed", "added", "removed"];
|
|
34
|
+
const renderValue = (value, notPresent) => value === void 0 ? notPresent : JSON.stringify(value, null, 2);
|
|
15
35
|
function DiffViewer({
|
|
16
36
|
base,
|
|
17
37
|
current,
|
|
@@ -19,9 +39,11 @@ function DiffViewer({
|
|
|
19
39
|
entries: providedEntries,
|
|
20
40
|
resolutions: controlledResolutions,
|
|
21
41
|
onResolutionChange,
|
|
22
|
-
labels
|
|
42
|
+
labels: labelOverrides,
|
|
23
43
|
className
|
|
24
44
|
}) {
|
|
45
|
+
const labels = { ...DEFAULT_DIFF_VIEWER_LABELS, ...labelOverrides };
|
|
46
|
+
const resolutionLabel = { accept: labels.resolutionAccept, skip: labels.resolutionSkip, pending: labels.resolutionPending };
|
|
25
47
|
const id = useId();
|
|
26
48
|
const entries = useMemo(() => providedEntries ?? buildThreeWayDiff(base, current, incoming), [providedEntries, base, current, incoming]);
|
|
27
49
|
const [internalResolutions, setInternalResolutions] = useState({});
|
|
@@ -31,32 +53,34 @@ function DiffViewer({
|
|
|
31
53
|
if (controlledResolutions === void 0) setInternalResolutions((currentState) => ({ ...currentState, [path]: resolution }));
|
|
32
54
|
onResolutionChange?.(path, resolution);
|
|
33
55
|
};
|
|
34
|
-
if (entries.length === 0) return /* @__PURE__ */ jsxs("section", { className: cx("uix-diff-viewer uix-diff-viewer--empty", className), "aria-label":
|
|
35
|
-
/* @__PURE__ */ jsx("h3", { children:
|
|
36
|
-
/* @__PURE__ */ jsx("p", { children:
|
|
56
|
+
if (entries.length === 0) return /* @__PURE__ */ jsxs("section", { className: cx("uix-diff-viewer uix-diff-viewer--empty", className), "aria-label": labels.region, children: [
|
|
57
|
+
/* @__PURE__ */ jsx("h3", { children: labels.noDifferences }),
|
|
58
|
+
/* @__PURE__ */ jsx("p", { children: labels.noDifferencesDetail })
|
|
37
59
|
] });
|
|
38
|
-
return /* @__PURE__ */ jsxs("section", { className: cx("uix-diff-viewer", className), "aria-label":
|
|
39
|
-
/* @__PURE__ */ jsxs("div", { className: "uix-diff-viewer__summary", "aria-label":
|
|
40
|
-
GROUPS.map((
|
|
41
|
-
/* @__PURE__ */ jsx("b", { children: summary[
|
|
60
|
+
return /* @__PURE__ */ jsxs("section", { className: cx("uix-diff-viewer", className), "aria-label": labels.region, children: [
|
|
61
|
+
/* @__PURE__ */ jsxs("div", { className: "uix-diff-viewer__summary", "aria-label": labels.summary, children: [
|
|
62
|
+
GROUPS.map((kind) => /* @__PURE__ */ jsxs("span", { children: [
|
|
63
|
+
/* @__PURE__ */ jsx("b", { children: summary[kind] }),
|
|
42
64
|
" ",
|
|
43
|
-
|
|
44
|
-
] },
|
|
65
|
+
labels[kind].toLowerCase()
|
|
66
|
+
] }, kind)),
|
|
45
67
|
/* @__PURE__ */ jsxs("span", { children: [
|
|
46
68
|
/* @__PURE__ */ jsx("b", { children: summary.resolved }),
|
|
47
|
-
"
|
|
69
|
+
" ",
|
|
70
|
+
labels.resolved
|
|
48
71
|
] }),
|
|
49
72
|
/* @__PURE__ */ jsxs("span", { children: [
|
|
50
73
|
/* @__PURE__ */ jsx("b", { children: summary.pending }),
|
|
51
|
-
"
|
|
74
|
+
" ",
|
|
75
|
+
labels.pending
|
|
52
76
|
] })
|
|
53
77
|
] }),
|
|
54
|
-
GROUPS.map((
|
|
55
|
-
const grouped = entries.filter((entry) => entry.kind ===
|
|
78
|
+
GROUPS.map((kind) => {
|
|
79
|
+
const grouped = entries.filter((entry) => entry.kind === kind);
|
|
56
80
|
if (!grouped.length) return null;
|
|
57
|
-
return /* @__PURE__ */ jsxs("section", { className: "uix-diff-viewer__group", "aria-labelledby": `${id}-${
|
|
58
|
-
/* @__PURE__ */ jsxs("h3", { id: `${id}-${
|
|
59
|
-
|
|
81
|
+
return /* @__PURE__ */ jsxs("section", { className: "uix-diff-viewer__group", "aria-labelledby": `${id}-${kind}`, children: [
|
|
82
|
+
/* @__PURE__ */ jsxs("h3", { id: `${id}-${kind}`, children: [
|
|
83
|
+
labels[kind],
|
|
60
84
|
" ",
|
|
61
85
|
/* @__PURE__ */ jsx("span", { children: grouped.length })
|
|
62
86
|
] }),
|
|
@@ -65,29 +89,25 @@ function DiffViewer({
|
|
|
65
89
|
return /* @__PURE__ */ jsxs("details", { className: "uix-diff-viewer__entry", "data-kind": entry.kind, open: entry.kind === "conflicted", children: [
|
|
66
90
|
/* @__PURE__ */ jsxs("summary", { children: [
|
|
67
91
|
/* @__PURE__ */ jsx("code", { children: entry.path }),
|
|
68
|
-
/* @__PURE__ */ jsx(StatusPill, { tone: resolution === "pending" ? "warning" : "success", children: resolution })
|
|
92
|
+
/* @__PURE__ */ jsx(StatusPill, { tone: resolution === "pending" ? "warning" : "success", children: resolutionLabel[resolution] })
|
|
69
93
|
] }),
|
|
70
|
-
/* @__PURE__ */ jsx("div", { className: "uix-diff-viewer__versions", children: ["base", "current", "incoming"].map((version) => /* @__PURE__ */ jsxs("div", { role: "region", "aria-label":
|
|
71
|
-
/* @__PURE__ */ jsx("strong", { children: labels[version]
|
|
72
|
-
/* @__PURE__ */ jsx("pre", { children: renderValue(entry[version]) })
|
|
94
|
+
/* @__PURE__ */ jsx("div", { className: "uix-diff-viewer__versions", children: ["base", "current", "incoming"].map((version) => /* @__PURE__ */ jsxs("div", { role: "region", "aria-label": fillLabel(labels.valueFor, { version: labels[version], path: entry.path }), children: [
|
|
95
|
+
/* @__PURE__ */ jsx("strong", { children: labels[version] }),
|
|
96
|
+
/* @__PURE__ */ jsx("pre", { children: renderValue(entry[version], labels.notPresent) })
|
|
73
97
|
] }, version)) }),
|
|
74
|
-
/* @__PURE__ */ jsxs("div", { className: "uix-diff-viewer__actions", "aria-label":
|
|
75
|
-
/* @__PURE__ */ jsx("button", { type: "button", className: "uix-btn uix-btn--primary uix-btn--sm", "aria-pressed": resolution === "accept", onClick: () => resolve(entry.path, "accept"), children:
|
|
76
|
-
/* @__PURE__ */ jsx("button", { type: "button", className: "uix-btn uix-btn--secondary uix-btn--sm", "aria-pressed": resolution === "skip", onClick: () => resolve(entry.path, "skip"), children:
|
|
77
|
-
/* @__PURE__ */ jsx("button", { type: "button", className: "uix-btn uix-btn--ghost uix-btn--sm", "aria-pressed": resolution === "pending", onClick: () => resolve(entry.path, "pending"), children:
|
|
98
|
+
/* @__PURE__ */ jsxs("div", { className: "uix-diff-viewer__actions", "aria-label": fillLabel(labels.resolve, { path: entry.path }), children: [
|
|
99
|
+
/* @__PURE__ */ jsx("button", { type: "button", className: "uix-btn uix-btn--primary uix-btn--sm", "aria-pressed": resolution === "accept", onClick: () => resolve(entry.path, "accept"), children: labels.acceptIncoming }),
|
|
100
|
+
/* @__PURE__ */ jsx("button", { type: "button", className: "uix-btn uix-btn--secondary uix-btn--sm", "aria-pressed": resolution === "skip", onClick: () => resolve(entry.path, "skip"), children: labels.keepCurrent }),
|
|
101
|
+
/* @__PURE__ */ jsx("button", { type: "button", className: "uix-btn uix-btn--ghost uix-btn--sm", "aria-pressed": resolution === "pending", onClick: () => resolve(entry.path, "pending"), children: labels.markPending })
|
|
78
102
|
] })
|
|
79
103
|
] }, entry.path);
|
|
80
104
|
})
|
|
81
|
-
] },
|
|
105
|
+
] }, kind);
|
|
82
106
|
}),
|
|
83
|
-
/* @__PURE__ */
|
|
84
|
-
summary.resolved,
|
|
85
|
-
" of ",
|
|
86
|
-
entries.length,
|
|
87
|
-
" differences resolved."
|
|
88
|
-
] })
|
|
107
|
+
/* @__PURE__ */ jsx("p", { className: "uix-visually-hidden", "aria-live": "polite", children: fillLabel(labels.progress, { resolved: summary.resolved, total: entries.length }) })
|
|
89
108
|
] });
|
|
90
109
|
}
|
|
91
110
|
export {
|
|
111
|
+
DEFAULT_DIFF_VIEWER_LABELS,
|
|
92
112
|
DiffViewer
|
|
93
113
|
};
|
|
@@ -2,12 +2,14 @@ import * as react from 'react';
|
|
|
2
2
|
import { HTMLAttributes, ReactNode } from 'react';
|
|
3
3
|
|
|
4
4
|
interface DrawerProps extends Omit<HTMLAttributes<HTMLDialogElement>, 'title'> {
|
|
5
|
+
/** TENSOR RX-125 (UIX-04): translatable; English default. */
|
|
6
|
+
closeLabel?: string;
|
|
5
7
|
open: boolean;
|
|
6
8
|
onClose?: () => void;
|
|
7
9
|
title?: ReactNode;
|
|
8
10
|
children?: ReactNode;
|
|
9
11
|
footer?: ReactNode;
|
|
10
12
|
}
|
|
11
|
-
declare function Drawer({ open, onClose, title, children, footer, className, ...rest }: DrawerProps): react.JSX.Element;
|
|
13
|
+
declare function Drawer({ open, onClose, title, children, footer, closeLabel, className, ...rest }: DrawerProps): react.JSX.Element;
|
|
12
14
|
|
|
13
15
|
export { Drawer, type DrawerProps };
|
|
@@ -4,7 +4,7 @@ import { useId } from "react";
|
|
|
4
4
|
import { cx } from "../cx.js";
|
|
5
5
|
import { useDialog } from "../hooks/useDialog.js";
|
|
6
6
|
const CloseIcon = () => /* @__PURE__ */ jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: 1.5, strokeLinecap: "round", "aria-hidden": "true", children: /* @__PURE__ */ jsx("path", { d: "M4 4l8 8M12 4l-8 8" }) });
|
|
7
|
-
function Drawer({ open, onClose, title, children, footer, className, ...rest }) {
|
|
7
|
+
function Drawer({ open, onClose, title, children, footer, closeLabel = "Close drawer", className, ...rest }) {
|
|
8
8
|
const ref = useDialog(open, onClose);
|
|
9
9
|
const titleId = useId();
|
|
10
10
|
return /* @__PURE__ */ jsxs("dialog", { ref, className: cx("uix-drawer", className), "aria-labelledby": title ? titleId : void 0, ...rest, children: [
|
|
@@ -15,7 +15,7 @@ function Drawer({ open, onClose, title, children, footer, className, ...rest })
|
|
|
15
15
|
{
|
|
16
16
|
style: { marginLeft: "auto", border: 0, background: "transparent", color: "var(--uix-text-muted)", cursor: "pointer", width: 30, height: 30, display: "grid", placeItems: "center", borderRadius: "var(--uix-radius-sm)" },
|
|
17
17
|
onClick: onClose,
|
|
18
|
-
"aria-label":
|
|
18
|
+
"aria-label": closeLabel,
|
|
19
19
|
children: /* @__PURE__ */ jsx(CloseIcon, {})
|
|
20
20
|
}
|
|
21
21
|
)
|
|
@@ -13,6 +13,8 @@ interface InboxProps extends HTMLAttributes<HTMLDivElement> {
|
|
|
13
13
|
/** Two-pane inbox master-detail container backed by `.uix-inbox`. Place `<InboxList>` and `<InboxDetail>` as children. */
|
|
14
14
|
declare function Inbox({ view, children, className, ...props }: InboxProps): react.JSX.Element;
|
|
15
15
|
interface InboxListProps extends HTMLAttributes<HTMLDivElement> {
|
|
16
|
+
/** TENSOR RX-125 (UIX-04): translatable; English default. */
|
|
17
|
+
listLabel?: string;
|
|
16
18
|
children?: ReactNode;
|
|
17
19
|
}
|
|
18
20
|
/**
|
|
@@ -20,7 +22,7 @@ interface InboxListProps extends HTMLAttributes<HTMLDivElement> {
|
|
|
20
22
|
* (UIX-A11Y-2): the list is the single tab stop; ArrowUp/ArrowDown/Home/End move the
|
|
21
23
|
* active option via `aria-activedescendant`, Enter/Space click it.
|
|
22
24
|
*/
|
|
23
|
-
declare function InboxList({ children, className, ...props }: InboxListProps): react.JSX.Element;
|
|
25
|
+
declare function InboxList({ children, listLabel, className, ...props }: InboxListProps): react.JSX.Element;
|
|
24
26
|
interface InboxItemProps extends HTMLAttributes<HTMLDivElement> {
|
|
25
27
|
/** Primary subject / title line. */
|
|
26
28
|
subject?: ReactNode;
|
package/dist/components/Inbox.js
CHANGED
|
@@ -6,7 +6,7 @@ function Inbox({ view, children, className, ...props }) {
|
|
|
6
6
|
return /* @__PURE__ */ jsx("div", { className: cx("uix-inbox", className), "data-view": view, ...props, children });
|
|
7
7
|
}
|
|
8
8
|
const InboxListCtx = createContext({});
|
|
9
|
-
function InboxList({ children, className, ...props }) {
|
|
9
|
+
function InboxList({ children, listLabel = "Inbox", className, ...props }) {
|
|
10
10
|
const listRef = useRef(null);
|
|
11
11
|
const [activeId, setActiveId] = useState(void 0);
|
|
12
12
|
const ctx = useMemo(() => ({ activeId }), [activeId]);
|
|
@@ -51,7 +51,7 @@ function InboxList({ children, className, ...props }) {
|
|
|
51
51
|
className: cx("uix-inbox__list", className),
|
|
52
52
|
role: "listbox",
|
|
53
53
|
tabIndex: 0,
|
|
54
|
-
"aria-label":
|
|
54
|
+
"aria-label": listLabel,
|
|
55
55
|
"aria-activedescendant": activeId,
|
|
56
56
|
onKeyDown,
|
|
57
57
|
...props,
|
|
@@ -19,6 +19,52 @@ interface MatchBulkResult {
|
|
|
19
19
|
succeeded: number;
|
|
20
20
|
failed?: number;
|
|
21
21
|
}
|
|
22
|
+
/**
|
|
23
|
+
* Every word the match review renders or announces (TENSOR RX-125, UIX-12). Plural
|
|
24
|
+
* pairs are `…One` / `…Many`; `{count}`, `{pending}`, `{total}`, `{id}` are placeholders.
|
|
25
|
+
*/
|
|
26
|
+
interface MatchReviewLabels {
|
|
27
|
+
region: string;
|
|
28
|
+
loading: string;
|
|
29
|
+
retry: string;
|
|
30
|
+
empty: string;
|
|
31
|
+
emptyDetail: string;
|
|
32
|
+
pendingOf: string;
|
|
33
|
+
bulk: string;
|
|
34
|
+
selectedCount: string;
|
|
35
|
+
applying: string;
|
|
36
|
+
acceptSelected: string;
|
|
37
|
+
dismissSelected: string;
|
|
38
|
+
caption: string;
|
|
39
|
+
select: string;
|
|
40
|
+
confidence: string;
|
|
41
|
+
status: string;
|
|
42
|
+
actions: string;
|
|
43
|
+
selectCandidate: string;
|
|
44
|
+
notScored: string;
|
|
45
|
+
resolved: string;
|
|
46
|
+
pending: string;
|
|
47
|
+
decisionAccepted: string;
|
|
48
|
+
decisionDismissed: string;
|
|
49
|
+
decisionSplit: string;
|
|
50
|
+
decisionOther: string;
|
|
51
|
+
accept: string;
|
|
52
|
+
dismiss: string;
|
|
53
|
+
split: string;
|
|
54
|
+
pickOther: string;
|
|
55
|
+
acceptingOne: string;
|
|
56
|
+
acceptingMany: string;
|
|
57
|
+
dismissingOne: string;
|
|
58
|
+
dismissingMany: string;
|
|
59
|
+
acceptedOne: string;
|
|
60
|
+
acceptedMany: string;
|
|
61
|
+
dismissedOne: string;
|
|
62
|
+
dismissedMany: string;
|
|
63
|
+
failedSuffix: string;
|
|
64
|
+
bulkAcceptFailed: string;
|
|
65
|
+
bulkDismissFailed: string;
|
|
66
|
+
}
|
|
67
|
+
declare const DEFAULT_MATCH_REVIEW_LABELS: MatchReviewLabels;
|
|
22
68
|
interface MatchReviewProps {
|
|
23
69
|
incoming: Record<string, JsonValue>;
|
|
24
70
|
incomingLabel?: string;
|
|
@@ -32,8 +78,9 @@ interface MatchReviewProps {
|
|
|
32
78
|
error?: string;
|
|
33
79
|
onRetry?: () => void;
|
|
34
80
|
className?: string;
|
|
81
|
+
labels?: Partial<MatchReviewLabels>;
|
|
35
82
|
}
|
|
36
83
|
/** Generic descriptor-driven incoming-record to candidate-match decision surface. */
|
|
37
|
-
declare function MatchReview({ incoming, incomingLabel, fields, candidates, selectedIds, onSelectionChange, onDecision, onBulkDecision, loading, error, onRetry, className, }: MatchReviewProps): react.JSX.Element;
|
|
84
|
+
declare function MatchReview({ incoming, incomingLabel, fields, candidates, selectedIds, onSelectionChange, onDecision, onBulkDecision, loading, error, onRetry, className, labels: labelOverrides, }: MatchReviewProps): react.JSX.Element;
|
|
38
85
|
|
|
39
|
-
export { type MatchBulkResult, MatchReview, type MatchReviewAction, type MatchReviewCandidate, type MatchReviewField, type MatchReviewProps };
|
|
86
|
+
export { DEFAULT_MATCH_REVIEW_LABELS, type MatchBulkResult, MatchReview, type MatchReviewAction, type MatchReviewCandidate, type MatchReviewField, type MatchReviewLabels, type MatchReviewProps };
|