@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,6 +3,29 @@ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
|
3
3
|
import { useEffect, useRef, useState } from "react";
|
|
4
4
|
import { cx } from "../cx.js";
|
|
5
5
|
import { reorder } from "../table-engine.js";
|
|
6
|
+
import { fillLabel } from "../fill-label.js";
|
|
7
|
+
const DEFAULT_BUILDER_CANVAS_LABELS = {
|
|
8
|
+
region: "Builder canvas",
|
|
9
|
+
palette: "Item palette",
|
|
10
|
+
paletteHeading: "Palette",
|
|
11
|
+
paletteEmpty: "No item types available.",
|
|
12
|
+
add: "Add",
|
|
13
|
+
addFirst: "Add {label}",
|
|
14
|
+
canvasHeading: "Canvas",
|
|
15
|
+
loading: "Loading canvas\u2026",
|
|
16
|
+
retry: "Try again",
|
|
17
|
+
moveUp: "Up",
|
|
18
|
+
moveUpNamed: "Move {label} up",
|
|
19
|
+
moveDown: "Down",
|
|
20
|
+
moveDownNamed: "Move {label} down",
|
|
21
|
+
remove: "Remove",
|
|
22
|
+
removeNamed: "Remove {label}",
|
|
23
|
+
properties: "Item properties",
|
|
24
|
+
propertiesHeading: "Properties",
|
|
25
|
+
propertiesEmpty: "Select a canvas item to edit its properties.",
|
|
26
|
+
type: "Type",
|
|
27
|
+
label: "Label"
|
|
28
|
+
};
|
|
6
29
|
function BuilderCanvas({
|
|
7
30
|
items,
|
|
8
31
|
onItemsChange,
|
|
@@ -15,8 +38,10 @@ function BuilderCanvas({
|
|
|
15
38
|
error,
|
|
16
39
|
onRetry,
|
|
17
40
|
emptyMessage = "Add an item from the palette to begin.",
|
|
18
|
-
className
|
|
41
|
+
className,
|
|
42
|
+
labels: labelOverrides
|
|
19
43
|
}) {
|
|
44
|
+
const labels = { ...DEFAULT_BUILDER_CANVAS_LABELS, ...labelOverrides };
|
|
20
45
|
const [internalSelectedId, setInternalSelectedId] = useState();
|
|
21
46
|
const [draggedId, setDraggedId] = useState();
|
|
22
47
|
const propertyHeadingRef = useRef(null);
|
|
@@ -57,26 +82,23 @@ function BuilderCanvas({
|
|
|
57
82
|
if (from >= 0 && to >= 0) onItemsChange(reorder(items, from, to));
|
|
58
83
|
setDraggedId(void 0);
|
|
59
84
|
};
|
|
60
|
-
return /* @__PURE__ */ jsxs("section", { className: cx("uix-builder-canvas", className), "aria-label":
|
|
61
|
-
/* @__PURE__ */ jsxs("aside", { className: "uix-builder-canvas__palette", "aria-label":
|
|
62
|
-
/* @__PURE__ */ jsx("h3", { children:
|
|
63
|
-
palette.length === 0 ? /* @__PURE__ */ jsx("p", { children:
|
|
85
|
+
return /* @__PURE__ */ jsxs("section", { className: cx("uix-builder-canvas", className), "aria-label": labels.region, children: [
|
|
86
|
+
/* @__PURE__ */ jsxs("aside", { className: "uix-builder-canvas__palette", "aria-label": labels.palette, children: [
|
|
87
|
+
/* @__PURE__ */ jsx("h3", { children: labels.paletteHeading }),
|
|
88
|
+
palette.length === 0 ? /* @__PURE__ */ jsx("p", { children: labels.paletteEmpty }) : /* @__PURE__ */ jsx("ul", { children: palette.map((item) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsxs("button", { type: "button", onClick: () => add(item), children: [
|
|
64
89
|
/* @__PURE__ */ jsx("strong", { children: item.label }),
|
|
65
90
|
item.description && /* @__PURE__ */ jsx("span", { children: item.description }),
|
|
66
|
-
/* @__PURE__ */ jsx("span", { "aria-hidden": "true", children:
|
|
91
|
+
/* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: labels.add })
|
|
67
92
|
] }) }, item.id)) })
|
|
68
93
|
] }),
|
|
69
94
|
/* @__PURE__ */ jsxs("div", { className: "uix-builder-canvas__workspace", children: [
|
|
70
|
-
/* @__PURE__ */ jsx("h3", { children:
|
|
71
|
-
loading ? /* @__PURE__ */ jsx("div", { className: "uix-builder-canvas__state", role: "status", children:
|
|
95
|
+
/* @__PURE__ */ jsx("h3", { children: labels.canvasHeading }),
|
|
96
|
+
loading ? /* @__PURE__ */ jsx("div", { className: "uix-builder-canvas__state", role: "status", children: labels.loading }) : error ? /* @__PURE__ */ jsxs("div", { className: "uix-builder-canvas__state", role: "alert", children: [
|
|
72
97
|
/* @__PURE__ */ jsx("p", { children: error }),
|
|
73
|
-
onRetry && /* @__PURE__ */ jsx("button", { type: "button", className: "uix-btn uix-btn--secondary", onClick: onRetry, children:
|
|
98
|
+
onRetry && /* @__PURE__ */ jsx("button", { type: "button", className: "uix-btn uix-btn--secondary", onClick: onRetry, children: labels.retry })
|
|
74
99
|
] }) : items.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "uix-builder-canvas__state", children: [
|
|
75
100
|
/* @__PURE__ */ jsx("p", { children: emptyMessage }),
|
|
76
|
-
palette[0] && /* @__PURE__ */
|
|
77
|
-
"Add ",
|
|
78
|
-
palette[0].label
|
|
79
|
-
] })
|
|
101
|
+
palette[0] && /* @__PURE__ */ jsx("button", { type: "button", className: "uix-btn uix-btn--primary", onClick: () => add(palette[0]), children: fillLabel(labels.addFirst, { label: palette[0].label }) })
|
|
80
102
|
] }) : /* @__PURE__ */ jsx("ol", { className: "uix-builder-canvas__items", children: items.map((item, index) => /* @__PURE__ */ jsxs(
|
|
81
103
|
"li",
|
|
82
104
|
{
|
|
@@ -92,26 +114,27 @@ function BuilderCanvas({
|
|
|
92
114
|
item.description && /* @__PURE__ */ jsx("span", { children: item.description })
|
|
93
115
|
] }) }),
|
|
94
116
|
/* @__PURE__ */ jsxs("span", { className: "uix-builder-canvas__item-actions", children: [
|
|
95
|
-
/* @__PURE__ */ jsx("button", { type: "button", onClick: () => move(item.id, -1), disabled: index === 0, "aria-label":
|
|
96
|
-
/* @__PURE__ */ jsx("button", { type: "button", onClick: () => move(item.id, 1), disabled: index === items.length - 1, "aria-label":
|
|
97
|
-
/* @__PURE__ */ jsx("button", { type: "button", onClick: () => remove(item.id), "aria-label":
|
|
117
|
+
/* @__PURE__ */ jsx("button", { type: "button", onClick: () => move(item.id, -1), disabled: index === 0, "aria-label": fillLabel(labels.moveUpNamed, { label: item.label }), children: labels.moveUp }),
|
|
118
|
+
/* @__PURE__ */ jsx("button", { type: "button", onClick: () => move(item.id, 1), disabled: index === items.length - 1, "aria-label": fillLabel(labels.moveDownNamed, { label: item.label }), children: labels.moveDown }),
|
|
119
|
+
/* @__PURE__ */ jsx("button", { type: "button", onClick: () => remove(item.id), "aria-label": fillLabel(labels.removeNamed, { label: item.label }), children: labels.remove })
|
|
98
120
|
] })
|
|
99
121
|
]
|
|
100
122
|
},
|
|
101
123
|
item.id
|
|
102
124
|
)) })
|
|
103
125
|
] }),
|
|
104
|
-
/* @__PURE__ */ jsxs("aside", { className: "uix-builder-canvas__properties", "aria-label":
|
|
105
|
-
/* @__PURE__ */ jsx("h3", { ref: propertyHeadingRef, tabIndex: -1, children:
|
|
106
|
-
!selected ? /* @__PURE__ */ jsx("p", { children:
|
|
107
|
-
/* @__PURE__ */ jsx("dt", { children:
|
|
126
|
+
/* @__PURE__ */ jsxs("aside", { className: "uix-builder-canvas__properties", "aria-label": labels.properties, children: [
|
|
127
|
+
/* @__PURE__ */ jsx("h3", { ref: propertyHeadingRef, tabIndex: -1, children: labels.propertiesHeading }),
|
|
128
|
+
!selected ? /* @__PURE__ */ jsx("p", { children: labels.propertiesEmpty }) : renderProperties?.(selected, (updated) => onItemsChange(items.map((item) => item.id === updated.id ? updated : item))) ?? /* @__PURE__ */ jsxs("dl", { children: [
|
|
129
|
+
/* @__PURE__ */ jsx("dt", { children: labels.type }),
|
|
108
130
|
/* @__PURE__ */ jsx("dd", { children: selected.type }),
|
|
109
|
-
/* @__PURE__ */ jsx("dt", { children:
|
|
131
|
+
/* @__PURE__ */ jsx("dt", { children: labels.label }),
|
|
110
132
|
/* @__PURE__ */ jsx("dd", { children: selected.label })
|
|
111
133
|
] })
|
|
112
134
|
] })
|
|
113
135
|
] });
|
|
114
136
|
}
|
|
115
137
|
export {
|
|
116
|
-
BuilderCanvas
|
|
138
|
+
BuilderCanvas,
|
|
139
|
+
DEFAULT_BUILDER_CANVAS_LABELS
|
|
117
140
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import { ChartProps } from './ChartCore.js';
|
|
3
|
-
export { ChartLegend, ChartLegendItem, ChartLegendItemProps, ChartLegendProps, ChartMetric, ChartMetricProps, ChartTableRow, uixChartPalette } from './ChartCore.js';
|
|
3
|
+
export { ChartLabels, ChartLegend, ChartLegendItem, ChartLegendItemProps, ChartLegendProps, ChartMetric, ChartMetricProps, ChartTableRow, DEFAULT_CHART_LABELS, uixChartPalette } from './ChartCore.js';
|
|
4
4
|
import 'echarts';
|
|
5
5
|
|
|
6
6
|
/** Full-compatibility adapter. Use `@tensor_1/react/chart/preset` for the lean preset. */
|
package/dist/components/Chart.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { jsx } from "react/jsx-runtime";
|
|
3
3
|
import * as echarts from "echarts";
|
|
4
4
|
import { ChartCore } from "./ChartCore.js";
|
|
5
|
-
import { ChartLegend, ChartLegendItem, ChartMetric, uixChartPalette } from "./ChartCore.js";
|
|
5
|
+
import { ChartLegend, ChartLegendItem, ChartMetric, DEFAULT_CHART_LABELS, uixChartPalette } from "./ChartCore.js";
|
|
6
6
|
function Chart(props) {
|
|
7
7
|
return /* @__PURE__ */ jsx(ChartCore, { ...props, engine: echarts });
|
|
8
8
|
}
|
|
@@ -11,5 +11,6 @@ export {
|
|
|
11
11
|
ChartLegend,
|
|
12
12
|
ChartLegendItem,
|
|
13
13
|
ChartMetric,
|
|
14
|
+
DEFAULT_CHART_LABELS,
|
|
14
15
|
uixChartPalette
|
|
15
16
|
};
|
|
@@ -11,6 +11,19 @@ declare function uixChartPalette(): string[];
|
|
|
11
11
|
interface ChartTableRow {
|
|
12
12
|
[key: string]: string | number;
|
|
13
13
|
}
|
|
14
|
+
/**
|
|
15
|
+
* Every word the chart renders itself (TENSOR RX-125, UIX-04 / UIX-05). The
|
|
16
|
+
* loading text used to live in CSS `content:`, where nothing could translate it.
|
|
17
|
+
*/
|
|
18
|
+
interface ChartLabels {
|
|
19
|
+
/** Shown (and announced inside the busy region) while `loading`. */
|
|
20
|
+
loading: ReactNode;
|
|
21
|
+
/** Accessible name when neither `ariaLabel` nor `title` is given. */
|
|
22
|
+
chart: string;
|
|
23
|
+
/** Appended to the chart's name for its data-table alternative. */
|
|
24
|
+
dataTableSuffix: string;
|
|
25
|
+
}
|
|
26
|
+
declare const DEFAULT_CHART_LABELS: ChartLabels;
|
|
14
27
|
interface ChartProps {
|
|
15
28
|
option: EChartsOption;
|
|
16
29
|
title?: string;
|
|
@@ -27,12 +40,14 @@ interface ChartProps {
|
|
|
27
40
|
footer?: ReactNode;
|
|
28
41
|
loading?: boolean;
|
|
29
42
|
empty?: ReactNode;
|
|
43
|
+
/** Translatable words; English defaults in {@link DEFAULT_CHART_LABELS}. */
|
|
44
|
+
labels?: Partial<ChartLabels>;
|
|
30
45
|
}
|
|
31
46
|
interface ChartCoreProps extends ChartProps {
|
|
32
47
|
engine: ChartEngine;
|
|
33
48
|
}
|
|
34
49
|
/** Shared chart lifecycle. Runtime adapters only choose the ECharts build. */
|
|
35
|
-
declare function ChartCore({ engine, option, title, subtitle, height, className, style, ariaLabel, tableData, tableHeaders, onReady, header, headerAction, footer, loading, empty, }: ChartCoreProps): react.JSX.Element;
|
|
50
|
+
declare function ChartCore({ engine, option, title, subtitle, height, className, style, ariaLabel, tableData, tableHeaders, onReady, header, headerAction, footer, loading, empty, labels: labelOverrides, }: ChartCoreProps): react.JSX.Element;
|
|
36
51
|
interface ChartMetricProps extends HTMLAttributes<HTMLDivElement> {
|
|
37
52
|
value: ReactNode;
|
|
38
53
|
label?: ReactNode;
|
|
@@ -51,4 +66,4 @@ interface ChartLegendItemProps extends HTMLAttributes<HTMLLIElement> {
|
|
|
51
66
|
}
|
|
52
67
|
declare function ChartLegendItem({ label, color, swatch, className, style, ...props }: ChartLegendItemProps): react.JSX.Element;
|
|
53
68
|
|
|
54
|
-
export { ChartCore, type ChartEngine, ChartLegend, ChartLegendItem, type ChartLegendItemProps, type ChartLegendProps, ChartMetric, type ChartMetricProps, type ChartProps, type ChartTableRow, uixChartPalette };
|
|
69
|
+
export { ChartCore, type ChartEngine, type ChartLabels, ChartLegend, ChartLegendItem, type ChartLegendItemProps, type ChartLegendProps, ChartMetric, type ChartMetricProps, type ChartProps, type ChartTableRow, DEFAULT_CHART_LABELS, uixChartPalette };
|
|
@@ -15,6 +15,11 @@ function motionSafe(option) {
|
|
|
15
15
|
}
|
|
16
16
|
return option;
|
|
17
17
|
}
|
|
18
|
+
const DEFAULT_CHART_LABELS = {
|
|
19
|
+
loading: "Loading chart\u2026",
|
|
20
|
+
chart: "Chart",
|
|
21
|
+
dataTableSuffix: "data table"
|
|
22
|
+
};
|
|
18
23
|
function ChartCore({
|
|
19
24
|
engine,
|
|
20
25
|
option,
|
|
@@ -31,8 +36,10 @@ function ChartCore({
|
|
|
31
36
|
headerAction,
|
|
32
37
|
footer,
|
|
33
38
|
loading = false,
|
|
34
|
-
empty
|
|
39
|
+
empty,
|
|
40
|
+
labels: labelOverrides
|
|
35
41
|
}) {
|
|
42
|
+
const labels = { ...DEFAULT_CHART_LABELS, ...labelOverrides };
|
|
36
43
|
const containerRef = useRef(null);
|
|
37
44
|
const chartRef = useRef(null);
|
|
38
45
|
const appliedOptionRef = useRef(null);
|
|
@@ -87,7 +94,7 @@ function ChartCore({
|
|
|
87
94
|
appliedOptionRef.current = option;
|
|
88
95
|
}, [option]);
|
|
89
96
|
const heightValue = typeof height === "number" ? `${height}px` : height;
|
|
90
|
-
const effectiveAriaLabel = ariaLabel ?? title ??
|
|
97
|
+
const effectiveAriaLabel = ariaLabel ?? title ?? labels.chart;
|
|
91
98
|
const hasTable = Boolean(tableData?.length && tableHeaders?.length);
|
|
92
99
|
return /* @__PURE__ */ jsxs("div", { className: cx("uix-chart", className), style, children: [
|
|
93
100
|
title != null || subtitle != null || header != null || headerAction != null ? /* @__PURE__ */ jsxs("div", { className: "uix-chart__header", children: [
|
|
@@ -98,17 +105,20 @@ function ChartCore({
|
|
|
98
105
|
] }),
|
|
99
106
|
headerAction
|
|
100
107
|
] }) : null,
|
|
101
|
-
hasEmpty ? /* @__PURE__ */ jsx("div", { className: "uix-chart__plot", "data-empty": true, children: empty }) : /* @__PURE__ */
|
|
102
|
-
"
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
108
|
+
hasEmpty ? /* @__PURE__ */ jsx("div", { className: "uix-chart__plot", "data-empty": true, children: empty }) : /* @__PURE__ */ jsxs("div", { className: "uix-chart__plot", "data-loading": loading || void 0, "aria-busy": loading || void 0, children: [
|
|
109
|
+
loading ? /* @__PURE__ */ jsx("span", { className: "uix-chart__loading", children: labels.loading }) : null,
|
|
110
|
+
/* @__PURE__ */ jsx(
|
|
111
|
+
"div",
|
|
112
|
+
{
|
|
113
|
+
ref: containerRef,
|
|
114
|
+
style: { height: heightValue },
|
|
115
|
+
role: "img",
|
|
116
|
+
"aria-label": effectiveAriaLabel,
|
|
117
|
+
"aria-describedby": hasTable ? tableId : void 0
|
|
118
|
+
}
|
|
119
|
+
)
|
|
120
|
+
] }),
|
|
121
|
+
hasTable ? /* @__PURE__ */ jsxs("table", { id: tableId, className: "uix-visually-hidden", "aria-label": `${effectiveAriaLabel} \u2014 ${labels.dataTableSuffix}`, children: [
|
|
112
122
|
/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsx("tr", { children: tableHeaders.map((label) => /* @__PURE__ */ jsx("th", { scope: "col", children: label }, label)) }) }),
|
|
113
123
|
/* @__PURE__ */ jsx("tbody", { children: tableData.map((row, index) => /* @__PURE__ */ jsx("tr", { children: tableHeaders.map((label) => /* @__PURE__ */ jsx("td", { children: row[label] }, label)) }, index)) })
|
|
114
124
|
] }) : null,
|
|
@@ -137,5 +147,6 @@ export {
|
|
|
137
147
|
ChartLegend,
|
|
138
148
|
ChartLegendItem,
|
|
139
149
|
ChartMetric,
|
|
150
|
+
DEFAULT_CHART_LABELS,
|
|
140
151
|
uixChartPalette
|
|
141
152
|
};
|
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Every word the colour picker renders (TENSOR RX-125, UIX-12). `{label}`, `{color}`,
|
|
5
|
+
* `{ratio}` and `{minimum}` are placeholders; `sample` is the contrast preview text.
|
|
6
|
+
*/
|
|
7
|
+
interface ColorPickerLabels {
|
|
8
|
+
trigger: string;
|
|
9
|
+
sample: string;
|
|
10
|
+
hue: string;
|
|
11
|
+
saturation: string;
|
|
12
|
+
brightness: string;
|
|
13
|
+
hex: string;
|
|
14
|
+
set: string;
|
|
15
|
+
presets: string;
|
|
16
|
+
recent: string;
|
|
17
|
+
usePreset: string;
|
|
18
|
+
useRecent: string;
|
|
19
|
+
contrastPasses: string;
|
|
20
|
+
contrastFails: string;
|
|
21
|
+
done: string;
|
|
22
|
+
}
|
|
23
|
+
declare const DEFAULT_COLOR_PICKER_LABELS: ColorPickerLabels;
|
|
3
24
|
interface ColorPickerProps {
|
|
4
25
|
value: string;
|
|
5
26
|
onChange: (value: string) => void;
|
|
@@ -10,8 +31,9 @@ interface ColorPickerProps {
|
|
|
10
31
|
label?: string;
|
|
11
32
|
disabled?: boolean;
|
|
12
33
|
className?: string;
|
|
34
|
+
labels?: Partial<ColorPickerLabels>;
|
|
13
35
|
}
|
|
14
36
|
/** Token-friendly HSV/hex picker with a fully keyboard-operable path and contrast feedback. */
|
|
15
|
-
declare function ColorPicker({ value, onChange, foreground, presets, recent, minimumContrast, label, disabled, className, }: ColorPickerProps): react.JSX.Element;
|
|
37
|
+
declare function ColorPicker({ value, onChange, foreground, presets, recent, minimumContrast, label, disabled, className, labels: labelOverrides, }: ColorPickerProps): react.JSX.Element;
|
|
16
38
|
|
|
17
|
-
export { ColorPicker, type ColorPickerProps };
|
|
39
|
+
export { ColorPicker, type ColorPickerLabels, type ColorPickerProps, DEFAULT_COLOR_PICKER_LABELS };
|
|
@@ -3,6 +3,23 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
3
3
|
import { useEffect, useId, useMemo, useRef, useState } from "react";
|
|
4
4
|
import { cx } from "../cx.js";
|
|
5
5
|
import { contrastRatio, hexToRgb, hsvToHex, normalizeHex, rgbToHsv } from "../color-model.js";
|
|
6
|
+
import { fillLabel } from "../fill-label.js";
|
|
7
|
+
const DEFAULT_COLOR_PICKER_LABELS = {
|
|
8
|
+
trigger: "{label}: {color}",
|
|
9
|
+
sample: "Aa",
|
|
10
|
+
hue: "Hue",
|
|
11
|
+
saturation: "Saturation",
|
|
12
|
+
brightness: "Brightness",
|
|
13
|
+
hex: "Hex",
|
|
14
|
+
set: "Set",
|
|
15
|
+
presets: "Presets",
|
|
16
|
+
recent: "Recent",
|
|
17
|
+
usePreset: "Use preset {color}",
|
|
18
|
+
useRecent: "Use recent color {color}",
|
|
19
|
+
contrastPasses: "Contrast {ratio}:1 \u2014 passes WCAG AA ({minimum}:1)",
|
|
20
|
+
contrastFails: "Contrast {ratio}:1 \u2014 does not meet WCAG AA ({minimum}:1)",
|
|
21
|
+
done: "Done"
|
|
22
|
+
};
|
|
6
23
|
const EMPTY_COLORS = [];
|
|
7
24
|
function ColorPicker({
|
|
8
25
|
value,
|
|
@@ -13,8 +30,10 @@ function ColorPicker({
|
|
|
13
30
|
minimumContrast = 4.5,
|
|
14
31
|
label = "Choose color",
|
|
15
32
|
disabled,
|
|
16
|
-
className
|
|
33
|
+
className,
|
|
34
|
+
labels: labelOverrides
|
|
17
35
|
}) {
|
|
36
|
+
const labels = { ...DEFAULT_COLOR_PICKER_LABELS, ...labelOverrides };
|
|
18
37
|
const id = useId();
|
|
19
38
|
const triggerRef = useRef(null);
|
|
20
39
|
const dialogRef = useRef(null);
|
|
@@ -75,7 +94,7 @@ function ColorPicker({
|
|
|
75
94
|
ref: triggerRef,
|
|
76
95
|
type: "button",
|
|
77
96
|
className: "uix-color-picker__trigger",
|
|
78
|
-
"aria-label":
|
|
97
|
+
"aria-label": fillLabel(labels.trigger, { label, color: normalized }),
|
|
79
98
|
"aria-expanded": open,
|
|
80
99
|
"aria-controls": `${id}-dialog`,
|
|
81
100
|
onClick: () => setOpen((current) => !current),
|
|
@@ -97,9 +116,10 @@ function ColorPicker({
|
|
|
97
116
|
className: "uix-color-picker__popover",
|
|
98
117
|
onKeyDown: onDialogKeyDown,
|
|
99
118
|
children: [
|
|
100
|
-
/* @__PURE__ */ jsx("div", { className: "uix-color-picker__preview", style: sampleStyle, children: /* @__PURE__ */ jsx("span", { style: { color: foreground }, children:
|
|
119
|
+
/* @__PURE__ */ jsx("div", { className: "uix-color-picker__preview", style: sampleStyle, children: /* @__PURE__ */ jsx("span", { style: { color: foreground }, children: labels.sample }) }),
|
|
101
120
|
/* @__PURE__ */ jsxs("label", { className: "uix-color-picker__range", children: [
|
|
102
|
-
|
|
121
|
+
labels.hue,
|
|
122
|
+
" ",
|
|
103
123
|
/* @__PURE__ */ jsxs("span", { children: [
|
|
104
124
|
Math.round(hsv.h),
|
|
105
125
|
"\xB0"
|
|
@@ -107,7 +127,8 @@ function ColorPicker({
|
|
|
107
127
|
/* @__PURE__ */ jsx("input", { type: "range", min: "0", max: "359", value: Math.round(hsv.h), onChange: (event) => updateHsv({ h: Number(event.currentTarget.value) }) })
|
|
108
128
|
] }),
|
|
109
129
|
/* @__PURE__ */ jsxs("label", { className: "uix-color-picker__range", children: [
|
|
110
|
-
|
|
130
|
+
labels.saturation,
|
|
131
|
+
" ",
|
|
111
132
|
/* @__PURE__ */ jsxs("span", { children: [
|
|
112
133
|
Math.round(hsv.s * 100),
|
|
113
134
|
"%"
|
|
@@ -115,7 +136,8 @@ function ColorPicker({
|
|
|
115
136
|
/* @__PURE__ */ jsx("input", { type: "range", min: "0", max: "100", value: Math.round(hsv.s * 100), onChange: (event) => updateHsv({ s: Number(event.currentTarget.value) / 100 }) })
|
|
116
137
|
] }),
|
|
117
138
|
/* @__PURE__ */ jsxs("label", { className: "uix-color-picker__range", children: [
|
|
118
|
-
|
|
139
|
+
labels.brightness,
|
|
140
|
+
" ",
|
|
119
141
|
/* @__PURE__ */ jsxs("span", { children: [
|
|
120
142
|
Math.round(hsv.v * 100),
|
|
121
143
|
"%"
|
|
@@ -123,36 +145,32 @@ function ColorPicker({
|
|
|
123
145
|
/* @__PURE__ */ jsx("input", { type: "range", min: "0", max: "100", value: Math.round(hsv.v * 100), onChange: (event) => updateHsv({ v: Number(event.currentTarget.value) / 100 }) })
|
|
124
146
|
] }),
|
|
125
147
|
/* @__PURE__ */ jsxs("label", { className: "uix-color-picker__hex", children: [
|
|
126
|
-
|
|
148
|
+
labels.hex,
|
|
127
149
|
/* @__PURE__ */ jsxs("span", { className: "uix-color-picker__hex-row", children: [
|
|
128
150
|
/* @__PURE__ */ jsx("input", { className: "uix-input", value: hexText, onChange: (event) => setHexText(event.currentTarget.value), onBlur: commitHex, onKeyDown: (event) => {
|
|
129
151
|
if (event.key === "Enter") commitHex();
|
|
130
152
|
}, "aria-invalid": !normalizeHex(hexText) }),
|
|
131
|
-
/* @__PURE__ */ jsx("button", { type: "button", className: "uix-btn uix-btn--secondary uix-btn--sm", onClick: commitHex, disabled: !normalizeHex(hexText), children:
|
|
153
|
+
/* @__PURE__ */ jsx("button", { type: "button", className: "uix-btn uix-btn--secondary uix-btn--sm", onClick: commitHex, disabled: !normalizeHex(hexText), children: labels.set })
|
|
132
154
|
] })
|
|
133
155
|
] }),
|
|
134
156
|
(presets.length > 0 || recent.length > 0) && /* @__PURE__ */ jsxs("div", { className: "uix-color-picker__palettes", children: [
|
|
135
157
|
presets.length > 0 && /* @__PURE__ */ jsxs("fieldset", { children: [
|
|
136
|
-
/* @__PURE__ */ jsx("legend", { children:
|
|
137
|
-
/* @__PURE__ */ jsx("div", { children: presets.map((color) => /* @__PURE__ */ jsx("button", { type: "button", className: "uix-color-picker__preset", style: { backgroundColor: normalizeHex(color) ?? color }, onClick: () => choose(color), "aria-label":
|
|
158
|
+
/* @__PURE__ */ jsx("legend", { children: labels.presets }),
|
|
159
|
+
/* @__PURE__ */ jsx("div", { children: presets.map((color) => /* @__PURE__ */ jsx("button", { type: "button", className: "uix-color-picker__preset", style: { backgroundColor: normalizeHex(color) ?? color }, onClick: () => choose(color), "aria-label": fillLabel(labels.usePreset, { color }) }, color)) })
|
|
138
160
|
] }),
|
|
139
161
|
recent.length > 0 && /* @__PURE__ */ jsxs("fieldset", { children: [
|
|
140
|
-
/* @__PURE__ */ jsx("legend", { children:
|
|
141
|
-
/* @__PURE__ */ jsx("div", { children: recent.map((color) => /* @__PURE__ */ jsx("button", { type: "button", className: "uix-color-picker__preset", style: { backgroundColor: normalizeHex(color) ?? color }, onClick: () => choose(color), "aria-label":
|
|
162
|
+
/* @__PURE__ */ jsx("legend", { children: labels.recent }),
|
|
163
|
+
/* @__PURE__ */ jsx("div", { children: recent.map((color) => /* @__PURE__ */ jsx("button", { type: "button", className: "uix-color-picker__preset", style: { backgroundColor: normalizeHex(color) ?? color }, onClick: () => choose(color), "aria-label": fillLabel(labels.useRecent, { color }) }, color)) })
|
|
142
164
|
] })
|
|
143
165
|
] }),
|
|
144
|
-
/* @__PURE__ */
|
|
145
|
-
|
|
146
|
-
ratio.toFixed(2),
|
|
147
|
-
":1 \u2014 ",
|
|
148
|
-
passes ? `passes WCAG AA (${minimumContrast}:1)` : `does not meet WCAG AA (${minimumContrast}:1)`
|
|
149
|
-
] }),
|
|
150
|
-
/* @__PURE__ */ jsx("button", { type: "button", className: "uix-btn uix-btn--primary uix-btn--sm", onClick: close, children: "Done" })
|
|
166
|
+
/* @__PURE__ */ jsx("p", { className: cx("uix-color-picker__contrast", passes ? "uix-color-picker__contrast--pass" : "uix-color-picker__contrast--fail"), role: "status", "aria-live": "polite", children: fillLabel(passes ? labels.contrastPasses : labels.contrastFails, { ratio: ratio.toFixed(2), minimum: minimumContrast }) }),
|
|
167
|
+
/* @__PURE__ */ jsx("button", { type: "button", className: "uix-btn uix-btn--primary uix-btn--sm", onClick: close, children: labels.done })
|
|
151
168
|
]
|
|
152
169
|
}
|
|
153
170
|
)
|
|
154
171
|
] });
|
|
155
172
|
}
|
|
156
173
|
export {
|
|
157
|
-
ColorPicker
|
|
174
|
+
ColorPicker,
|
|
175
|
+
DEFAULT_COLOR_PICKER_LABELS
|
|
158
176
|
};
|
|
@@ -2,6 +2,8 @@ import * as react from 'react';
|
|
|
2
2
|
import { ReactNode, HTMLAttributes, InputHTMLAttributes } from 'react';
|
|
3
3
|
|
|
4
4
|
interface CommandPaletteProps extends HTMLAttributes<HTMLDivElement> {
|
|
5
|
+
/** TENSOR RX-125 (UIX-04): translatable; English default. */
|
|
6
|
+
inputLabel?: string;
|
|
5
7
|
/** Props for the search input (value/onChange/placeholder wired by the consumer). */
|
|
6
8
|
inputProps?: InputHTMLAttributes<HTMLInputElement>;
|
|
7
9
|
children?: ReactNode;
|
|
@@ -12,7 +14,7 @@ interface CommandPaletteProps extends HTMLAttributes<HTMLDivElement> {
|
|
|
12
14
|
* a combobox over the listbox of `CommandItem`s; spreads override every default, so
|
|
13
15
|
* consumers already passing their own roles/labels keep working.
|
|
14
16
|
*/
|
|
15
|
-
declare function CommandPalette({ inputProps, children, className, ...props }: CommandPaletteProps): react.JSX.Element;
|
|
17
|
+
declare function CommandPalette({ inputProps, children, inputLabel, className, ...props }: CommandPaletteProps): react.JSX.Element;
|
|
16
18
|
interface CommandGroupProps {
|
|
17
19
|
label?: ReactNode;
|
|
18
20
|
children?: ReactNode;
|
|
@@ -3,7 +3,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
3
3
|
import { createContext, useCallback, useContext, useEffect, useId, useMemo, useState } from "react";
|
|
4
4
|
import { cx } from "../cx.js";
|
|
5
5
|
const CmdkContext = createContext(null);
|
|
6
|
-
function CommandPalette({ inputProps, children, className, ...props }) {
|
|
6
|
+
function CommandPalette({ inputProps, children, inputLabel = "Command palette", className, ...props }) {
|
|
7
7
|
const listId = useId();
|
|
8
8
|
const [activeId, setActiveId] = useState(null);
|
|
9
9
|
const [count, setCount] = useState(0);
|
|
@@ -30,7 +30,7 @@ function CommandPalette({ inputProps, children, className, ...props }) {
|
|
|
30
30
|
"aria-autocomplete": "list",
|
|
31
31
|
"aria-controls": listId,
|
|
32
32
|
"aria-activedescendant": activeId ?? void 0,
|
|
33
|
-
"aria-label":
|
|
33
|
+
"aria-label": inputLabel,
|
|
34
34
|
...inputProps
|
|
35
35
|
}
|
|
36
36
|
),
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
|
|
3
|
+
interface CopyButtonProps {
|
|
4
|
+
/** The text written to the clipboard. */
|
|
5
|
+
value: string;
|
|
6
|
+
/** Accessible name of the button, e.g. "Copy email". */
|
|
7
|
+
label: string;
|
|
8
|
+
/** Announced through a polite status region after a successful copy, e.g. "Copied". */
|
|
9
|
+
copiedLabel: string;
|
|
10
|
+
/**
|
|
11
|
+
* Announced when the copy fails (no clipboard, or the write was refused), e.g.
|
|
12
|
+
* "Could not copy — select the text instead". Without it a failure is silent: nothing
|
|
13
|
+
* false is shown, but the person is left guessing why nothing happened.
|
|
14
|
+
*/
|
|
15
|
+
failedLabel?: string;
|
|
16
|
+
className?: string;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Icon-only ghost button that copies `value`. On success it shows a check for 1.5 s and
|
|
20
|
+
* announces `copiedLabel`. On failure (no clipboard, or the write was refused) it shows no
|
|
21
|
+
* check and announces `failedLabel` when one is given.
|
|
22
|
+
*/
|
|
23
|
+
declare function CopyButton({ value, label, copiedLabel, failedLabel, className }: CopyButtonProps): react.JSX.Element;
|
|
24
|
+
|
|
25
|
+
export { CopyButton, type CopyButtonProps };
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useEffect, useRef, useState } from "react";
|
|
4
|
+
import { cx } from "../cx.js";
|
|
5
|
+
import { copyText } from "../copy-model.js";
|
|
6
|
+
const CONFIRM_MS = 1500;
|
|
7
|
+
const CopyGlyph = () => /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [
|
|
8
|
+
/* @__PURE__ */ jsx("rect", { width: "14", height: "14", x: "8", y: "8", rx: "2" }),
|
|
9
|
+
/* @__PURE__ */ jsx("path", { d: "M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2" })
|
|
10
|
+
] });
|
|
11
|
+
const CheckGlyph = () => /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: /* @__PURE__ */ jsx("path", { d: "M20 6 9 17l-5-5" }) });
|
|
12
|
+
function CopyButton({ value, label, copiedLabel, failedLabel, className }) {
|
|
13
|
+
const [outcome, setOutcome] = useState("idle");
|
|
14
|
+
const copied = outcome === "copied";
|
|
15
|
+
const timer = useRef(void 0);
|
|
16
|
+
const mounted = useRef(true);
|
|
17
|
+
useEffect(() => {
|
|
18
|
+
mounted.current = true;
|
|
19
|
+
return () => {
|
|
20
|
+
mounted.current = false;
|
|
21
|
+
clearTimeout(timer.current);
|
|
22
|
+
};
|
|
23
|
+
}, []);
|
|
24
|
+
const onClick = async () => {
|
|
25
|
+
const ok = await copyText(value);
|
|
26
|
+
if (!mounted.current) return;
|
|
27
|
+
clearTimeout(timer.current);
|
|
28
|
+
if (!ok && !failedLabel) {
|
|
29
|
+
setOutcome("idle");
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
setOutcome(ok ? "copied" : "failed");
|
|
33
|
+
timer.current = setTimeout(() => setOutcome("idle"), CONFIRM_MS);
|
|
34
|
+
};
|
|
35
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
36
|
+
/* @__PURE__ */ jsx(
|
|
37
|
+
"button",
|
|
38
|
+
{
|
|
39
|
+
type: "button",
|
|
40
|
+
className: cx("uix-btn", "uix-btn--ghost", "uix-btn--icon", "uix-btn--sm", "uix-copy-button", className),
|
|
41
|
+
"aria-label": label,
|
|
42
|
+
"data-copied": copied || void 0,
|
|
43
|
+
onClick,
|
|
44
|
+
children: copied ? /* @__PURE__ */ jsx(CheckGlyph, {}) : /* @__PURE__ */ jsx(CopyGlyph, {})
|
|
45
|
+
}
|
|
46
|
+
),
|
|
47
|
+
/* @__PURE__ */ jsx("span", { role: "status", className: "uix-visually-hidden", children: outcome === "copied" ? copiedLabel : outcome === "failed" ? failedLabel : "" })
|
|
48
|
+
] });
|
|
49
|
+
}
|
|
50
|
+
export {
|
|
51
|
+
CopyButton
|
|
52
|
+
};
|
|
@@ -1,6 +1,23 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import { DateRangeValue } from '../calendar-model.js';
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Every word the picker renders or announces (TENSOR RX-125, UIX-13). `{start}` and
|
|
6
|
+
* `{end}` are replaced with the locale-formatted dates.
|
|
7
|
+
*/
|
|
8
|
+
interface DateRangePickerLabels {
|
|
9
|
+
previous: string;
|
|
10
|
+
previousMonth: string;
|
|
11
|
+
next: string;
|
|
12
|
+
nextMonth: string;
|
|
13
|
+
noneSelected: string;
|
|
14
|
+
startSelected: string;
|
|
15
|
+
rangeSelected: string;
|
|
16
|
+
rangeStart: string;
|
|
17
|
+
rangeEnd: string;
|
|
18
|
+
inRange: string;
|
|
19
|
+
}
|
|
20
|
+
declare const DEFAULT_DATE_RANGE_PICKER_LABELS: DateRangePickerLabels;
|
|
4
21
|
interface DateRangePickerProps {
|
|
5
22
|
value: DateRangeValue;
|
|
6
23
|
onChange: (value: DateRangeValue) => void;
|
|
@@ -16,8 +33,10 @@ interface DateRangePickerProps {
|
|
|
16
33
|
invalidMessage?: string;
|
|
17
34
|
disabled?: boolean;
|
|
18
35
|
className?: string;
|
|
36
|
+
/** Translatable words; English defaults in {@link DEFAULT_DATE_RANGE_PICKER_LABELS}. */
|
|
37
|
+
labels?: Partial<DateRangePickerLabels>;
|
|
19
38
|
}
|
|
20
39
|
/** Controlled, two-month range picker using the UIx calendar language. */
|
|
21
|
-
declare function DateRangePicker({ value, onChange, visibleMonth: controlledMonth, onVisibleMonthChange, months, min, max, isDateDisabled, locale, label, invalid, invalidMessage, disabled, className, }: DateRangePickerProps): react.JSX.Element;
|
|
40
|
+
declare function DateRangePicker({ value, onChange, visibleMonth: controlledMonth, onVisibleMonthChange, months, min, max, isDateDisabled, locale, label, invalid, invalidMessage, disabled, className, labels: labelOverrides, }: DateRangePickerProps): react.JSX.Element;
|
|
22
41
|
|
|
23
|
-
export { DateRangePicker, type DateRangePickerProps };
|
|
42
|
+
export { DEFAULT_DATE_RANGE_PICKER_LABELS, DateRangePicker, type DateRangePickerLabels, type DateRangePickerProps };
|