@tensor_1/react 2.29.0 → 2.30.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 +23 -0
- package/dist/components/SchedulingTimeline.d.ts +109 -0
- package/dist/components/SchedulingTimeline.js +245 -0
- package/dist/index.cjs +664 -303
- package/dist/index.d.cts +174 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +23 -0
- package/dist/labels-context.d.ts +3 -0
- package/dist/scheduling-timeline-model.d.ts +71 -0
- package/dist/scheduling-timeline-model.js +108 -0
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -54,6 +54,7 @@ __export(src_exports, {
|
|
|
54
54
|
ContentList: () => ContentList,
|
|
55
55
|
ContentListItem: () => ContentListItem,
|
|
56
56
|
CopyButton: () => CopyButton,
|
|
57
|
+
DAY: () => DAY,
|
|
57
58
|
DEFAULT_BRAND_PROFILE_EDITOR_LABELS: () => DEFAULT_BRAND_PROFILE_EDITOR_LABELS,
|
|
58
59
|
DEFAULT_BUILDER_CANVAS_LABELS: () => DEFAULT_BUILDER_CANVAS_LABELS,
|
|
59
60
|
DEFAULT_COLOR_PICKER_LABELS: () => DEFAULT_COLOR_PICKER_LABELS,
|
|
@@ -65,6 +66,7 @@ __export(src_exports, {
|
|
|
65
66
|
DEFAULT_RULE_BUILDER_LABELS: () => DEFAULT_RULE_BUILDER_LABELS,
|
|
66
67
|
DEFAULT_SAVE_STATUS_LABELS: () => DEFAULT_SAVE_STATUS_LABELS,
|
|
67
68
|
DEFAULT_SCHEDULING_CALENDAR_LABELS: () => DEFAULT_SCHEDULING_CALENDAR_LABELS,
|
|
69
|
+
DEFAULT_SCHEDULING_TIMELINE_LABELS: () => DEFAULT_SCHEDULING_TIMELINE_LABELS,
|
|
68
70
|
DEFAULT_STEP_STATE_LABELS: () => DEFAULT_STEP_STATE_LABELS,
|
|
69
71
|
DateRangePicker: () => DateRangePicker,
|
|
70
72
|
DescriptionItem: () => DescriptionItem,
|
|
@@ -86,6 +88,7 @@ __export(src_exports, {
|
|
|
86
88
|
Flow: () => Flow,
|
|
87
89
|
FlowNode: () => FlowNode,
|
|
88
90
|
ForbiddenState: () => ForbiddenState,
|
|
91
|
+
HOUR: () => HOUR,
|
|
89
92
|
Highlighted: () => Highlighted,
|
|
90
93
|
Inbox: () => Inbox,
|
|
91
94
|
InboxDetail: () => InboxDetail,
|
|
@@ -143,6 +146,7 @@ __export(src_exports, {
|
|
|
143
146
|
SaveStatus: () => SaveStatus,
|
|
144
147
|
SavedViewMenu: () => SavedViewMenu,
|
|
145
148
|
SchedulingCalendar: () => SchedulingCalendar,
|
|
149
|
+
SchedulingTimeline: () => SchedulingTimeline,
|
|
146
150
|
SearchSuggest: () => SearchSuggest,
|
|
147
151
|
SectionHead: () => SectionHead,
|
|
148
152
|
Segmented: () => Segmented,
|
|
@@ -198,6 +202,7 @@ __export(src_exports, {
|
|
|
198
202
|
createToastApi: () => createToastApi,
|
|
199
203
|
createToastStore: () => createToastStore,
|
|
200
204
|
cx: () => cx,
|
|
205
|
+
defaultTimelineStep: () => defaultTimelineStep,
|
|
201
206
|
enumerateDateSpan: () => enumerateDateSpan,
|
|
202
207
|
filterComboboxOptions: () => filterComboboxOptions,
|
|
203
208
|
findRuleNodeDepth: () => findRuleNodeDepth,
|
|
@@ -211,6 +216,7 @@ __export(src_exports, {
|
|
|
211
216
|
isDateUnavailable: () => isDateUnavailable,
|
|
212
217
|
isRuleGroup: () => isRuleGroup,
|
|
213
218
|
layeredNeighbor: () => layeredNeighbor,
|
|
219
|
+
layoutLane: () => layoutLane,
|
|
214
220
|
layoutLayeredGraph: () => layoutLayeredGraph,
|
|
215
221
|
layoutRelationshipGraph: () => layoutRelationshipGraph,
|
|
216
222
|
mapRuleGroup: () => mapRuleGroup,
|
|
@@ -224,6 +230,8 @@ __export(src_exports, {
|
|
|
224
230
|
parseDateValue: () => parseDateValue,
|
|
225
231
|
parseMetricValue: () => parseMetricValue,
|
|
226
232
|
parseView: () => parseView,
|
|
233
|
+
pixelsToMs: () => pixelsToMs,
|
|
234
|
+
placeSpan: () => placeSpan,
|
|
227
235
|
relationshipNeighbors: () => relationshipNeighbors,
|
|
228
236
|
relativeTimeValue: () => relativeTimeValue,
|
|
229
237
|
removeRuleNode: () => removeRuleNode,
|
|
@@ -238,11 +246,14 @@ __export(src_exports, {
|
|
|
238
246
|
selectAllState: () => selectAllState,
|
|
239
247
|
selectRangeDate: () => selectRangeDate,
|
|
240
248
|
serializeView: () => serializeView,
|
|
249
|
+
shiftSpan: () => shiftSpan,
|
|
241
250
|
shouldVirtualize: () => shouldVirtualize,
|
|
251
|
+
snapToStep: () => snapToStep,
|
|
242
252
|
startOfMonth: () => startOfMonth,
|
|
243
253
|
stepMetricValue: () => stepMetricValue,
|
|
244
254
|
summarizeDiff: () => summarizeDiff,
|
|
245
255
|
summarizeRule: () => summarizeRule,
|
|
256
|
+
timelineTicks: () => timelineTicks,
|
|
246
257
|
toDateKey: () => toDateKey,
|
|
247
258
|
toast: () => toast,
|
|
248
259
|
toggleId: () => toggleId,
|
|
@@ -6743,9 +6754,348 @@ function SchedulingCalendar({
|
|
|
6743
6754
|
] });
|
|
6744
6755
|
}
|
|
6745
6756
|
|
|
6746
|
-
// src/components/
|
|
6757
|
+
// src/components/SchedulingTimeline.tsx
|
|
6747
6758
|
var import_react50 = require("react");
|
|
6759
|
+
|
|
6760
|
+
// src/scheduling-timeline-model.ts
|
|
6761
|
+
var HOUR = 36e5;
|
|
6762
|
+
var DAY = 24 * HOUR;
|
|
6763
|
+
var toMs = (value) => {
|
|
6764
|
+
const ms = typeof value === "number" ? value : Date.parse(value);
|
|
6765
|
+
if (Number.isNaN(ms)) throw new TypeError(`Invalid instant: ${String(value)}`);
|
|
6766
|
+
return ms;
|
|
6767
|
+
};
|
|
6768
|
+
var defaultTimelineStep = (scale) => scale === "hour" ? 15 * 6e4 : scale === "day" ? HOUR : DAY;
|
|
6769
|
+
function zonedParts(ms, timeZone) {
|
|
6770
|
+
const parts = new Intl.DateTimeFormat("en-US", {
|
|
6771
|
+
timeZone,
|
|
6772
|
+
hourCycle: "h23",
|
|
6773
|
+
year: "numeric",
|
|
6774
|
+
month: "numeric",
|
|
6775
|
+
day: "numeric",
|
|
6776
|
+
hour: "numeric",
|
|
6777
|
+
minute: "numeric",
|
|
6778
|
+
weekday: "short"
|
|
6779
|
+
}).formatToParts(new Date(ms));
|
|
6780
|
+
const get = (type) => parts.find((p) => p.type === type)?.value ?? "";
|
|
6781
|
+
return { year: +get("year"), month: +get("month"), day: +get("day"), hour: +get("hour"), minute: +get("minute"), weekday: get("weekday") };
|
|
6782
|
+
}
|
|
6783
|
+
function timelineTicks(range, scale, timeZone, weekStartsOn = 1) {
|
|
6784
|
+
const start = toMs(range.start);
|
|
6785
|
+
const end = toMs(range.end);
|
|
6786
|
+
if (end <= start) return [];
|
|
6787
|
+
const span = end - start;
|
|
6788
|
+
const ticks = [];
|
|
6789
|
+
const weekdays = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
|
|
6790
|
+
const step = scale === "hour" ? 15 * 6e4 : HOUR;
|
|
6791
|
+
let prev = zonedParts(start - step, timeZone);
|
|
6792
|
+
for (let at = Math.ceil(start / step) * step; at <= end && ticks.length < 500; at += step) {
|
|
6793
|
+
const p = zonedParts(at, timeZone);
|
|
6794
|
+
const newHour = p.minute === 0 && (p.hour !== prev.hour || prev.minute !== 0);
|
|
6795
|
+
const newDay = p.day !== prev.day && p.minute === 0;
|
|
6796
|
+
const newMonth = newDay && p.day === 1;
|
|
6797
|
+
const newWeek = newDay && weekdays.indexOf(p.weekday) === weekStartsOn;
|
|
6798
|
+
const isTick = scale === "hour" ? newHour : scale === "day" ? newDay : scale === "week" ? newWeek : newMonth;
|
|
6799
|
+
if (isTick) {
|
|
6800
|
+
const major = scale === "hour" ? newDay : scale === "day" ? newWeek : scale === "week" ? newMonth : p.month === 1;
|
|
6801
|
+
ticks.push({ at, offset: (at - start) / span * 100, major });
|
|
6802
|
+
}
|
|
6803
|
+
prev = p;
|
|
6804
|
+
}
|
|
6805
|
+
return ticks;
|
|
6806
|
+
}
|
|
6807
|
+
function placeSpan(span, range) {
|
|
6808
|
+
const start = toMs(range.start);
|
|
6809
|
+
const end = toMs(range.end);
|
|
6810
|
+
const s = toMs(span.start);
|
|
6811
|
+
const e = Math.max(toMs(span.end), s);
|
|
6812
|
+
if (e < start || s > end || end <= start) return null;
|
|
6813
|
+
const total = end - start;
|
|
6814
|
+
const left = (Math.max(s, start) - start) / total * 100;
|
|
6815
|
+
const right = (Math.min(e, end) - start) / total * 100;
|
|
6816
|
+
return { left, width: Math.max(right - left, 0), clippedStart: s < start, clippedEnd: e > end };
|
|
6817
|
+
}
|
|
6818
|
+
function layoutLane(items, range) {
|
|
6819
|
+
const sorted = [...items].sort((a, b) => toMs(a.start) - toMs(b.start) || toMs(a.end) - toMs(b.end));
|
|
6820
|
+
const rowEnds = [];
|
|
6821
|
+
const placed = [];
|
|
6822
|
+
for (const item of sorted) {
|
|
6823
|
+
const pos = placeSpan(item, range);
|
|
6824
|
+
if (!pos) continue;
|
|
6825
|
+
const s = toMs(item.start);
|
|
6826
|
+
let row = rowEnds.findIndex((end) => end <= s);
|
|
6827
|
+
if (row === -1) {
|
|
6828
|
+
row = rowEnds.length;
|
|
6829
|
+
rowEnds.push(0);
|
|
6830
|
+
}
|
|
6831
|
+
rowEnds[row] = Math.max(toMs(item.end), s);
|
|
6832
|
+
placed.push({ item, ...pos, row, conflict: false });
|
|
6833
|
+
}
|
|
6834
|
+
for (let i = 0; i < placed.length; i++) {
|
|
6835
|
+
for (let j = i + 1; j < placed.length; j++) {
|
|
6836
|
+
const a = placed[i].item;
|
|
6837
|
+
const b = placed[j].item;
|
|
6838
|
+
if (toMs(b.start) >= toMs(a.end)) continue;
|
|
6839
|
+
if (toMs(a.start) < toMs(b.end)) {
|
|
6840
|
+
placed[i].conflict = true;
|
|
6841
|
+
placed[j].conflict = true;
|
|
6842
|
+
}
|
|
6843
|
+
}
|
|
6844
|
+
}
|
|
6845
|
+
return placed;
|
|
6846
|
+
}
|
|
6847
|
+
var snapToStep = (ms, step) => Math.round(ms / step) * step;
|
|
6848
|
+
function shiftSpan(span, delta, mode, step) {
|
|
6849
|
+
const s = toMs(span.start);
|
|
6850
|
+
const e = toMs(span.end);
|
|
6851
|
+
if (mode === "move") return { start: new Date(s + delta).toISOString(), end: new Date(e + delta).toISOString() };
|
|
6852
|
+
return { start: new Date(s).toISOString(), end: new Date(Math.max(e + delta, s + step)).toISOString() };
|
|
6853
|
+
}
|
|
6854
|
+
function pixelsToMs(px, trackWidth, range, step) {
|
|
6855
|
+
if (trackWidth <= 0) return 0;
|
|
6856
|
+
return snapToStep(px / trackWidth * (toMs(range.end) - toMs(range.start)), step);
|
|
6857
|
+
}
|
|
6858
|
+
|
|
6859
|
+
// src/components/SchedulingTimeline.tsx
|
|
6748
6860
|
var import_jsx_runtime73 = require("react/jsx-runtime");
|
|
6861
|
+
var DEFAULT_SCHEDULING_TIMELINE_LABELS = {
|
|
6862
|
+
region: "Schedule timeline in {timeZone}",
|
|
6863
|
+
lanes: "Lanes",
|
|
6864
|
+
item: "{title}, {state}, {start} to {end}{conflict}",
|
|
6865
|
+
conflict: ", overlaps another entry",
|
|
6866
|
+
moveHint: "Shift and an arrow key moves it; Alt, Shift and an arrow key changes when it ends.",
|
|
6867
|
+
moved: "Moved {title} to {start} \u2013 {end}",
|
|
6868
|
+
resized: "{title} now ends {end}",
|
|
6869
|
+
loading: "Loading schedule\u2026",
|
|
6870
|
+
retry: "Try again",
|
|
6871
|
+
empty: "Nothing is scheduled in this range.",
|
|
6872
|
+
windows: "Windows and markers in this range",
|
|
6873
|
+
now: "Now",
|
|
6874
|
+
states: { scheduled: "Scheduled", conflicted: "Conflicted", "in-progress": "In progress", "blackout-violation": "Blackout violation" },
|
|
6875
|
+
overlays: { freeze: "Change freeze", maintenance: "Maintenance window", blackout: "Blackout" }
|
|
6876
|
+
};
|
|
6877
|
+
var TICK_WIDTH = { hour: "3.5rem", day: "7rem", week: "6rem", month: "8rem" };
|
|
6878
|
+
var TICK_FORMAT = {
|
|
6879
|
+
hour: { hour: "2-digit", minute: "2-digit" },
|
|
6880
|
+
day: { weekday: "short", day: "numeric" },
|
|
6881
|
+
week: { day: "numeric", month: "short" },
|
|
6882
|
+
month: { month: "short", year: "numeric" }
|
|
6883
|
+
};
|
|
6884
|
+
function SchedulingTimeline({
|
|
6885
|
+
lanes,
|
|
6886
|
+
items,
|
|
6887
|
+
range,
|
|
6888
|
+
scale = "day",
|
|
6889
|
+
timeZone,
|
|
6890
|
+
locale,
|
|
6891
|
+
overlays = [],
|
|
6892
|
+
markers = [],
|
|
6893
|
+
now,
|
|
6894
|
+
weekStartsOn = 1,
|
|
6895
|
+
tickWidth,
|
|
6896
|
+
step: stepProp,
|
|
6897
|
+
formatTick,
|
|
6898
|
+
formatInstant: formatInstantProp,
|
|
6899
|
+
renderItem,
|
|
6900
|
+
onSelectItem,
|
|
6901
|
+
onMoveItem,
|
|
6902
|
+
loading,
|
|
6903
|
+
error,
|
|
6904
|
+
onRetry,
|
|
6905
|
+
labels: labelOverrides,
|
|
6906
|
+
className
|
|
6907
|
+
}) {
|
|
6908
|
+
const uixLabels = useUixLabels();
|
|
6909
|
+
const labels = {
|
|
6910
|
+
...DEFAULT_SCHEDULING_TIMELINE_LABELS,
|
|
6911
|
+
...uixLabels.schedulingTimeline,
|
|
6912
|
+
...labelOverrides,
|
|
6913
|
+
states: { ...DEFAULT_SCHEDULING_TIMELINE_LABELS.states, ...uixLabels.schedulingTimeline?.states, ...labelOverrides?.states },
|
|
6914
|
+
overlays: { ...DEFAULT_SCHEDULING_TIMELINE_LABELS.overlays, ...uixLabels.schedulingTimeline?.overlays, ...labelOverrides?.overlays }
|
|
6915
|
+
};
|
|
6916
|
+
const id = (0, import_react50.useId)();
|
|
6917
|
+
const step = stepProp ?? defaultTimelineStep(scale);
|
|
6918
|
+
const ticks = (0, import_react50.useMemo)(() => timelineTicks(range, scale, timeZone, weekStartsOn), [range.start, range.end, scale, timeZone, weekStartsOn]);
|
|
6919
|
+
const laneLayouts = (0, import_react50.useMemo)(
|
|
6920
|
+
() => lanes.map((lane) => ({ lane, placed: layoutLane(items.filter((item) => item.laneId === lane.id), range) })),
|
|
6921
|
+
[lanes, items, range.start, range.end]
|
|
6922
|
+
// eslint-disable-line react-hooks/exhaustive-deps
|
|
6923
|
+
);
|
|
6924
|
+
const ordered = (0, import_react50.useMemo)(() => laneLayouts.flatMap((l) => l.placed.map((p) => p.item.id)), [laneLayouts]);
|
|
6925
|
+
const [activeId, setActiveId] = (0, import_react50.useState)();
|
|
6926
|
+
const focusId = activeId && ordered.includes(activeId) ? activeId : ordered[0];
|
|
6927
|
+
const [drag, setDrag] = (0, import_react50.useState)(null);
|
|
6928
|
+
const [announcement, setAnnouncement] = (0, import_react50.useState)("");
|
|
6929
|
+
const rootRef = (0, import_react50.useRef)(null);
|
|
6930
|
+
const fmtInstant = (instant) => formatInstantProp?.(instant) ?? new Intl.DateTimeFormat(locale, { timeZone, dateStyle: "medium", timeStyle: "short" }).format(new Date(instant));
|
|
6931
|
+
const fmtTick = (at) => formatTick?.(new Date(at), scale) ?? new Intl.DateTimeFormat(locale, { timeZone, ...TICK_FORMAT[scale] }).format(new Date(at));
|
|
6932
|
+
const movable = (item) => !!onMoveItem && item.movable !== false;
|
|
6933
|
+
const focusItem = (itemId) => {
|
|
6934
|
+
if (!itemId) return;
|
|
6935
|
+
setActiveId(itemId);
|
|
6936
|
+
requestAnimationFrame(() => rootRef.current?.querySelector(`[data-timeline-item="${CSS.escape(itemId)}"]`)?.focus());
|
|
6937
|
+
};
|
|
6938
|
+
const commit = (item, delta, mode) => {
|
|
6939
|
+
if (!onMoveItem || delta === 0) return;
|
|
6940
|
+
const next = shiftSpan(item, delta, mode, step);
|
|
6941
|
+
onMoveItem(item.id, next);
|
|
6942
|
+
setAnnouncement(mode === "move" ? fillLabel(labels.moved, { title: item.title, start: fmtInstant(next.start), end: fmtInstant(next.end) }) : fillLabel(labels.resized, { title: item.title, end: fmtInstant(next.end) }));
|
|
6943
|
+
};
|
|
6944
|
+
const onItemKeyDown = (event, laneIndex, placed, index) => {
|
|
6945
|
+
const item = placed[index].item;
|
|
6946
|
+
const horizontal = event.key === "ArrowLeft" ? -1 : event.key === "ArrowRight" ? 1 : 0;
|
|
6947
|
+
if (horizontal && event.shiftKey && movable(item)) {
|
|
6948
|
+
event.preventDefault();
|
|
6949
|
+
commit(item, horizontal * step, event.altKey ? "resize" : "move");
|
|
6950
|
+
return;
|
|
6951
|
+
}
|
|
6952
|
+
if (horizontal) {
|
|
6953
|
+
event.preventDefault();
|
|
6954
|
+
focusItem(placed[index + horizontal]?.item.id);
|
|
6955
|
+
return;
|
|
6956
|
+
}
|
|
6957
|
+
if (event.key === "Home" || event.key === "End") {
|
|
6958
|
+
event.preventDefault();
|
|
6959
|
+
focusItem((event.key === "Home" ? placed[0] : placed[placed.length - 1])?.item.id);
|
|
6960
|
+
return;
|
|
6961
|
+
}
|
|
6962
|
+
const vertical = event.key === "ArrowUp" ? -1 : event.key === "ArrowDown" ? 1 : 0;
|
|
6963
|
+
if (vertical) {
|
|
6964
|
+
event.preventDefault();
|
|
6965
|
+
const start = Date.parse(item.start);
|
|
6966
|
+
for (let l = laneIndex + vertical; l >= 0 && l < laneLayouts.length; l += vertical) {
|
|
6967
|
+
const candidates = laneLayouts[l].placed;
|
|
6968
|
+
if (candidates.length === 0) continue;
|
|
6969
|
+
const nearest = candidates.reduce((best, p) => Math.abs(Date.parse(p.item.start) - start) < Math.abs(Date.parse(best.item.start) - start) ? p : best);
|
|
6970
|
+
focusItem(nearest.item.id);
|
|
6971
|
+
return;
|
|
6972
|
+
}
|
|
6973
|
+
}
|
|
6974
|
+
};
|
|
6975
|
+
const onPointerDown = (event, item) => {
|
|
6976
|
+
if (!movable(item) || event.button !== 0) return;
|
|
6977
|
+
const track = event.currentTarget.closest(".uix-scheduling-timeline__track");
|
|
6978
|
+
if (!track) return;
|
|
6979
|
+
event.currentTarget.setPointerCapture?.(event.pointerId);
|
|
6980
|
+
setDrag({ id: item.id, x: event.clientX, width: track.getBoundingClientRect().width, delta: 0, moved: false });
|
|
6981
|
+
};
|
|
6982
|
+
const onPointerMove = (event) => {
|
|
6983
|
+
if (!drag) return;
|
|
6984
|
+
const dx = event.clientX - drag.x;
|
|
6985
|
+
const delta = pixelsToMs(dx, drag.width, range, step);
|
|
6986
|
+
if (delta !== drag.delta || !drag.moved && Math.abs(dx) > 3) setDrag({ ...drag, delta, moved: drag.moved || Math.abs(dx) > 3 });
|
|
6987
|
+
};
|
|
6988
|
+
const onPointerUp = (item) => {
|
|
6989
|
+
if (!drag || drag.id !== item.id) return;
|
|
6990
|
+
if (drag.moved) commit(item, drag.delta, "move");
|
|
6991
|
+
setDrag(drag.moved ? { ...drag, delta: 0 } : null);
|
|
6992
|
+
if (drag.moved) window.setTimeout(() => setDrag(null), 0);
|
|
6993
|
+
};
|
|
6994
|
+
const nowPos = now ? placeSpan({ start: now, end: now }, range) : null;
|
|
6995
|
+
const overlaysFor = (laneId) => overlays.filter((o) => !o.laneId || o.laneId === laneId);
|
|
6996
|
+
const markersFor = (laneId) => markers.filter((m) => !m.laneId || m.laneId === laneId);
|
|
6997
|
+
const trackStyle = { minWidth: `calc(${Math.max(ticks.length - 1, 1)} * ${tickWidth ?? TICK_WIDTH[scale]})` };
|
|
6998
|
+
const band = (o, showLabel) => {
|
|
6999
|
+
const pos = placeSpan(o, range);
|
|
7000
|
+
return pos && /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { className: "uix-scheduling-timeline__overlay", "data-kind": o.kind, style: { left: `${pos.left}%`, width: `${pos.width}%` }, children: showLabel && /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { className: "uix-scheduling-timeline__overlay-label", children: o.label }) }, o.id);
|
|
7001
|
+
};
|
|
7002
|
+
return /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("section", { ref: rootRef, className: cx("uix-scheduling-timeline", className), "aria-label": fillLabel(labels.region, { timeZone }), children: [
|
|
7003
|
+
loading ? /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("div", { className: "uix-scheduling-timeline__state", role: "status", children: labels.loading }) : error ? /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("div", { className: "uix-scheduling-timeline__state", role: "alert", children: [
|
|
7004
|
+
/* @__PURE__ */ (0, import_jsx_runtime73.jsx)("p", { children: error }),
|
|
7005
|
+
onRetry && /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("button", { type: "button", className: "uix-btn uix-btn--secondary", onClick: onRetry, children: labels.retry })
|
|
7006
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)(import_jsx_runtime73.Fragment, { children: [
|
|
7007
|
+
(overlays.length > 0 || markers.length > 0) && /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("div", { className: "uix-visually-hidden", children: [
|
|
7008
|
+
/* @__PURE__ */ (0, import_jsx_runtime73.jsx)("p", { id: `${id}-windows`, children: labels.windows }),
|
|
7009
|
+
/* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("ul", { "aria-labelledby": `${id}-windows`, children: [
|
|
7010
|
+
overlays.map((o) => /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("li", { children: [
|
|
7011
|
+
labels.overlays[o.kind],
|
|
7012
|
+
": ",
|
|
7013
|
+
o.label,
|
|
7014
|
+
", ",
|
|
7015
|
+
fmtInstant(o.start),
|
|
7016
|
+
" \u2013 ",
|
|
7017
|
+
fmtInstant(o.end)
|
|
7018
|
+
] }, o.id)),
|
|
7019
|
+
markers.map((m) => /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("li", { children: [
|
|
7020
|
+
m.label,
|
|
7021
|
+
", ",
|
|
7022
|
+
fmtInstant(m.at)
|
|
7023
|
+
] }, m.id))
|
|
7024
|
+
] })
|
|
7025
|
+
] }),
|
|
7026
|
+
/* @__PURE__ */ (0, import_jsx_runtime73.jsx)("div", { className: "uix-scheduling-timeline__scroller", children: /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("div", { className: "uix-scheduling-timeline__grid", children: [
|
|
7027
|
+
/* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("div", { className: "uix-scheduling-timeline__row uix-scheduling-timeline__row--axis", "aria-hidden": "true", children: [
|
|
7028
|
+
/* @__PURE__ */ (0, import_jsx_runtime73.jsx)("div", { className: "uix-scheduling-timeline__lane-label", children: labels.lanes }),
|
|
7029
|
+
/* @__PURE__ */ (0, import_jsx_runtime73.jsx)("div", { className: "uix-scheduling-timeline__track uix-scheduling-timeline__axis", style: trackStyle, children: ticks.map((tick) => /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { className: "uix-scheduling-timeline__tick", "data-major": tick.major || void 0, style: { left: `${tick.offset}%` }, children: tick.offset < 100 && /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { className: "uix-scheduling-timeline__tick-label", children: fmtTick(tick.at) }) }, tick.at)) })
|
|
7030
|
+
] }),
|
|
7031
|
+
laneLayouts.map(({ lane, placed }, laneIndex) => {
|
|
7032
|
+
const rows = placed.reduce((max, p) => Math.max(max, p.row + 1), 1);
|
|
7033
|
+
const laneLabelId = `${id}-lane-${laneIndex}`;
|
|
7034
|
+
return /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("div", { className: "uix-scheduling-timeline__row", style: { "--uix-timeline-rows": rows }, children: [
|
|
7035
|
+
/* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("div", { className: "uix-scheduling-timeline__lane-label", id: laneLabelId, children: [
|
|
7036
|
+
/* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { className: "uix-scheduling-timeline__lane-name", children: lane.label }),
|
|
7037
|
+
lane.meta != null && /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { className: "uix-scheduling-timeline__lane-meta", children: lane.meta })
|
|
7038
|
+
] }),
|
|
7039
|
+
/* @__PURE__ */ (0, import_jsx_runtime73.jsxs)("div", { className: "uix-scheduling-timeline__track", style: trackStyle, children: [
|
|
7040
|
+
ticks.map((tick) => /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { className: "uix-scheduling-timeline__gridline", "data-major": tick.major || void 0, style: { left: `${tick.offset}%` }, "aria-hidden": "true" }, tick.at)),
|
|
7041
|
+
/* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { "aria-hidden": "true", children: overlaysFor(lane.id).map((o) => band(o, laneIndex === 0 || !!o.laneId)) }),
|
|
7042
|
+
nowPos && /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { className: "uix-scheduling-timeline__now", style: { left: `${nowPos.left}%` }, "aria-hidden": "true", children: laneIndex === 0 && /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { className: "uix-scheduling-timeline__now-label", children: labels.now }) }),
|
|
7043
|
+
markersFor(lane.id).map((m) => {
|
|
7044
|
+
const pos = placeSpan({ start: m.at, end: m.at }, range);
|
|
7045
|
+
return pos && /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { className: "uix-scheduling-timeline__marker", style: { left: `${pos.left}%` }, title: m.label, "aria-hidden": "true" }, m.id);
|
|
7046
|
+
}),
|
|
7047
|
+
/* @__PURE__ */ (0, import_jsx_runtime73.jsx)("ul", { className: "uix-scheduling-timeline__items", "aria-labelledby": laneLabelId, children: placed.map((p, index) => {
|
|
7048
|
+
const item = p.item;
|
|
7049
|
+
const state = item.state ?? "scheduled";
|
|
7050
|
+
const dragging = drag?.id === item.id && drag.moved;
|
|
7051
|
+
const shown = dragging && drag ? placeSpan(shiftSpan(item, drag.delta, "move", step), range) ?? p : p;
|
|
7052
|
+
return /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("li", { className: "uix-scheduling-timeline__slot", style: { left: `${shown.left}%`, width: `${shown.width}%`, "--uix-timeline-row": p.row }, children: /* @__PURE__ */ (0, import_jsx_runtime73.jsxs)(
|
|
7053
|
+
"button",
|
|
7054
|
+
{
|
|
7055
|
+
type: "button",
|
|
7056
|
+
className: "uix-scheduling-timeline__item",
|
|
7057
|
+
"data-timeline-item": item.id,
|
|
7058
|
+
title: item.title,
|
|
7059
|
+
"data-state": state,
|
|
7060
|
+
"data-conflict": p.conflict || void 0,
|
|
7061
|
+
"data-clipped-start": p.clippedStart || void 0,
|
|
7062
|
+
"data-clipped-end": p.clippedEnd || void 0,
|
|
7063
|
+
"data-movable": movable(item) || void 0,
|
|
7064
|
+
"data-dragging": dragging || void 0,
|
|
7065
|
+
tabIndex: focusId === item.id ? 0 : -1,
|
|
7066
|
+
"aria-label": fillLabel(labels.item, { title: item.title, state: labels.states[state], start: fmtInstant(item.start), end: fmtInstant(item.end), conflict: p.conflict ? labels.conflict : "" }),
|
|
7067
|
+
"aria-describedby": movable(item) ? `${id}-hint` : void 0,
|
|
7068
|
+
onFocus: () => setActiveId(item.id),
|
|
7069
|
+
onKeyDown: (event) => onItemKeyDown(event, laneIndex, placed, index),
|
|
7070
|
+
onPointerDown: (event) => onPointerDown(event, item),
|
|
7071
|
+
onPointerMove,
|
|
7072
|
+
onPointerUp: () => onPointerUp(item),
|
|
7073
|
+
onPointerCancel: () => setDrag(null),
|
|
7074
|
+
onClick: () => {
|
|
7075
|
+
if (drag?.moved) return;
|
|
7076
|
+
onSelectItem?.(item);
|
|
7077
|
+
},
|
|
7078
|
+
children: [
|
|
7079
|
+
/* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { className: "uix-scheduling-timeline__item-title", children: renderItem?.(item) ?? item.title }),
|
|
7080
|
+
item.meta && /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { className: "uix-scheduling-timeline__item-meta", children: item.meta })
|
|
7081
|
+
]
|
|
7082
|
+
}
|
|
7083
|
+
) }, item.id);
|
|
7084
|
+
}) })
|
|
7085
|
+
] })
|
|
7086
|
+
] }, lane.id);
|
|
7087
|
+
})
|
|
7088
|
+
] }) }),
|
|
7089
|
+
ordered.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("p", { className: "uix-scheduling-timeline__empty", children: labels.empty })
|
|
7090
|
+
] }),
|
|
7091
|
+
onMoveItem && /* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { id: `${id}-hint`, className: "uix-visually-hidden", children: labels.moveHint }),
|
|
7092
|
+
/* @__PURE__ */ (0, import_jsx_runtime73.jsx)("span", { className: "uix-visually-hidden", role: "status", "aria-live": "polite", children: announcement })
|
|
7093
|
+
] });
|
|
7094
|
+
}
|
|
7095
|
+
|
|
7096
|
+
// src/components/DateRangePicker.tsx
|
|
7097
|
+
var import_react51 = require("react");
|
|
7098
|
+
var import_jsx_runtime74 = require("react/jsx-runtime");
|
|
6749
7099
|
var DEFAULT_DATE_RANGE_PICKER_LABELS = {
|
|
6750
7100
|
previous: "Previous",
|
|
6751
7101
|
previousMonth: "Show previous month",
|
|
@@ -6781,28 +7131,28 @@ function DateRangePicker({
|
|
|
6781
7131
|
className,
|
|
6782
7132
|
labels: labelOverrides
|
|
6783
7133
|
}) {
|
|
6784
|
-
const id = (0,
|
|
7134
|
+
const id = (0, import_react51.useId)();
|
|
6785
7135
|
const uixLabels = useUixLabels();
|
|
6786
7136
|
const labels = { ...DEFAULT_DATE_RANGE_PICKER_LABELS, ...uixLabels.dateRangePicker, ...labelOverrides };
|
|
6787
|
-
const weekdays = (0,
|
|
6788
|
-
const [internalMonth, setInternalMonth] = (0,
|
|
7137
|
+
const weekdays = (0, import_react51.useMemo)(() => weekdayNames(locale), [locale]);
|
|
7138
|
+
const [internalMonth, setInternalMonth] = (0, import_react51.useState)(() => startOfMonth(controlledMonth ?? value.start ?? (/* @__PURE__ */ new Date()).toISOString().slice(0, 10)));
|
|
6789
7139
|
const visibleMonth = startOfMonth(controlledMonth ?? internalMonth);
|
|
6790
|
-
const [activeDate, setActiveDate] = (0,
|
|
6791
|
-
const rootRef = (0,
|
|
6792
|
-
const pendingFocus = (0,
|
|
7140
|
+
const [activeDate, setActiveDate] = (0, import_react51.useState)(value.end ?? value.start ?? visibleMonth);
|
|
7141
|
+
const rootRef = (0, import_react51.useRef)(null);
|
|
7142
|
+
const pendingFocus = (0, import_react51.useRef)(false);
|
|
6793
7143
|
const count = Math.max(1, Math.min(3, months));
|
|
6794
|
-
const calendars = (0,
|
|
7144
|
+
const calendars = (0, import_react51.useMemo)(() => Array.from({ length: count }, (_, index) => {
|
|
6795
7145
|
const month = startOfMonth(addCalendarMonths(visibleMonth, index));
|
|
6796
7146
|
return { month, days: buildMonthGrid(month).filter((day) => day.inMonth) };
|
|
6797
7147
|
}), [visibleMonth, count]);
|
|
6798
7148
|
const rangeInvalid = invalid || !!value.start && !!value.end && value.start > value.end;
|
|
6799
|
-
(0,
|
|
7149
|
+
(0, import_react51.useEffect)(() => {
|
|
6800
7150
|
const first = calendars[0]?.days[0]?.date;
|
|
6801
7151
|
const finalDays = calendars[calendars.length - 1]?.days;
|
|
6802
7152
|
const last = finalDays?.[finalDays.length - 1]?.date;
|
|
6803
7153
|
if (first && last && (activeDate < first || activeDate > last)) setActiveDate(first);
|
|
6804
7154
|
}, [activeDate, calendars]);
|
|
6805
|
-
(0,
|
|
7155
|
+
(0, import_react51.useEffect)(() => {
|
|
6806
7156
|
if (!pendingFocus.current) return;
|
|
6807
7157
|
rootRef.current?.querySelector(`[data-date="${activeDate}"]`)?.focus();
|
|
6808
7158
|
pendingFocus.current = false;
|
|
@@ -6840,23 +7190,23 @@ function DateRangePicker({
|
|
|
6840
7190
|
}
|
|
6841
7191
|
};
|
|
6842
7192
|
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));
|
|
6843
|
-
return /* @__PURE__ */ (0,
|
|
6844
|
-
/* @__PURE__ */ (0,
|
|
6845
|
-
/* @__PURE__ */ (0,
|
|
6846
|
-
/* @__PURE__ */ (0,
|
|
6847
|
-
/* @__PURE__ */ (0,
|
|
6848
|
-
/* @__PURE__ */ (0,
|
|
7193
|
+
return /* @__PURE__ */ (0, import_jsx_runtime74.jsxs)("section", { className: cx("uix-date-range-picker", rangeInvalid && "uix-date-range-picker--invalid", className), "aria-labelledby": `${id}-label`, children: [
|
|
7194
|
+
/* @__PURE__ */ (0, import_jsx_runtime74.jsxs)("div", { className: "uix-date-range-picker__header", children: [
|
|
7195
|
+
/* @__PURE__ */ (0, import_jsx_runtime74.jsx)("h3", { id: `${id}-label`, children: label }),
|
|
7196
|
+
/* @__PURE__ */ (0, import_jsx_runtime74.jsxs)("div", { children: [
|
|
7197
|
+
/* @__PURE__ */ (0, import_jsx_runtime74.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 }),
|
|
7198
|
+
/* @__PURE__ */ (0, import_jsx_runtime74.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 })
|
|
6849
7199
|
] })
|
|
6850
7200
|
] }),
|
|
6851
|
-
/* @__PURE__ */ (0,
|
|
6852
|
-
/* @__PURE__ */ (0,
|
|
6853
|
-
/* @__PURE__ */ (0,
|
|
6854
|
-
/* @__PURE__ */ (0,
|
|
6855
|
-
Array.from({ length: ((/* @__PURE__ */ new Date(`${month}T00:00:00Z`)).getUTCDay() + 6) % 7 }, (_, index) => /* @__PURE__ */ (0,
|
|
7201
|
+
/* @__PURE__ */ (0, import_jsx_runtime74.jsx)("div", { ref: rootRef, className: "uix-date-range-picker__months", children: calendars.map(({ month, days }) => /* @__PURE__ */ (0, import_jsx_runtime74.jsxs)("div", { className: "uix-date-range-picker__month", children: [
|
|
7202
|
+
/* @__PURE__ */ (0, import_jsx_runtime74.jsx)("h4", { children: monthLabel(month, locale) }),
|
|
7203
|
+
/* @__PURE__ */ (0, import_jsx_runtime74.jsx)("div", { className: "uix-date-range-picker__weekdays", "aria-hidden": "true", children: weekdays.map((day, index) => /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("span", { children: day }, index)) }),
|
|
7204
|
+
/* @__PURE__ */ (0, import_jsx_runtime74.jsxs)("div", { className: "uix-date-range-picker__grid", role: "group", "aria-label": monthLabel(month, locale), children: [
|
|
7205
|
+
Array.from({ length: ((/* @__PURE__ */ new Date(`${month}T00:00:00Z`)).getUTCDay() + 6) % 7 }, (_, index) => /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("span", { "aria-hidden": "true" }, `blank-${index}`)),
|
|
6856
7206
|
days.map((day) => {
|
|
6857
7207
|
const unavailable = disabled || isDateUnavailable(day.date, { min, max, isDisabled: isDateDisabled });
|
|
6858
7208
|
const edge = day.date === value.start ? "start" : day.date === value.end ? "end" : void 0;
|
|
6859
|
-
return /* @__PURE__ */ (0,
|
|
7209
|
+
return /* @__PURE__ */ (0, import_jsx_runtime74.jsx)(
|
|
6860
7210
|
"button",
|
|
6861
7211
|
{
|
|
6862
7212
|
type: "button",
|
|
@@ -6877,13 +7227,13 @@ function DateRangePicker({
|
|
|
6877
7227
|
})
|
|
6878
7228
|
] })
|
|
6879
7229
|
] }, month)) }),
|
|
6880
|
-
/* @__PURE__ */ (0,
|
|
6881
|
-
rangeInvalid && /* @__PURE__ */ (0,
|
|
7230
|
+
/* @__PURE__ */ (0, import_jsx_runtime74.jsx)("p", { className: "uix-date-range-picker__selection", "aria-live": "polite", children: announcement }),
|
|
7231
|
+
rangeInvalid && /* @__PURE__ */ (0, import_jsx_runtime74.jsx)("p", { className: "uix-field__error", role: "alert", children: invalidMessage })
|
|
6882
7232
|
] });
|
|
6883
7233
|
}
|
|
6884
7234
|
|
|
6885
7235
|
// src/components/RelationshipGraph.tsx
|
|
6886
|
-
var
|
|
7236
|
+
var import_react53 = require("react");
|
|
6887
7237
|
|
|
6888
7238
|
// src/relationship-graph-model.ts
|
|
6889
7239
|
function boundRelationshipGraph(nodes, edges, maxNodes = 40) {
|
|
@@ -7364,10 +7714,10 @@ function layeredNeighbor(layout, currentId, key) {
|
|
|
7364
7714
|
}
|
|
7365
7715
|
|
|
7366
7716
|
// src/components/RelationshipGraphLayered.tsx
|
|
7367
|
-
var
|
|
7717
|
+
var import_react52 = require("react");
|
|
7368
7718
|
|
|
7369
7719
|
// src/components/RelationshipGraphList.tsx
|
|
7370
|
-
var
|
|
7720
|
+
var import_jsx_runtime75 = require("react/jsx-runtime");
|
|
7371
7721
|
function EquivalentRelationshipList({
|
|
7372
7722
|
nodes,
|
|
7373
7723
|
edges,
|
|
@@ -7378,19 +7728,19 @@ function EquivalentRelationshipList({
|
|
|
7378
7728
|
onOpenDetails
|
|
7379
7729
|
}) {
|
|
7380
7730
|
const labelById = new Map(nodes.map((node) => [node.id, node.label]));
|
|
7381
|
-
return /* @__PURE__ */ (0,
|
|
7382
|
-
/* @__PURE__ */ (0,
|
|
7383
|
-
/* @__PURE__ */ (0,
|
|
7731
|
+
return /* @__PURE__ */ (0, import_jsx_runtime75.jsxs)("div", { className: "uix-relationship-graph__list", role: "region", "aria-label": labels.list, children: [
|
|
7732
|
+
/* @__PURE__ */ (0, import_jsx_runtime75.jsx)("h3", { children: labels.listHeading }),
|
|
7733
|
+
/* @__PURE__ */ (0, import_jsx_runtime75.jsx)("ul", { children: nodes.map((node) => {
|
|
7384
7734
|
const neighbors = relationshipNeighbors(node.id, edges).map((id) => labelById.get(id) ?? id);
|
|
7385
|
-
return /* @__PURE__ */ (0,
|
|
7386
|
-
/* @__PURE__ */ (0,
|
|
7387
|
-
/* @__PURE__ */ (0,
|
|
7388
|
-
node.type && /* @__PURE__ */ (0,
|
|
7389
|
-
/* @__PURE__ */ (0,
|
|
7735
|
+
return /* @__PURE__ */ (0, import_jsx_runtime75.jsxs)("li", { "data-selected": selectedId === node.id || void 0, children: [
|
|
7736
|
+
/* @__PURE__ */ (0, import_jsx_runtime75.jsxs)("button", { type: "button", onClick: () => onSelect(node.id), "aria-pressed": selectedId === node.id, children: [
|
|
7737
|
+
/* @__PURE__ */ (0, import_jsx_runtime75.jsx)("strong", { children: node.label }),
|
|
7738
|
+
node.type && /* @__PURE__ */ (0, import_jsx_runtime75.jsx)("span", { children: node.type }),
|
|
7739
|
+
/* @__PURE__ */ (0, import_jsx_runtime75.jsx)("span", { children: neighbors.length ? labels.connectedTo(neighbors.join(", ")) : labels.noConnections })
|
|
7390
7740
|
] }),
|
|
7391
|
-
/* @__PURE__ */ (0,
|
|
7392
|
-
onExpandNeighbors && /* @__PURE__ */ (0,
|
|
7393
|
-
onOpenDetails && /* @__PURE__ */ (0,
|
|
7741
|
+
/* @__PURE__ */ (0, import_jsx_runtime75.jsxs)("span", { className: "uix-relationship-graph__list-actions", children: [
|
|
7742
|
+
onExpandNeighbors && /* @__PURE__ */ (0, import_jsx_runtime75.jsx)("button", { type: "button", onClick: () => onExpandNeighbors(node), children: labels.expandNeighbors }),
|
|
7743
|
+
onOpenDetails && /* @__PURE__ */ (0, import_jsx_runtime75.jsx)("button", { type: "button", onClick: () => onOpenDetails(node), children: labels.openDetails })
|
|
7394
7744
|
] })
|
|
7395
7745
|
] }, node.id);
|
|
7396
7746
|
}) })
|
|
@@ -7398,7 +7748,7 @@ function EquivalentRelationshipList({
|
|
|
7398
7748
|
}
|
|
7399
7749
|
|
|
7400
7750
|
// src/components/RelationshipGraphLayered.tsx
|
|
7401
|
-
var
|
|
7751
|
+
var import_jsx_runtime76 = require("react/jsx-runtime");
|
|
7402
7752
|
var EMPTY_IDS = /* @__PURE__ */ new Set();
|
|
7403
7753
|
var MIN_ZOOM = 0.4;
|
|
7404
7754
|
var MAX_ZOOM = 1.5;
|
|
@@ -7451,11 +7801,11 @@ function LayeredRelationshipGraph({
|
|
|
7451
7801
|
focusId,
|
|
7452
7802
|
onFocusChange
|
|
7453
7803
|
}) {
|
|
7454
|
-
const hintId = (0,
|
|
7455
|
-
const bounded = (0,
|
|
7456
|
-
const [localExpanded, setLocalExpanded] = (0,
|
|
7804
|
+
const hintId = (0, import_react52.useId)();
|
|
7805
|
+
const bounded = (0, import_react52.useMemo)(() => boundRelationshipGraph(nodes, edges, maxNodes), [nodes, edges, maxNodes]);
|
|
7806
|
+
const [localExpanded, setLocalExpanded] = (0, import_react52.useState)(EMPTY_IDS);
|
|
7457
7807
|
const expanded = expandedClusterIds ?? localExpanded;
|
|
7458
|
-
const layout = (0,
|
|
7808
|
+
const layout = (0, import_react52.useMemo)(
|
|
7459
7809
|
() => layoutLayeredGraph(bounded.nodes, bounded.edges, {
|
|
7460
7810
|
...rootId !== void 0 ? { rootId } : {},
|
|
7461
7811
|
...clusterThreshold !== void 0 ? { clusterThreshold } : {},
|
|
@@ -7464,29 +7814,29 @@ function LayeredRelationshipGraph({
|
|
|
7464
7814
|
}),
|
|
7465
7815
|
[bounded, rootId, clusterThreshold, expanded, density]
|
|
7466
7816
|
);
|
|
7467
|
-
const itemById = (0,
|
|
7468
|
-
const viewportRef = (0,
|
|
7469
|
-
const itemRefs = (0,
|
|
7470
|
-
const [size, setSize] = (0,
|
|
7471
|
-
const [view, setView] = (0,
|
|
7472
|
-
const [animate, setAnimate] = (0,
|
|
7473
|
-
const [localFocus, setLocalFocus] = (0,
|
|
7474
|
-
const [hoverId, setHoverId] = (0,
|
|
7475
|
-
const viewRef = (0,
|
|
7817
|
+
const itemById = (0, import_react52.useMemo)(() => new Map(layout.items.map((item) => [item.id, item])), [layout]);
|
|
7818
|
+
const viewportRef = (0, import_react52.useRef)(null);
|
|
7819
|
+
const itemRefs = (0, import_react52.useRef)(/* @__PURE__ */ new Map());
|
|
7820
|
+
const [size, setSize] = (0, import_react52.useState)({ width: 0, height: 0 });
|
|
7821
|
+
const [view, setView] = (0, import_react52.useState)({ x: 0, y: 0, zoom: 1 });
|
|
7822
|
+
const [animate, setAnimate] = (0, import_react52.useState)(false);
|
|
7823
|
+
const [localFocus, setLocalFocus] = (0, import_react52.useState)(void 0);
|
|
7824
|
+
const [hoverId, setHoverId] = (0, import_react52.useState)(void 0);
|
|
7825
|
+
const viewRef = (0, import_react52.useRef)(view);
|
|
7476
7826
|
viewRef.current = view;
|
|
7477
|
-
const layoutRef = (0,
|
|
7827
|
+
const layoutRef = (0, import_react52.useRef)(layout);
|
|
7478
7828
|
layoutRef.current = layout;
|
|
7479
|
-
const pendingFocus = (0,
|
|
7480
|
-
const initialisedFor = (0,
|
|
7829
|
+
const pendingFocus = (0, import_react52.useRef)(void 0);
|
|
7830
|
+
const initialisedFor = (0, import_react52.useRef)(void 0);
|
|
7481
7831
|
const rootItemId = layout.rootId !== void 0 ? layout.itemOf[layout.rootId] : layout.items[0]?.id;
|
|
7482
7832
|
const requestedFocus = focusId !== void 0 ? layout.itemOf[focusId] ?? focusId : localFocus;
|
|
7483
7833
|
const focusedId = requestedFocus !== void 0 && itemById.has(requestedFocus) ? requestedFocus : rootItemId;
|
|
7484
7834
|
const selectedItemId = selectedId !== void 0 ? layout.itemOf[selectedId] : void 0;
|
|
7485
|
-
const activeIds = (0,
|
|
7835
|
+
const activeIds = (0, import_react52.useMemo)(
|
|
7486
7836
|
() => new Set([hoverId, selectedItemId].filter((id) => id !== void 0)),
|
|
7487
7837
|
[hoverId, selectedItemId]
|
|
7488
7838
|
);
|
|
7489
|
-
(0,
|
|
7839
|
+
(0, import_react52.useEffect)(() => {
|
|
7490
7840
|
const element = viewportRef.current;
|
|
7491
7841
|
if (!element) return;
|
|
7492
7842
|
const measure = () => setSize({ width: element.clientWidth, height: element.clientHeight });
|
|
@@ -7496,18 +7846,18 @@ function LayeredRelationshipGraph({
|
|
|
7496
7846
|
observer.observe(element);
|
|
7497
7847
|
return () => observer.disconnect();
|
|
7498
7848
|
}, []);
|
|
7499
|
-
(0,
|
|
7849
|
+
(0, import_react52.useEffect)(() => {
|
|
7500
7850
|
if (size.width === 0) return;
|
|
7501
7851
|
const key = `${layout.rootId ?? ""}`;
|
|
7502
7852
|
if (initialisedFor.current === key) return;
|
|
7503
7853
|
initialisedFor.current = key;
|
|
7504
7854
|
setView(initialView(layout, size));
|
|
7505
7855
|
}, [layout, size]);
|
|
7506
|
-
const moveView = (0,
|
|
7856
|
+
const moveView = (0, import_react52.useCallback)((next, smooth) => {
|
|
7507
7857
|
setAnimate(smooth);
|
|
7508
7858
|
setView(next);
|
|
7509
7859
|
}, []);
|
|
7510
|
-
const ensureVisible = (0,
|
|
7860
|
+
const ensureVisible = (0, import_react52.useCallback)((id, smooth) => {
|
|
7511
7861
|
const element = viewportRef.current;
|
|
7512
7862
|
const item = layoutRef.current.items.find((candidate) => candidate.id === id);
|
|
7513
7863
|
if (!element || !item) return;
|
|
@@ -7526,7 +7876,7 @@ function LayeredRelationshipGraph({
|
|
|
7526
7876
|
else if (bottom > heightPx - FOCUS_MARGIN) nextY -= bottom - (heightPx - FOCUS_MARGIN);
|
|
7527
7877
|
if (nextX !== x || nextY !== y) moveView({ x: nextX, y: nextY, zoom }, smooth);
|
|
7528
7878
|
}, [moveView]);
|
|
7529
|
-
const focusItem = (0,
|
|
7879
|
+
const focusItem = (0, import_react52.useCallback)((id) => {
|
|
7530
7880
|
setLocalFocus(id);
|
|
7531
7881
|
onFocusChange?.(id);
|
|
7532
7882
|
requestAnimationFrame(() => {
|
|
@@ -7534,7 +7884,7 @@ function LayeredRelationshipGraph({
|
|
|
7534
7884
|
ensureVisible(id, true);
|
|
7535
7885
|
});
|
|
7536
7886
|
}, [ensureVisible, onFocusChange]);
|
|
7537
|
-
(0,
|
|
7887
|
+
(0, import_react52.useEffect)(() => {
|
|
7538
7888
|
const wanted = pendingFocus.current;
|
|
7539
7889
|
if (wanted !== void 0 && itemById.has(wanted)) {
|
|
7540
7890
|
pendingFocus.current = void 0;
|
|
@@ -7544,8 +7894,8 @@ function LayeredRelationshipGraph({
|
|
|
7544
7894
|
const controlledTarget = focusId !== void 0 ? layout.itemOf[focusId] ?? focusId : void 0;
|
|
7545
7895
|
const controlledPresent = controlledTarget !== void 0 && itemById.has(controlledTarget);
|
|
7546
7896
|
const controlledKey = `${controlledTarget ?? ""}|${controlledPresent}`;
|
|
7547
|
-
const lastControlledKey = (0,
|
|
7548
|
-
(0,
|
|
7897
|
+
const lastControlledKey = (0, import_react52.useRef)(controlledKey);
|
|
7898
|
+
(0, import_react52.useEffect)(() => {
|
|
7549
7899
|
if (lastControlledKey.current === controlledKey) return;
|
|
7550
7900
|
lastControlledKey.current = controlledKey;
|
|
7551
7901
|
if (!controlledPresent || controlledTarget === void 0) return;
|
|
@@ -7554,7 +7904,7 @@ function LayeredRelationshipGraph({
|
|
|
7554
7904
|
ensureVisible(controlledTarget, true);
|
|
7555
7905
|
});
|
|
7556
7906
|
}, [controlledKey, controlledTarget, controlledPresent, ensureVisible]);
|
|
7557
|
-
(0,
|
|
7907
|
+
(0, import_react52.useEffect)(() => {
|
|
7558
7908
|
const element = viewportRef.current;
|
|
7559
7909
|
if (!element) return;
|
|
7560
7910
|
const onWheel = (event) => {
|
|
@@ -7572,8 +7922,8 @@ function LayeredRelationshipGraph({
|
|
|
7572
7922
|
element.addEventListener("wheel", onWheel, { passive: false });
|
|
7573
7923
|
return () => element.removeEventListener("wheel", onWheel);
|
|
7574
7924
|
}, []);
|
|
7575
|
-
const pointers = (0,
|
|
7576
|
-
const pinchDistance = (0,
|
|
7925
|
+
const pointers = (0, import_react52.useRef)(/* @__PURE__ */ new Map());
|
|
7926
|
+
const pinchDistance = (0, import_react52.useRef)(void 0);
|
|
7577
7927
|
const onPointerDown = (event) => {
|
|
7578
7928
|
if (event.target.closest("button")) return;
|
|
7579
7929
|
event.currentTarget.setPointerCapture?.(event.pointerId);
|
|
@@ -7671,21 +8021,21 @@ function LayeredRelationshipGraph({
|
|
|
7671
8021
|
height: layout.height,
|
|
7672
8022
|
transform: `translate(${view.x}px, ${view.y}px) scale(${view.zoom})`
|
|
7673
8023
|
};
|
|
7674
|
-
return /* @__PURE__ */ (0,
|
|
7675
|
-
/* @__PURE__ */ (0,
|
|
7676
|
-
/* @__PURE__ */ (0,
|
|
7677
|
-
/* @__PURE__ */ (0,
|
|
7678
|
-
/* @__PURE__ */ (0,
|
|
7679
|
-
/* @__PURE__ */ (0,
|
|
7680
|
-
/* @__PURE__ */ (0,
|
|
7681
|
-
/* @__PURE__ */ (0,
|
|
7682
|
-
/* @__PURE__ */ (0,
|
|
7683
|
-
/* @__PURE__ */ (0,
|
|
7684
|
-
/* @__PURE__ */ (0,
|
|
8024
|
+
return /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("section", { className: cx("uix-relationship-graph", "uix-relationship-graph--layered", density === "compact" && "uix-relationship-graph--compact", className), "aria-label": labels.graph, children: [
|
|
8025
|
+
/* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { className: "uix-relationship-graph__toolbar", role: "group", "aria-label": labels.controls, children: [
|
|
8026
|
+
/* @__PURE__ */ (0, import_jsx_runtime76.jsx)("button", { type: "button", onClick: () => zoomBy(ZOOM_STEP), disabled: view.zoom >= MAX_ZOOM, children: labels.zoomIn }),
|
|
8027
|
+
/* @__PURE__ */ (0, import_jsx_runtime76.jsx)("button", { type: "button", onClick: () => zoomBy(1 / ZOOM_STEP), disabled: view.zoom <= MIN_ZOOM, children: labels.zoomOut }),
|
|
8028
|
+
/* @__PURE__ */ (0, import_jsx_runtime76.jsx)("button", { type: "button", onClick: () => moveView(fitView(layout, size), true), children: labels.fit }),
|
|
8029
|
+
/* @__PURE__ */ (0, import_jsx_runtime76.jsx)("button", { type: "button", onClick: () => moveView(initialView(layout, size), true), children: labels.reset }),
|
|
8030
|
+
/* @__PURE__ */ (0, import_jsx_runtime76.jsx)("button", { type: "button", onClick: () => panBy(PAN_STEP, 0), "aria-label": labels.panLeft, children: labels.left }),
|
|
8031
|
+
/* @__PURE__ */ (0, import_jsx_runtime76.jsx)("button", { type: "button", onClick: () => panBy(0, PAN_STEP), "aria-label": labels.panUp, children: labels.up }),
|
|
8032
|
+
/* @__PURE__ */ (0, import_jsx_runtime76.jsx)("button", { type: "button", onClick: () => panBy(0, -PAN_STEP), "aria-label": labels.panDown, children: labels.down }),
|
|
8033
|
+
/* @__PURE__ */ (0, import_jsx_runtime76.jsx)("button", { type: "button", onClick: () => panBy(-PAN_STEP, 0), "aria-label": labels.panRight, children: labels.right }),
|
|
8034
|
+
/* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { "aria-live": "polite", children: labels.zoomLevel(Math.round(view.zoom * 100)) })
|
|
7685
8035
|
] }),
|
|
7686
|
-
bounded.omittedNodeCount > 0 && /* @__PURE__ */ (0,
|
|
7687
|
-
/* @__PURE__ */ (0,
|
|
7688
|
-
/* @__PURE__ */ (0,
|
|
8036
|
+
bounded.omittedNodeCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("p", { className: "uix-relationship-graph__bounded", role: "status", children: labels.bounded(bounded.nodes.length, bounded.omittedNodeCount) }),
|
|
8037
|
+
/* @__PURE__ */ (0, import_jsx_runtime76.jsx)("p", { id: hintId, className: "uix-visually-hidden", children: labels.keyboardHint }),
|
|
8038
|
+
/* @__PURE__ */ (0, import_jsx_runtime76.jsx)(
|
|
7689
8039
|
"div",
|
|
7690
8040
|
{
|
|
7691
8041
|
ref: viewportRef,
|
|
@@ -7695,11 +8045,11 @@ function LayeredRelationshipGraph({
|
|
|
7695
8045
|
onPointerMove,
|
|
7696
8046
|
onPointerUp: onPointerEnd,
|
|
7697
8047
|
onPointerCancel: onPointerEnd,
|
|
7698
|
-
children: /* @__PURE__ */ (0,
|
|
7699
|
-
/* @__PURE__ */ (0,
|
|
8048
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)("div", { className: "uix-relationship-graph__stage", style: stageStyle, "data-animate": animate || void 0, onTransitionEnd: () => setAnimate(false), children: [
|
|
8049
|
+
/* @__PURE__ */ (0, import_jsx_runtime76.jsx)("svg", { className: "uix-relationship-graph__edges", width: layout.width, height: layout.height, "aria-hidden": "true", focusable: "false", children: layout.edges.map((edge) => {
|
|
7700
8050
|
const active = activeIds.has(edge.source) || activeIds.has(edge.target) || edge.edgeIds.some((id) => highlightedEdgeIds.has(id));
|
|
7701
8051
|
const angle = edge.arrowAngle * 180 / Math.PI;
|
|
7702
|
-
return /* @__PURE__ */ (0,
|
|
8052
|
+
return /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)(
|
|
7703
8053
|
"g",
|
|
7704
8054
|
{
|
|
7705
8055
|
className: "uix-relationship-graph__link",
|
|
@@ -7709,15 +8059,15 @@ function LayeredRelationshipGraph({
|
|
|
7709
8059
|
"data-conflicted": edge.edgeIds.some((id) => conflictedEdgeIds.has(id)) || void 0,
|
|
7710
8060
|
"data-dimmed": dimmedNodeIds.has(edge.source) && dimmedNodeIds.has(edge.target) || void 0,
|
|
7711
8061
|
children: [
|
|
7712
|
-
/* @__PURE__ */ (0,
|
|
7713
|
-
edge.arrow !== "none" && /* @__PURE__ */ (0,
|
|
7714
|
-
showLabel(edge) && /* @__PURE__ */ (0,
|
|
8062
|
+
/* @__PURE__ */ (0, import_jsx_runtime76.jsx)("path", { d: edge.path }),
|
|
8063
|
+
edge.arrow !== "none" && /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("polygon", { points: arrowPoints, transform: `translate(${edge.arrowX} ${edge.arrowY}) rotate(${angle})` }),
|
|
8064
|
+
showLabel(edge) && /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("text", { x: edge.labelX, y: edge.labelY, textAnchor: "middle", dominantBaseline: "middle", children: (edge.kind === "cycle" ? [...edge.labelLines, labels.cycle] : edge.labelLines).map((line, index, lines) => /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("tspan", { x: edge.labelX, dy: index === 0 ? `${-(lines.length - 1) * 0.55}em` : "1.1em", children: line }, index)) })
|
|
7715
8065
|
]
|
|
7716
8066
|
},
|
|
7717
8067
|
edge.id
|
|
7718
8068
|
);
|
|
7719
8069
|
}) }),
|
|
7720
|
-
layout.columns.map((column) => /* @__PURE__ */ (0,
|
|
8070
|
+
layout.columns.map((column) => /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(
|
|
7721
8071
|
"div",
|
|
7722
8072
|
{
|
|
7723
8073
|
className: "uix-relationship-graph__column",
|
|
@@ -7727,17 +8077,17 @@ function LayeredRelationshipGraph({
|
|
|
7727
8077
|
},
|
|
7728
8078
|
column.depth
|
|
7729
8079
|
)),
|
|
7730
|
-
/* @__PURE__ */ (0,
|
|
8080
|
+
/* @__PURE__ */ (0, import_jsx_runtime76.jsx)("div", { role: "group", "aria-roledescription": labels.roleDescription, "aria-label": labels.graphSummary(bounded.nodes.length, bounded.edges.length), "aria-describedby": hintId, children: layout.items.map((item) => {
|
|
7731
8081
|
const selected = item.id === selectedItemId;
|
|
7732
8082
|
const dimmed = item.node ? dimmedNodeIds.has(item.node.id) : item.cluster.members.every((member) => dimmedNodeIds.has(member.id));
|
|
7733
|
-
const body = item.cluster ? renderCluster?.(item.cluster) ?? /* @__PURE__ */ (0,
|
|
7734
|
-
/* @__PURE__ */ (0,
|
|
7735
|
-
/* @__PURE__ */ (0,
|
|
7736
|
-
] }) : renderNode?.(item.node, { selected, dimmed }) ?? /* @__PURE__ */ (0,
|
|
7737
|
-
/* @__PURE__ */ (0,
|
|
7738
|
-
(item.node.type || item.node.description) && /* @__PURE__ */ (0,
|
|
8083
|
+
const body = item.cluster ? renderCluster?.(item.cluster) ?? /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)(import_jsx_runtime76.Fragment, { children: [
|
|
8084
|
+
/* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { className: "uix-relationship-graph__item-label", children: labels.cluster(item.cluster.members.length, item.cluster.type, item.cluster.edgeLabel) }),
|
|
8085
|
+
/* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { className: "uix-relationship-graph__item-meta", children: labels.expandCluster })
|
|
8086
|
+
] }) : renderNode?.(item.node, { selected, dimmed }) ?? /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)(import_jsx_runtime76.Fragment, { children: [
|
|
8087
|
+
/* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { className: "uix-relationship-graph__item-label", children: item.node.label }),
|
|
8088
|
+
(item.node.type || item.node.description) && /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { className: "uix-relationship-graph__item-meta", children: [item.node.type, item.node.description].filter(Boolean).join(" \xB7 ") })
|
|
7739
8089
|
] });
|
|
7740
|
-
return /* @__PURE__ */ (0,
|
|
8090
|
+
return /* @__PURE__ */ (0, import_jsx_runtime76.jsxs)(
|
|
7741
8091
|
"button",
|
|
7742
8092
|
{
|
|
7743
8093
|
ref: (element) => {
|
|
@@ -7768,7 +8118,7 @@ function LayeredRelationshipGraph({
|
|
|
7768
8118
|
onPointerLeave: () => setHoverId((current) => current === item.id ? void 0 : current),
|
|
7769
8119
|
children: [
|
|
7770
8120
|
body,
|
|
7771
|
-
item.inCycle && /* @__PURE__ */ (0,
|
|
8121
|
+
item.inCycle && /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("span", { className: "uix-relationship-graph__item-flag", "aria-hidden": "true", children: labels.cycle })
|
|
7772
8122
|
]
|
|
7773
8123
|
},
|
|
7774
8124
|
item.id
|
|
@@ -7776,7 +8126,7 @@ function LayeredRelationshipGraph({
|
|
|
7776
8126
|
}) }),
|
|
7777
8127
|
layout.items.filter((item) => item.expandedGroup).map((item) => {
|
|
7778
8128
|
const group = item.expandedGroup;
|
|
7779
|
-
return /* @__PURE__ */ (0,
|
|
8129
|
+
return /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(
|
|
7780
8130
|
"button",
|
|
7781
8131
|
{
|
|
7782
8132
|
type: "button",
|
|
@@ -7792,8 +8142,8 @@ function LayeredRelationshipGraph({
|
|
|
7792
8142
|
] })
|
|
7793
8143
|
}
|
|
7794
8144
|
),
|
|
7795
|
-
legend.length > 0 && /* @__PURE__ */ (0,
|
|
7796
|
-
showList && /* @__PURE__ */ (0,
|
|
8145
|
+
legend.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("ul", { className: "uix-relationship-graph__legend", "aria-label": labels.legend, children: legend.map((entry) => /* @__PURE__ */ (0, import_jsx_runtime76.jsx)("li", { "data-type": entry.id, children: entry.label }, entry.id)) }),
|
|
8146
|
+
showList && /* @__PURE__ */ (0, import_jsx_runtime76.jsx)(
|
|
7797
8147
|
EquivalentRelationshipList,
|
|
7798
8148
|
{
|
|
7799
8149
|
nodes: bounded.nodes,
|
|
@@ -7812,7 +8162,7 @@ function LayeredRelationshipGraph({
|
|
|
7812
8162
|
}
|
|
7813
8163
|
|
|
7814
8164
|
// src/components/RelationshipGraph.tsx
|
|
7815
|
-
var
|
|
8165
|
+
var import_jsx_runtime77 = require("react/jsx-runtime");
|
|
7816
8166
|
var DEFAULT_RELATIONSHIP_GRAPH_LABELS = {
|
|
7817
8167
|
graph: "Relationship graph",
|
|
7818
8168
|
controls: "Graph view controls",
|
|
@@ -7874,21 +8224,21 @@ function radialViewBox(nodes) {
|
|
|
7874
8224
|
return `${round(minX)} ${round(minY)} ${width} ${height}`;
|
|
7875
8225
|
}
|
|
7876
8226
|
function RelationshipGraph(props) {
|
|
7877
|
-
const labels = (0,
|
|
8227
|
+
const labels = (0, import_react53.useMemo)(() => ({ ...DEFAULT_RELATIONSHIP_GRAPH_LABELS, ...props.labels }), [props.labels]);
|
|
7878
8228
|
const stateClass = cx("uix-relationship-graph uix-relationship-graph--state", props.className);
|
|
7879
|
-
if (props.loading) return /* @__PURE__ */ (0,
|
|
8229
|
+
if (props.loading) return /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("div", { className: stateClass, role: "status", children: labels.loading });
|
|
7880
8230
|
if (props.error) {
|
|
7881
|
-
return /* @__PURE__ */ (0,
|
|
7882
|
-
/* @__PURE__ */ (0,
|
|
7883
|
-
props.onRetry && /* @__PURE__ */ (0,
|
|
8231
|
+
return /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: stateClass, role: "alert", children: [
|
|
8232
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsx)("p", { children: props.error }),
|
|
8233
|
+
props.onRetry && /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("button", { type: "button", className: "uix-btn uix-btn--secondary", onClick: props.onRetry, children: labels.retry })
|
|
7884
8234
|
] });
|
|
7885
8235
|
}
|
|
7886
|
-
if (props.nodes.length === 0) return /* @__PURE__ */ (0,
|
|
7887
|
-
/* @__PURE__ */ (0,
|
|
7888
|
-
/* @__PURE__ */ (0,
|
|
8236
|
+
if (props.nodes.length === 0) return /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: stateClass, children: [
|
|
8237
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsx)("p", { children: labels.emptyTitle }),
|
|
8238
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsx)("p", { children: labels.emptyHint })
|
|
7889
8239
|
] });
|
|
7890
|
-
if (props.layout === "layered") return /* @__PURE__ */ (0,
|
|
7891
|
-
return /* @__PURE__ */ (0,
|
|
8240
|
+
if (props.layout === "layered") return /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(LayeredRelationshipGraph, { ...props, labels });
|
|
8241
|
+
return /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(RadialRelationshipGraph, { ...props, labels });
|
|
7892
8242
|
}
|
|
7893
8243
|
function RadialRelationshipGraph({
|
|
7894
8244
|
nodes,
|
|
@@ -7908,17 +8258,17 @@ function RadialRelationshipGraph({
|
|
|
7908
8258
|
labels,
|
|
7909
8259
|
showList = true
|
|
7910
8260
|
}) {
|
|
7911
|
-
const bounded = (0,
|
|
7912
|
-
const positioned = (0,
|
|
7913
|
-
const typeColor = (0,
|
|
8261
|
+
const bounded = (0, import_react53.useMemo)(() => boundRelationshipGraph(nodes, edges, maxNodes), [nodes, edges, maxNodes]);
|
|
8262
|
+
const positioned = (0, import_react53.useMemo)(() => layoutRelationshipGraph(bounded.nodes, bounded.edges, selectedId), [bounded, selectedId]);
|
|
8263
|
+
const typeColor = (0, import_react53.useMemo)(
|
|
7914
8264
|
() => new Map(legend.map((item, index) => [item.id, `var(--uix-chart-${index % 8 + 1})`])),
|
|
7915
8265
|
[legend]
|
|
7916
8266
|
);
|
|
7917
|
-
const positionedById = (0,
|
|
7918
|
-
const [zoom, setZoom] = (0,
|
|
7919
|
-
const [pan, setPan] = (0,
|
|
7920
|
-
const [focusedId, setFocusedId] = (0,
|
|
7921
|
-
const svgRef = (0,
|
|
8267
|
+
const positionedById = (0, import_react53.useMemo)(() => new Map(positioned.map((node) => [node.id, node])), [positioned]);
|
|
8268
|
+
const [zoom, setZoom] = (0, import_react53.useState)(1);
|
|
8269
|
+
const [pan, setPan] = (0, import_react53.useState)({ x: 0, y: 0 });
|
|
8270
|
+
const [focusedId, setFocusedId] = (0, import_react53.useState)(selectedId ?? positioned[0]?.id);
|
|
8271
|
+
const svgRef = (0, import_react53.useRef)(null);
|
|
7922
8272
|
const select = (id) => {
|
|
7923
8273
|
const node = bounded.nodes.find((item) => item.id === id);
|
|
7924
8274
|
if (node) onSelect?.(node);
|
|
@@ -7941,25 +8291,25 @@ function RadialRelationshipGraph({
|
|
|
7941
8291
|
setZoom(1);
|
|
7942
8292
|
setPan({ x: 0, y: 0 });
|
|
7943
8293
|
};
|
|
7944
|
-
return /* @__PURE__ */ (0,
|
|
7945
|
-
/* @__PURE__ */ (0,
|
|
7946
|
-
/* @__PURE__ */ (0,
|
|
7947
|
-
/* @__PURE__ */ (0,
|
|
7948
|
-
/* @__PURE__ */ (0,
|
|
7949
|
-
/* @__PURE__ */ (0,
|
|
7950
|
-
/* @__PURE__ */ (0,
|
|
7951
|
-
/* @__PURE__ */ (0,
|
|
7952
|
-
/* @__PURE__ */ (0,
|
|
7953
|
-
/* @__PURE__ */ (0,
|
|
8294
|
+
return /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("section", { className: cx("uix-relationship-graph", `uix-relationship-graph--${density}`, className), "aria-label": labels.graph, children: [
|
|
8295
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("div", { className: "uix-relationship-graph__toolbar", "aria-label": labels.controls, children: [
|
|
8296
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsx)("button", { type: "button", onClick: () => setPan((value) => ({ ...value, x: value.x - 24 })), "aria-label": labels.panLeft, children: labels.left }),
|
|
8297
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsx)("button", { type: "button", onClick: () => setPan((value) => ({ ...value, y: value.y - 24 })), "aria-label": labels.panUp, children: labels.up }),
|
|
8298
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsx)("button", { type: "button", onClick: () => setPan((value) => ({ ...value, y: value.y + 24 })), "aria-label": labels.panDown, children: labels.down }),
|
|
8299
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsx)("button", { type: "button", onClick: () => setPan((value) => ({ ...value, x: value.x + 24 })), "aria-label": labels.panRight, children: labels.right }),
|
|
8300
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsx)("button", { type: "button", onClick: () => setZoom((value) => Math.min(2, Number((value + 0.2).toFixed(1)))), "aria-label": labels.zoomIn, children: labels.zoomIn }),
|
|
8301
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsx)("button", { type: "button", onClick: () => setZoom((value) => Math.max(0.5, Number((value - 0.2).toFixed(1)))), "aria-label": labels.zoomOut, children: labels.zoomOut }),
|
|
8302
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsx)("button", { type: "button", onClick: reset, children: labels.reset }),
|
|
8303
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsx)("span", { "aria-live": "polite", children: labels.zoomLevel(Math.round(zoom * 100)) })
|
|
7954
8304
|
] }),
|
|
7955
|
-
bounded.omittedNodeCount > 0 && /* @__PURE__ */ (0,
|
|
7956
|
-
/* @__PURE__ */ (0,
|
|
8305
|
+
bounded.omittedNodeCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("p", { className: "uix-relationship-graph__bounded", role: "status", children: labels.bounded(bounded.nodes.length, bounded.omittedNodeCount) }),
|
|
8306
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsx)("div", { className: "uix-relationship-graph__visual", children: /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("svg", { ref: svgRef, viewBox: radialViewBox(positioned), role: "group", "aria-label": labels.graphSummary(bounded.nodes.length, bounded.edges.length), children: /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)("g", { transform: `translate(${pan.x} ${pan.y}) scale(${zoom})`, children: [
|
|
7957
8307
|
bounded.edges.map((edge) => {
|
|
7958
8308
|
const source = positionedById.get(edge.source);
|
|
7959
8309
|
const target = positionedById.get(edge.target);
|
|
7960
|
-
return /* @__PURE__ */ (0,
|
|
8310
|
+
return /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("line", { x1: source.x * RADIAL_SCALE_X, y1: source.y * RADIAL_SCALE_Y, x2: target.x * RADIAL_SCALE_X, y2: target.y * RADIAL_SCALE_Y, className: "uix-relationship-graph__edge", "data-typed": edge.type != null && typeColor.has(edge.type) || void 0, style: edge.type != null && typeColor.has(edge.type) ? { "--uix-graph-type-color": typeColor.get(edge.type) } : void 0, "data-highlighted": highlightedEdgeIds.has(edge.id) || void 0, "data-conflicted": conflictedEdgeIds.has(edge.id) || void 0, children: /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("title", { children: edge.label ?? edge.type ?? labels.relationship }) }, edge.id);
|
|
7961
8311
|
}),
|
|
7962
|
-
positioned.map((node) => /* @__PURE__ */ (0,
|
|
8312
|
+
positioned.map((node) => /* @__PURE__ */ (0, import_jsx_runtime77.jsxs)(
|
|
7963
8313
|
"g",
|
|
7964
8314
|
{
|
|
7965
8315
|
transform: `translate(${node.x * RADIAL_SCALE_X} ${node.y * RADIAL_SCALE_Y})`,
|
|
@@ -7975,22 +8325,22 @@ function RadialRelationshipGraph({
|
|
|
7975
8325
|
onKeyDown: (event) => onNodeKeyDown(event, node.id),
|
|
7976
8326
|
onClick: () => select(node.id),
|
|
7977
8327
|
children: [
|
|
7978
|
-
/* @__PURE__ */ (0,
|
|
7979
|
-
/* @__PURE__ */ (0,
|
|
7980
|
-
/* @__PURE__ */ (0,
|
|
8328
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsx)("title", { children: node.label }),
|
|
8329
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsx)("rect", { x: -RADIAL_NODE_HALF_W, y: -RADIAL_NODE_HALF_H, width: RADIAL_NODE_HALF_W * 2, height: RADIAL_NODE_HALF_H * 2, rx: "8" }),
|
|
8330
|
+
/* @__PURE__ */ (0, import_jsx_runtime77.jsx)("text", { textAnchor: "middle", dominantBaseline: "middle", children: node.label.length > 16 ? `${node.label.slice(0, 15)}\u2026` : node.label })
|
|
7981
8331
|
]
|
|
7982
8332
|
},
|
|
7983
8333
|
node.id
|
|
7984
8334
|
))
|
|
7985
8335
|
] }) }) }),
|
|
7986
|
-
legend.length > 0 && /* @__PURE__ */ (0,
|
|
7987
|
-
showList && /* @__PURE__ */ (0,
|
|
8336
|
+
legend.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("ul", { className: "uix-relationship-graph__legend", "aria-label": labels.legend, children: legend.map((item) => /* @__PURE__ */ (0, import_jsx_runtime77.jsx)("li", { "data-type": item.id, style: { "--uix-graph-type-color": typeColor.get(item.id) }, children: item.label }, item.id)) }),
|
|
8337
|
+
showList && /* @__PURE__ */ (0, import_jsx_runtime77.jsx)(EquivalentRelationshipList, { nodes: bounded.nodes, edges: bounded.edges, selectedId, labels, onSelect: select, onExpandNeighbors, onOpenDetails })
|
|
7988
8338
|
] });
|
|
7989
8339
|
}
|
|
7990
8340
|
|
|
7991
8341
|
// src/components/MatchReview.tsx
|
|
7992
|
-
var
|
|
7993
|
-
var
|
|
8342
|
+
var import_react54 = require("react");
|
|
8343
|
+
var import_jsx_runtime78 = require("react/jsx-runtime");
|
|
7994
8344
|
var DEFAULT_MATCH_REVIEW_LABELS = {
|
|
7995
8345
|
region: "Match review",
|
|
7996
8346
|
loading: "Loading match candidates\u2026",
|
|
@@ -8052,11 +8402,11 @@ function MatchReview({
|
|
|
8052
8402
|
const plural = (n, one, many) => fillLabel(n === 1 ? one : many, { count: n });
|
|
8053
8403
|
const decisionLabel = { accepted: labels.decisionAccepted, dismissed: labels.decisionDismissed, split: labels.decisionSplit, other: labels.decisionOther };
|
|
8054
8404
|
const actionLabel = { accept: labels.accept, dismiss: labels.dismiss, split: labels.split, "pick-other": labels.pickOther };
|
|
8055
|
-
const [internalSelection, setInternalSelection] = (0,
|
|
8056
|
-
const [announcement, setAnnouncement] = (0,
|
|
8057
|
-
const [bulkPending, setBulkPending] = (0,
|
|
8405
|
+
const [internalSelection, setInternalSelection] = (0, import_react54.useState)(/* @__PURE__ */ new Set());
|
|
8406
|
+
const [announcement, setAnnouncement] = (0, import_react54.useState)("");
|
|
8407
|
+
const [bulkPending, setBulkPending] = (0, import_react54.useState)(false);
|
|
8058
8408
|
const selection = selectedIds ?? internalSelection;
|
|
8059
|
-
const pending = (0,
|
|
8409
|
+
const pending = (0, import_react54.useMemo)(() => candidates.filter((candidate) => candidate.status !== "resolved"), [candidates]);
|
|
8060
8410
|
const setSelection = (next) => {
|
|
8061
8411
|
if (selectedIds === void 0) setInternalSelection(next);
|
|
8062
8412
|
onSelectionChange?.(next);
|
|
@@ -8085,48 +8435,48 @@ function MatchReview({
|
|
|
8085
8435
|
setBulkPending(false);
|
|
8086
8436
|
}
|
|
8087
8437
|
};
|
|
8088
|
-
if (loading) return /* @__PURE__ */ (0,
|
|
8089
|
-
if (error) return /* @__PURE__ */ (0,
|
|
8090
|
-
/* @__PURE__ */ (0,
|
|
8091
|
-
onRetry && /* @__PURE__ */ (0,
|
|
8438
|
+
if (loading) return /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("div", { className: cx("uix-match-review uix-match-review--state", className), role: "status", children: labels.loading });
|
|
8439
|
+
if (error) return /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("div", { className: cx("uix-match-review uix-match-review--state", className), role: "alert", children: [
|
|
8440
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsx)("p", { children: error }),
|
|
8441
|
+
onRetry && /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("button", { type: "button", className: "uix-btn uix-btn--secondary", onClick: onRetry, children: labels.retry })
|
|
8092
8442
|
] });
|
|
8093
|
-
if (candidates.length === 0) return /* @__PURE__ */ (0,
|
|
8094
|
-
/* @__PURE__ */ (0,
|
|
8095
|
-
/* @__PURE__ */ (0,
|
|
8443
|
+
if (candidates.length === 0) return /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("div", { className: cx("uix-match-review uix-match-review--state", className), children: [
|
|
8444
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsx)("p", { children: labels.empty }),
|
|
8445
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsx)("p", { children: labels.emptyDetail })
|
|
8096
8446
|
] });
|
|
8097
|
-
return /* @__PURE__ */ (0,
|
|
8098
|
-
/* @__PURE__ */ (0,
|
|
8099
|
-
/* @__PURE__ */ (0,
|
|
8100
|
-
/* @__PURE__ */ (0,
|
|
8101
|
-
/* @__PURE__ */ (0,
|
|
8447
|
+
return /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("section", { className: cx("uix-match-review", className), "aria-label": labels.region, children: [
|
|
8448
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("div", { className: "uix-match-review__summary", children: [
|
|
8449
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("div", { children: [
|
|
8450
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsx)("strong", { children: incomingLabel }),
|
|
8451
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsx)("span", { children: fillLabel(labels.pendingOf, { pending: pending.length, total: candidates.length }) })
|
|
8102
8452
|
] }),
|
|
8103
|
-
/* @__PURE__ */ (0,
|
|
8104
|
-
/* @__PURE__ */ (0,
|
|
8453
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsx)("div", { className: "uix-match-review__incoming", children: fields.map((field) => /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("span", { children: [
|
|
8454
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsx)("b", { children: field.label }),
|
|
8105
8455
|
field.render?.(incoming[field.id], incoming) ?? valueText(incoming[field.id])
|
|
8106
8456
|
] }, field.id)) })
|
|
8107
8457
|
] }),
|
|
8108
|
-
onBulkDecision && /* @__PURE__ */ (0,
|
|
8109
|
-
/* @__PURE__ */ (0,
|
|
8110
|
-
/* @__PURE__ */ (0,
|
|
8111
|
-
/* @__PURE__ */ (0,
|
|
8458
|
+
onBulkDecision && /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("div", { className: "uix-match-review__bulk", "aria-label": labels.bulk, children: [
|
|
8459
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsx)("span", { children: fillLabel(labels.selectedCount, { count: selection.size }) }),
|
|
8460
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsx)("button", { type: "button", className: "uix-btn uix-btn--secondary uix-btn--sm", disabled: selection.size === 0 || bulkPending, onClick: () => void runBulk("accept"), children: bulkPending ? labels.applying : labels.acceptSelected }),
|
|
8461
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsx)("button", { type: "button", className: "uix-btn uix-btn--ghost uix-btn--sm", disabled: selection.size === 0 || bulkPending, onClick: () => void runBulk("dismiss"), children: bulkPending ? labels.applying : labels.dismissSelected })
|
|
8112
8462
|
] }),
|
|
8113
|
-
/* @__PURE__ */ (0,
|
|
8114
|
-
/* @__PURE__ */ (0,
|
|
8115
|
-
/* @__PURE__ */ (0,
|
|
8116
|
-
/* @__PURE__ */ (0,
|
|
8117
|
-
/* @__PURE__ */ (0,
|
|
8118
|
-
fields.map((field) => /* @__PURE__ */ (0,
|
|
8119
|
-
/* @__PURE__ */ (0,
|
|
8120
|
-
/* @__PURE__ */ (0,
|
|
8463
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsx)("div", { className: "uix-match-review__table-wrap", children: /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("table", { className: "uix-table uix-match-review__table", children: [
|
|
8464
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsx)("caption", { className: "uix-visually-hidden", children: labels.caption }),
|
|
8465
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("tr", { children: [
|
|
8466
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsx)("th", { scope: "col", children: /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("span", { className: "uix-visually-hidden", children: labels.select }) }),
|
|
8467
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsx)("th", { scope: "col", children: labels.confidence }),
|
|
8468
|
+
fields.map((field) => /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("th", { scope: "col", children: field.label }, field.id)),
|
|
8469
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsx)("th", { scope: "col", children: labels.status }),
|
|
8470
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsx)("th", { scope: "col", children: labels.actions })
|
|
8121
8471
|
] }) }),
|
|
8122
|
-
/* @__PURE__ */ (0,
|
|
8472
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsx)("tbody", { children: candidates.map((candidate) => {
|
|
8123
8473
|
const resolved = candidate.status === "resolved";
|
|
8124
|
-
return /* @__PURE__ */ (0,
|
|
8125
|
-
/* @__PURE__ */ (0,
|
|
8126
|
-
/* @__PURE__ */ (0,
|
|
8127
|
-
fields.map((field) => /* @__PURE__ */ (0,
|
|
8128
|
-
/* @__PURE__ */ (0,
|
|
8129
|
-
/* @__PURE__ */ (0,
|
|
8474
|
+
return /* @__PURE__ */ (0, import_jsx_runtime78.jsxs)("tr", { "data-status": candidate.status ?? "pending", children: [
|
|
8475
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("input", { type: "checkbox", checked: selection.has(candidate.id), onChange: () => toggle(candidate.id), "aria-label": fillLabel(labels.selectCandidate, { id: candidate.id }) }) }),
|
|
8476
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("span", { className: "uix-match-review__confidence", children: candidate.confidence == null ? labels.notScored : `${Math.round(candidate.confidence * 100)}%` }) }),
|
|
8477
|
+
fields.map((field) => /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("td", { children: field.render?.(candidate.record[field.id], candidate.record) ?? valueText(candidate.record[field.id]) }, field.id)),
|
|
8478
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(StatusPill, { tone: resolved ? "success" : "warning", children: resolved ? candidate.decision ? decisionLabel[candidate.decision] : labels.resolved : labels.pending }) }),
|
|
8479
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime78.jsx)("div", { className: "uix-match-review__actions", children: ["accept", "dismiss", "split", "pick-other"].map((action) => /* @__PURE__ */ (0, import_jsx_runtime78.jsx)(
|
|
8130
8480
|
"button",
|
|
8131
8481
|
{
|
|
8132
8482
|
type: "button",
|
|
@@ -8140,12 +8490,12 @@ function MatchReview({
|
|
|
8140
8490
|
] }, candidate.id);
|
|
8141
8491
|
}) })
|
|
8142
8492
|
] }) }),
|
|
8143
|
-
/* @__PURE__ */ (0,
|
|
8493
|
+
/* @__PURE__ */ (0, import_jsx_runtime78.jsx)("p", { className: "uix-visually-hidden", "aria-live": "polite", children: announcement })
|
|
8144
8494
|
] });
|
|
8145
8495
|
}
|
|
8146
8496
|
|
|
8147
8497
|
// src/components/MetricInput.tsx
|
|
8148
|
-
var
|
|
8498
|
+
var import_react55 = require("react");
|
|
8149
8499
|
|
|
8150
8500
|
// src/metric-model.ts
|
|
8151
8501
|
function decimals(value) {
|
|
@@ -8170,7 +8520,7 @@ function parseMetricValue(value) {
|
|
|
8170
8520
|
}
|
|
8171
8521
|
|
|
8172
8522
|
// src/components/MetricInput.tsx
|
|
8173
|
-
var
|
|
8523
|
+
var import_jsx_runtime79 = require("react/jsx-runtime");
|
|
8174
8524
|
var defaultMetricFormat = (input) => input == null ? "" : String(input);
|
|
8175
8525
|
function MetricInput({
|
|
8176
8526
|
value,
|
|
@@ -8189,11 +8539,11 @@ function MetricInput({
|
|
|
8189
8539
|
className,
|
|
8190
8540
|
id: providedId
|
|
8191
8541
|
}) {
|
|
8192
|
-
const generatedId = (0,
|
|
8542
|
+
const generatedId = (0, import_react55.useId)();
|
|
8193
8543
|
const id = providedId ?? generatedId;
|
|
8194
8544
|
const errorId = `${id}-error`;
|
|
8195
|
-
const [text, setText] = (0,
|
|
8196
|
-
(0,
|
|
8545
|
+
const [text, setText] = (0, import_react55.useState)(() => format(value));
|
|
8546
|
+
(0, import_react55.useEffect)(() => setText(format(value)), [value, format]);
|
|
8197
8547
|
const commit = (input) => {
|
|
8198
8548
|
const parsed = parse(input);
|
|
8199
8549
|
if (input.trim() === "" || parsed !== null) {
|
|
@@ -8219,10 +8569,10 @@ function MetricInput({
|
|
|
8219
8569
|
const parsed = parse(event.currentTarget.value);
|
|
8220
8570
|
setText(parsed === null && event.currentTarget.value.trim() !== "" ? format(value) : format(parsed));
|
|
8221
8571
|
};
|
|
8222
|
-
return /* @__PURE__ */ (0,
|
|
8223
|
-
/* @__PURE__ */ (0,
|
|
8224
|
-
/* @__PURE__ */ (0,
|
|
8225
|
-
/* @__PURE__ */ (0,
|
|
8572
|
+
return /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("div", { className: cx("uix-metric-input", invalid && "uix-metric-input--invalid", className), children: [
|
|
8573
|
+
/* @__PURE__ */ (0, import_jsx_runtime79.jsx)("label", { className: "uix-field__label", htmlFor: id, children: label }),
|
|
8574
|
+
/* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("div", { className: "uix-metric-input__control", children: [
|
|
8575
|
+
/* @__PURE__ */ (0, import_jsx_runtime79.jsx)(
|
|
8226
8576
|
Input,
|
|
8227
8577
|
{
|
|
8228
8578
|
id,
|
|
@@ -8241,22 +8591,22 @@ function MetricInput({
|
|
|
8241
8591
|
readOnly
|
|
8242
8592
|
}
|
|
8243
8593
|
),
|
|
8244
|
-
unit && /* @__PURE__ */ (0,
|
|
8245
|
-
/* @__PURE__ */ (0,
|
|
8246
|
-
/* @__PURE__ */ (0,
|
|
8247
|
-
/* @__PURE__ */ (0,
|
|
8594
|
+
unit && /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("span", { className: "uix-metric-input__unit", "aria-hidden": "true", children: unit }),
|
|
8595
|
+
/* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("span", { className: "uix-metric-input__steps", children: [
|
|
8596
|
+
/* @__PURE__ */ (0, import_jsx_runtime79.jsx)("button", { type: "button", className: "uix-metric-input__step", onClick: () => stepBy(1), disabled: disabled || readOnly, "aria-label": `Increase ${label}`, children: "+" }),
|
|
8597
|
+
/* @__PURE__ */ (0, import_jsx_runtime79.jsx)("button", { type: "button", className: "uix-metric-input__step", onClick: () => stepBy(-1), disabled: disabled || readOnly, "aria-label": `Decrease ${label}`, children: "\u2212" })
|
|
8248
8598
|
] })
|
|
8249
8599
|
] }),
|
|
8250
|
-
unit && /* @__PURE__ */ (0,
|
|
8600
|
+
unit && /* @__PURE__ */ (0, import_jsx_runtime79.jsxs)("span", { className: "uix-visually-hidden", children: [
|
|
8251
8601
|
"Unit: ",
|
|
8252
8602
|
unit
|
|
8253
8603
|
] }),
|
|
8254
|
-
invalid && errorMessage && /* @__PURE__ */ (0,
|
|
8604
|
+
invalid && errorMessage && /* @__PURE__ */ (0, import_jsx_runtime79.jsx)("span", { id: errorId, className: "uix-field__error", children: errorMessage })
|
|
8255
8605
|
] });
|
|
8256
8606
|
}
|
|
8257
8607
|
|
|
8258
8608
|
// src/components/LicensePositionBar.tsx
|
|
8259
|
-
var
|
|
8609
|
+
var import_jsx_runtime80 = require("react/jsx-runtime");
|
|
8260
8610
|
var defaultCapacityFormat = (value) => new Intl.NumberFormat().format(value);
|
|
8261
8611
|
function LicensePositionBar({
|
|
8262
8612
|
consumed,
|
|
@@ -8277,18 +8627,18 @@ function LicensePositionBar({
|
|
|
8277
8627
|
const percent = safeEntitled === 0 ? safeConsumed > 0 ? 100 : 0 : safeConsumed / safeEntitled * 100;
|
|
8278
8628
|
const format = (value) => `${formatValue(value)}${unit ? ` ${unit}` : ""}`;
|
|
8279
8629
|
const summary = `${consumedLabel}: ${format(safeConsumed)}. ${entitledLabel}: ${format(safeEntitled)}. ${over > 0 ? `${format(over)} ${overLabel}` : `${format(available)} ${availableLabel}`}.`;
|
|
8280
|
-
return /* @__PURE__ */ (0,
|
|
8281
|
-
/* @__PURE__ */ (0,
|
|
8282
|
-
/* @__PURE__ */ (0,
|
|
8630
|
+
return /* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: cx("uix-license-position", over > 0 && "uix-license-position--over", className), ...props, children: [
|
|
8631
|
+
/* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "uix-license-position__header", children: [
|
|
8632
|
+
/* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("span", { className: "uix-license-position__value", children: [
|
|
8283
8633
|
format(safeConsumed),
|
|
8284
8634
|
" / ",
|
|
8285
8635
|
format(safeEntitled)
|
|
8286
8636
|
] }),
|
|
8287
|
-
/* @__PURE__ */ (0,
|
|
8637
|
+
/* @__PURE__ */ (0, import_jsx_runtime80.jsx)(StatusPill, { tone: over > 0 ? "danger" : percent >= 80 ? "warning" : "success", children: over > 0 ? `${format(over)} ${overLabel}` : `${format(available)} ${availableLabel}` })
|
|
8288
8638
|
] }),
|
|
8289
|
-
/* @__PURE__ */ (0,
|
|
8290
|
-
/* @__PURE__ */ (0,
|
|
8291
|
-
over > 0 && /* @__PURE__ */ (0,
|
|
8639
|
+
/* @__PURE__ */ (0, import_jsx_runtime80.jsxs)("div", { className: "uix-license-position__track", children: [
|
|
8640
|
+
/* @__PURE__ */ (0, import_jsx_runtime80.jsx)(Meter, { value: Math.min(100, percent), tone: over > 0 ? "danger" : percent >= 80 ? "warning" : "success", "aria-label": summary, "aria-valuetext": summary }),
|
|
8641
|
+
over > 0 && /* @__PURE__ */ (0, import_jsx_runtime80.jsx)(
|
|
8292
8642
|
"span",
|
|
8293
8643
|
{
|
|
8294
8644
|
className: "uix-license-position__overflow",
|
|
@@ -8297,12 +8647,12 @@ function LicensePositionBar({
|
|
|
8297
8647
|
}
|
|
8298
8648
|
)
|
|
8299
8649
|
] }),
|
|
8300
|
-
/* @__PURE__ */ (0,
|
|
8650
|
+
/* @__PURE__ */ (0, import_jsx_runtime80.jsx)("span", { className: "uix-visually-hidden", children: summary })
|
|
8301
8651
|
] });
|
|
8302
8652
|
}
|
|
8303
8653
|
|
|
8304
8654
|
// src/components/BrandProfiles.tsx
|
|
8305
|
-
var
|
|
8655
|
+
var import_react57 = require("react");
|
|
8306
8656
|
|
|
8307
8657
|
// src/color-model.ts
|
|
8308
8658
|
var clamp2 = (value, min, max) => Math.min(max, Math.max(min, value));
|
|
@@ -8371,8 +8721,8 @@ function meetsContrast(background, foreground, minimum = 4.5) {
|
|
|
8371
8721
|
}
|
|
8372
8722
|
|
|
8373
8723
|
// src/components/ColorPicker.tsx
|
|
8374
|
-
var
|
|
8375
|
-
var
|
|
8724
|
+
var import_react56 = require("react");
|
|
8725
|
+
var import_jsx_runtime81 = require("react/jsx-runtime");
|
|
8376
8726
|
var DEFAULT_COLOR_PICKER_LABELS = {
|
|
8377
8727
|
trigger: "{label}: {color}",
|
|
8378
8728
|
sample: "Aa",
|
|
@@ -8403,17 +8753,17 @@ function ColorPicker({
|
|
|
8403
8753
|
labels: labelOverrides
|
|
8404
8754
|
}) {
|
|
8405
8755
|
const labels = { ...DEFAULT_COLOR_PICKER_LABELS, ...labelOverrides };
|
|
8406
|
-
const id = (0,
|
|
8407
|
-
const triggerRef = (0,
|
|
8408
|
-
const dialogRef = (0,
|
|
8409
|
-
const [open, setOpen] = (0,
|
|
8756
|
+
const id = (0, import_react56.useId)();
|
|
8757
|
+
const triggerRef = (0, import_react56.useRef)(null);
|
|
8758
|
+
const dialogRef = (0, import_react56.useRef)(null);
|
|
8759
|
+
const [open, setOpen] = (0, import_react56.useState)(false);
|
|
8410
8760
|
const normalized = normalizeHex(value) ?? "#000000";
|
|
8411
|
-
const [hexText, setHexText] = (0,
|
|
8412
|
-
const hsv = (0,
|
|
8761
|
+
const [hexText, setHexText] = (0, import_react56.useState)(normalized);
|
|
8762
|
+
const hsv = (0, import_react56.useMemo)(() => rgbToHsv(hexToRgb(normalized)), [normalized]);
|
|
8413
8763
|
const ratio = contrastRatio(normalized, foreground) ?? 0;
|
|
8414
8764
|
const passes = ratio >= minimumContrast;
|
|
8415
|
-
(0,
|
|
8416
|
-
(0,
|
|
8765
|
+
(0, import_react56.useEffect)(() => setHexText(normalized), [normalized]);
|
|
8766
|
+
(0, import_react56.useEffect)(() => {
|
|
8417
8767
|
if (!open) return;
|
|
8418
8768
|
const dialog = dialogRef.current;
|
|
8419
8769
|
dialog?.querySelector("input,button")?.focus();
|
|
@@ -8456,8 +8806,8 @@ function ColorPicker({
|
|
|
8456
8806
|
if (next) onChange(next);
|
|
8457
8807
|
};
|
|
8458
8808
|
const sampleStyle = { backgroundColor: normalized };
|
|
8459
|
-
return /* @__PURE__ */ (0,
|
|
8460
|
-
/* @__PURE__ */ (0,
|
|
8809
|
+
return /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("div", { className: cx("uix-color-picker", className), children: [
|
|
8810
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsxs)(
|
|
8461
8811
|
"button",
|
|
8462
8812
|
{
|
|
8463
8813
|
ref: triggerRef,
|
|
@@ -8469,12 +8819,12 @@ function ColorPicker({
|
|
|
8469
8819
|
onClick: () => setOpen((current) => !current),
|
|
8470
8820
|
disabled,
|
|
8471
8821
|
children: [
|
|
8472
|
-
/* @__PURE__ */ (0,
|
|
8473
|
-
/* @__PURE__ */ (0,
|
|
8822
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsx)("span", { className: "uix-color-picker__swatch", style: sampleStyle, "aria-hidden": "true" }),
|
|
8823
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsx)("span", { children: normalized })
|
|
8474
8824
|
]
|
|
8475
8825
|
}
|
|
8476
8826
|
),
|
|
8477
|
-
open && /* @__PURE__ */ (0,
|
|
8827
|
+
open && /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)(
|
|
8478
8828
|
"div",
|
|
8479
8829
|
{
|
|
8480
8830
|
ref: dialogRef,
|
|
@@ -8485,55 +8835,55 @@ function ColorPicker({
|
|
|
8485
8835
|
className: "uix-color-picker__popover",
|
|
8486
8836
|
onKeyDown: onDialogKeyDown,
|
|
8487
8837
|
children: [
|
|
8488
|
-
/* @__PURE__ */ (0,
|
|
8489
|
-
/* @__PURE__ */ (0,
|
|
8838
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsx)("div", { className: "uix-color-picker__preview", style: sampleStyle, children: /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("span", { style: { color: foreground }, children: labels.sample }) }),
|
|
8839
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("label", { className: "uix-color-picker__range", children: [
|
|
8490
8840
|
labels.hue,
|
|
8491
8841
|
" ",
|
|
8492
|
-
/* @__PURE__ */ (0,
|
|
8842
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("span", { children: [
|
|
8493
8843
|
Math.round(hsv.h),
|
|
8494
8844
|
"\xB0"
|
|
8495
8845
|
] }),
|
|
8496
|
-
/* @__PURE__ */ (0,
|
|
8846
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsx)("input", { type: "range", min: "0", max: "359", value: Math.round(hsv.h), onChange: (event) => updateHsv({ h: Number(event.currentTarget.value) }) })
|
|
8497
8847
|
] }),
|
|
8498
|
-
/* @__PURE__ */ (0,
|
|
8848
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("label", { className: "uix-color-picker__range", children: [
|
|
8499
8849
|
labels.saturation,
|
|
8500
8850
|
" ",
|
|
8501
|
-
/* @__PURE__ */ (0,
|
|
8851
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("span", { children: [
|
|
8502
8852
|
Math.round(hsv.s * 100),
|
|
8503
8853
|
"%"
|
|
8504
8854
|
] }),
|
|
8505
|
-
/* @__PURE__ */ (0,
|
|
8855
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsx)("input", { type: "range", min: "0", max: "100", value: Math.round(hsv.s * 100), onChange: (event) => updateHsv({ s: Number(event.currentTarget.value) / 100 }) })
|
|
8506
8856
|
] }),
|
|
8507
|
-
/* @__PURE__ */ (0,
|
|
8857
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("label", { className: "uix-color-picker__range", children: [
|
|
8508
8858
|
labels.brightness,
|
|
8509
8859
|
" ",
|
|
8510
|
-
/* @__PURE__ */ (0,
|
|
8860
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("span", { children: [
|
|
8511
8861
|
Math.round(hsv.v * 100),
|
|
8512
8862
|
"%"
|
|
8513
8863
|
] }),
|
|
8514
|
-
/* @__PURE__ */ (0,
|
|
8864
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsx)("input", { type: "range", min: "0", max: "100", value: Math.round(hsv.v * 100), onChange: (event) => updateHsv({ v: Number(event.currentTarget.value) / 100 }) })
|
|
8515
8865
|
] }),
|
|
8516
|
-
/* @__PURE__ */ (0,
|
|
8866
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("label", { className: "uix-color-picker__hex", children: [
|
|
8517
8867
|
labels.hex,
|
|
8518
|
-
/* @__PURE__ */ (0,
|
|
8519
|
-
/* @__PURE__ */ (0,
|
|
8868
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("span", { className: "uix-color-picker__hex-row", children: [
|
|
8869
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsx)("input", { className: "uix-input", value: hexText, onChange: (event) => setHexText(event.currentTarget.value), onBlur: commitHex, onKeyDown: (event) => {
|
|
8520
8870
|
if (event.key === "Enter") commitHex();
|
|
8521
8871
|
}, "aria-invalid": !normalizeHex(hexText) }),
|
|
8522
|
-
/* @__PURE__ */ (0,
|
|
8872
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsx)("button", { type: "button", className: "uix-btn uix-btn--secondary uix-btn--sm", onClick: commitHex, disabled: !normalizeHex(hexText), children: labels.set })
|
|
8523
8873
|
] })
|
|
8524
8874
|
] }),
|
|
8525
|
-
(presets.length > 0 || recent.length > 0) && /* @__PURE__ */ (0,
|
|
8526
|
-
presets.length > 0 && /* @__PURE__ */ (0,
|
|
8527
|
-
/* @__PURE__ */ (0,
|
|
8528
|
-
/* @__PURE__ */ (0,
|
|
8875
|
+
(presets.length > 0 || recent.length > 0) && /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("div", { className: "uix-color-picker__palettes", children: [
|
|
8876
|
+
presets.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("fieldset", { children: [
|
|
8877
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsx)("legend", { children: labels.presets }),
|
|
8878
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsx)("div", { children: presets.map((color) => /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("button", { type: "button", className: "uix-color-picker__preset", style: { backgroundColor: normalizeHex(color) ?? color }, onClick: () => choose(color), "aria-label": fillLabel(labels.usePreset, { color }) }, color)) })
|
|
8529
8879
|
] }),
|
|
8530
|
-
recent.length > 0 && /* @__PURE__ */ (0,
|
|
8531
|
-
/* @__PURE__ */ (0,
|
|
8532
|
-
/* @__PURE__ */ (0,
|
|
8880
|
+
recent.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime81.jsxs)("fieldset", { children: [
|
|
8881
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsx)("legend", { children: labels.recent }),
|
|
8882
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsx)("div", { children: recent.map((color) => /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("button", { type: "button", className: "uix-color-picker__preset", style: { backgroundColor: normalizeHex(color) ?? color }, onClick: () => choose(color), "aria-label": fillLabel(labels.useRecent, { color }) }, color)) })
|
|
8533
8883
|
] })
|
|
8534
8884
|
] }),
|
|
8535
|
-
/* @__PURE__ */ (0,
|
|
8536
|
-
/* @__PURE__ */ (0,
|
|
8885
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.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 }) }),
|
|
8886
|
+
/* @__PURE__ */ (0, import_jsx_runtime81.jsx)("button", { type: "button", className: "uix-btn uix-btn--primary uix-btn--sm", onClick: close, children: labels.done })
|
|
8537
8887
|
]
|
|
8538
8888
|
}
|
|
8539
8889
|
)
|
|
@@ -8541,7 +8891,7 @@ function ColorPicker({
|
|
|
8541
8891
|
}
|
|
8542
8892
|
|
|
8543
8893
|
// src/components/BrandProfiles.tsx
|
|
8544
|
-
var
|
|
8894
|
+
var import_jsx_runtime82 = require("react/jsx-runtime");
|
|
8545
8895
|
var PROFILE_PROPERTIES = {
|
|
8546
8896
|
brand: "--uix-brand",
|
|
8547
8897
|
brandForeground: "--uix-brand-fg",
|
|
@@ -8633,7 +8983,7 @@ function BrandProfileEditor({
|
|
|
8633
8983
|
labels: labelOverrides
|
|
8634
8984
|
}) {
|
|
8635
8985
|
const labels = { ...DEFAULT_BRAND_PROFILE_EDITOR_LABELS, ...labelOverrides };
|
|
8636
|
-
const [announcement, setAnnouncement] = (0,
|
|
8986
|
+
const [announcement, setAnnouncement] = (0, import_react57.useState)("");
|
|
8637
8987
|
const update = (patch) => onChange({ ...value, ...patch });
|
|
8638
8988
|
const apply = () => {
|
|
8639
8989
|
if (applyTarget !== null) applyBrandProfile(value, applyTarget);
|
|
@@ -8650,54 +9000,54 @@ function BrandProfileEditor({
|
|
|
8650
9000
|
...value.typography?.sans ? { "--uix-font-sans": value.typography.sans } : {},
|
|
8651
9001
|
...value.typography?.heading ? { "--uix-font-heading": value.typography.heading } : {}
|
|
8652
9002
|
};
|
|
8653
|
-
return /* @__PURE__ */ (0,
|
|
8654
|
-
/* @__PURE__ */ (0,
|
|
8655
|
-
profiles.length > 0 && /* @__PURE__ */ (0,
|
|
9003
|
+
return /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("section", { className: cx("uix-brand-profiles", className), "aria-label": labels.region, children: [
|
|
9004
|
+
/* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("div", { className: "uix-brand-profiles__form", children: [
|
|
9005
|
+
profiles.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("label", { className: "uix-field__label", children: [
|
|
8656
9006
|
labels.profile,
|
|
8657
|
-
/* @__PURE__ */ (0,
|
|
9007
|
+
/* @__PURE__ */ (0, import_jsx_runtime82.jsx)("select", { className: "uix-select", value: value.id, onChange: (event) => {
|
|
8658
9008
|
const selected = profiles.find((profile) => profile.id === event.currentTarget.value);
|
|
8659
9009
|
if (selected) onSelectProfile?.(selected);
|
|
8660
|
-
}, children: profiles.map((profile) => /* @__PURE__ */ (0,
|
|
9010
|
+
}, children: profiles.map((profile) => /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("option", { value: profile.id, children: profile.name }, profile.id)) })
|
|
8661
9011
|
] }),
|
|
8662
|
-
/* @__PURE__ */ (0,
|
|
9012
|
+
/* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("label", { className: "uix-field__label", children: [
|
|
8663
9013
|
labels.name,
|
|
8664
|
-
/* @__PURE__ */ (0,
|
|
9014
|
+
/* @__PURE__ */ (0, import_jsx_runtime82.jsx)("input", { className: "uix-input", value: value.name, onChange: (event) => update({ name: event.currentTarget.value }) })
|
|
8665
9015
|
] }),
|
|
8666
|
-
/* @__PURE__ */ (0,
|
|
8667
|
-
/* @__PURE__ */ (0,
|
|
9016
|
+
/* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("div", { className: "uix-brand-profiles__colors", children: [
|
|
9017
|
+
/* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("label", { children: [
|
|
8668
9018
|
labels.brand,
|
|
8669
|
-
/* @__PURE__ */ (0,
|
|
9019
|
+
/* @__PURE__ */ (0, import_jsx_runtime82.jsx)(ColorPicker, { label: labels.brandColor, value: value.brand, foreground: value.brandForeground, presets: colorPresets, onChange: (brand) => update({ brand }) })
|
|
8670
9020
|
] }),
|
|
8671
|
-
/* @__PURE__ */ (0,
|
|
9021
|
+
/* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("label", { children: [
|
|
8672
9022
|
labels.onBrand,
|
|
8673
|
-
/* @__PURE__ */ (0,
|
|
9023
|
+
/* @__PURE__ */ (0, import_jsx_runtime82.jsx)(ColorPicker, { label: labels.onBrandColor, value: value.brandForeground, foreground: value.brand, presets: colorPresets, onChange: (brandForeground) => update({ brandForeground }) })
|
|
8674
9024
|
] })
|
|
8675
9025
|
] }),
|
|
8676
|
-
/* @__PURE__ */ (0,
|
|
9026
|
+
/* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("label", { className: "uix-field__label", children: [
|
|
8677
9027
|
labels.bodyFont,
|
|
8678
|
-
/* @__PURE__ */ (0,
|
|
9028
|
+
/* @__PURE__ */ (0, import_jsx_runtime82.jsx)("input", { className: "uix-input", value: value.typography?.sans ?? "", onChange: (event) => update({ typography: { ...value.typography, sans: event.currentTarget.value || void 0 } }) })
|
|
8679
9029
|
] }),
|
|
8680
|
-
/* @__PURE__ */ (0,
|
|
9030
|
+
/* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("label", { className: "uix-field__label", children: [
|
|
8681
9031
|
labels.headingFont,
|
|
8682
|
-
/* @__PURE__ */ (0,
|
|
9032
|
+
/* @__PURE__ */ (0, import_jsx_runtime82.jsx)("input", { className: "uix-input", value: value.typography?.heading ?? "", onChange: (event) => update({ typography: { ...value.typography, heading: event.currentTarget.value || void 0 } }) })
|
|
8683
9033
|
] }),
|
|
8684
|
-
/* @__PURE__ */ (0,
|
|
9034
|
+
/* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("label", { className: "uix-file-upload uix-brand-profiles__upload", children: [
|
|
8685
9035
|
labels.logoFile,
|
|
8686
|
-
/* @__PURE__ */ (0,
|
|
9036
|
+
/* @__PURE__ */ (0, import_jsx_runtime82.jsx)("input", { type: "file", accept: "image/*", onChange: onFile })
|
|
8687
9037
|
] }),
|
|
8688
|
-
/* @__PURE__ */ (0,
|
|
8689
|
-
/* @__PURE__ */ (0,
|
|
9038
|
+
/* @__PURE__ */ (0, import_jsx_runtime82.jsx)("button", { type: "button", className: "uix-btn uix-btn--primary", onClick: apply, children: labels.apply }),
|
|
9039
|
+
/* @__PURE__ */ (0, import_jsx_runtime82.jsx)("span", { className: "uix-visually-hidden", "aria-live": "polite", children: announcement })
|
|
8690
9040
|
] }),
|
|
8691
|
-
/* @__PURE__ */ (0,
|
|
8692
|
-
/* @__PURE__ */ (0,
|
|
8693
|
-
value.logo ? /* @__PURE__ */ (0,
|
|
8694
|
-
/* @__PURE__ */ (0,
|
|
9041
|
+
/* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("div", { className: "uix-brand-profiles__preview", style: previewStyle, "aria-label": fillLabel(labels.preview, { name: value.name }), children: [
|
|
9042
|
+
/* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("div", { className: "uix-brand-profiles__preview-header", children: [
|
|
9043
|
+
value.logo ? /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("img", { src: value.logo.src, alt: value.logo.alt }) : /* @__PURE__ */ (0, import_jsx_runtime82.jsx)("span", { className: "uix-brand-profiles__logo-placeholder", children: labels.logoPlaceholder }),
|
|
9044
|
+
/* @__PURE__ */ (0, import_jsx_runtime82.jsx)("strong", { children: value.name || labels.previewTitleFallback })
|
|
8695
9045
|
] }),
|
|
8696
|
-
/* @__PURE__ */ (0,
|
|
8697
|
-
/* @__PURE__ */ (0,
|
|
8698
|
-
/* @__PURE__ */ (0,
|
|
8699
|
-
/* @__PURE__ */ (0,
|
|
8700
|
-
/* @__PURE__ */ (0,
|
|
9046
|
+
/* @__PURE__ */ (0, import_jsx_runtime82.jsxs)("div", { className: "uix-brand-profiles__preview-body", children: [
|
|
9047
|
+
/* @__PURE__ */ (0, import_jsx_runtime82.jsx)("h3", { children: labels.previewHeading }),
|
|
9048
|
+
/* @__PURE__ */ (0, import_jsx_runtime82.jsx)("p", { children: labels.previewBody }),
|
|
9049
|
+
/* @__PURE__ */ (0, import_jsx_runtime82.jsx)("button", { type: "button", className: "uix-btn uix-btn--primary", children: labels.previewPrimary }),
|
|
9050
|
+
/* @__PURE__ */ (0, import_jsx_runtime82.jsx)("a", { href: "#brand-profile-preview", children: labels.previewLink })
|
|
8701
9051
|
] })
|
|
8702
9052
|
] })
|
|
8703
9053
|
] });
|
|
@@ -8705,7 +9055,7 @@ function BrandProfileEditor({
|
|
|
8705
9055
|
var BrandProfiles = BrandProfileEditor;
|
|
8706
9056
|
|
|
8707
9057
|
// src/components/DiffViewer.tsx
|
|
8708
|
-
var
|
|
9058
|
+
var import_react58 = require("react");
|
|
8709
9059
|
|
|
8710
9060
|
// src/diff-model.ts
|
|
8711
9061
|
function isJsonObject(value) {
|
|
@@ -8756,7 +9106,7 @@ function summarizeDiff(entries, resolutions = {}) {
|
|
|
8756
9106
|
}
|
|
8757
9107
|
|
|
8758
9108
|
// src/components/DiffViewer.tsx
|
|
8759
|
-
var
|
|
9109
|
+
var import_jsx_runtime83 = require("react/jsx-runtime");
|
|
8760
9110
|
var DEFAULT_DIFF_VIEWER_LABELS = {
|
|
8761
9111
|
base: "Base",
|
|
8762
9112
|
current: "Current",
|
|
@@ -8801,33 +9151,33 @@ function DiffViewer({
|
|
|
8801
9151
|
const labels = { ...DEFAULT_DIFF_VIEWER_LABELS, ...labelOverrides };
|
|
8802
9152
|
const resolutionLabel = { accept: labels.resolutionAccept, skip: labels.resolutionSkip, pending: labels.resolutionPending };
|
|
8803
9153
|
const buttonSize = controlSize === "md" ? void 0 : `uix-btn--${controlSize}`;
|
|
8804
|
-
const id = (0,
|
|
8805
|
-
const entries = (0,
|
|
8806
|
-
const [internalResolutions, setInternalResolutions] = (0,
|
|
9154
|
+
const id = (0, import_react58.useId)();
|
|
9155
|
+
const entries = (0, import_react58.useMemo)(() => providedEntries ?? buildThreeWayDiff(base, current, incoming), [providedEntries, base, current, incoming]);
|
|
9156
|
+
const [internalResolutions, setInternalResolutions] = (0, import_react58.useState)({});
|
|
8807
9157
|
const resolutions = controlledResolutions ?? internalResolutions;
|
|
8808
9158
|
const summary = summarizeDiff(entries, resolutions);
|
|
8809
9159
|
const resolve = (path, resolution) => {
|
|
8810
9160
|
if (controlledResolutions === void 0) setInternalResolutions((currentState) => ({ ...currentState, [path]: resolution }));
|
|
8811
9161
|
onResolutionChange?.(path, resolution);
|
|
8812
9162
|
};
|
|
8813
|
-
if (entries.length === 0) return /* @__PURE__ */ (0,
|
|
8814
|
-
/* @__PURE__ */ (0,
|
|
8815
|
-
/* @__PURE__ */ (0,
|
|
9163
|
+
if (entries.length === 0) return /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("section", { className: cx("uix-diff-viewer uix-diff-viewer--empty", className), "aria-label": labels.region, children: [
|
|
9164
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsx)("h3", { children: labels.noDifferences }),
|
|
9165
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsx)("p", { children: labels.noDifferencesDetail })
|
|
8816
9166
|
] });
|
|
8817
|
-
return /* @__PURE__ */ (0,
|
|
8818
|
-
/* @__PURE__ */ (0,
|
|
8819
|
-
GROUPS.map((kind) => /* @__PURE__ */ (0,
|
|
8820
|
-
/* @__PURE__ */ (0,
|
|
9167
|
+
return /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("section", { className: cx("uix-diff-viewer", className), "aria-label": labels.region, "data-control-size": controlSize, children: [
|
|
9168
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("div", { className: "uix-diff-viewer__summary", role: "group", "aria-label": labels.summary, children: [
|
|
9169
|
+
GROUPS.map((kind) => /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("span", { children: [
|
|
9170
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsx)("b", { children: summary[kind] }),
|
|
8821
9171
|
" ",
|
|
8822
9172
|
labels[kind].toLowerCase()
|
|
8823
9173
|
] }, kind)),
|
|
8824
|
-
/* @__PURE__ */ (0,
|
|
8825
|
-
/* @__PURE__ */ (0,
|
|
9174
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("span", { children: [
|
|
9175
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsx)("b", { children: summary.resolved }),
|
|
8826
9176
|
" ",
|
|
8827
9177
|
labels.resolved
|
|
8828
9178
|
] }),
|
|
8829
|
-
/* @__PURE__ */ (0,
|
|
8830
|
-
/* @__PURE__ */ (0,
|
|
9179
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("span", { children: [
|
|
9180
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsx)("b", { children: summary.pending }),
|
|
8831
9181
|
" ",
|
|
8832
9182
|
labels.pending
|
|
8833
9183
|
] })
|
|
@@ -8835,33 +9185,33 @@ function DiffViewer({
|
|
|
8835
9185
|
GROUPS.map((kind) => {
|
|
8836
9186
|
const grouped = entries.filter((entry) => entry.kind === kind);
|
|
8837
9187
|
if (!grouped.length) return null;
|
|
8838
|
-
return /* @__PURE__ */ (0,
|
|
8839
|
-
/* @__PURE__ */ (0,
|
|
9188
|
+
return /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("section", { className: "uix-diff-viewer__group", "aria-labelledby": `${id}-${kind}`, children: [
|
|
9189
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("h3", { id: `${id}-${kind}`, children: [
|
|
8840
9190
|
labels[kind],
|
|
8841
9191
|
" ",
|
|
8842
|
-
/* @__PURE__ */ (0,
|
|
9192
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsx)("span", { children: grouped.length })
|
|
8843
9193
|
] }),
|
|
8844
9194
|
grouped.map((entry) => {
|
|
8845
9195
|
const resolution = resolutions[entry.path] ?? "pending";
|
|
8846
|
-
return /* @__PURE__ */ (0,
|
|
8847
|
-
/* @__PURE__ */ (0,
|
|
8848
|
-
/* @__PURE__ */ (0,
|
|
8849
|
-
/* @__PURE__ */ (0,
|
|
9196
|
+
return /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("details", { className: "uix-diff-viewer__entry", "data-kind": entry.kind, open: entry.kind === "conflicted", children: [
|
|
9197
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("summary", { children: [
|
|
9198
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsx)("code", { children: entry.path }),
|
|
9199
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsx)(StatusPill, { tone: resolution === "pending" ? "warning" : "success", children: resolutionLabel[resolution] })
|
|
8850
9200
|
] }),
|
|
8851
|
-
/* @__PURE__ */ (0,
|
|
8852
|
-
/* @__PURE__ */ (0,
|
|
8853
|
-
/* @__PURE__ */ (0,
|
|
9201
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsx)("div", { className: "uix-diff-viewer__versions", children: ["base", "current", "incoming"].map((version) => /* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("div", { role: "region", "aria-label": fillLabel(labels.valueFor, { version: labels[version], path: entry.path }), children: [
|
|
9202
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsx)("strong", { children: labels[version] }),
|
|
9203
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsx)("pre", { children: renderValue(entry[version], labels.notPresent) })
|
|
8854
9204
|
] }, version)) }),
|
|
8855
|
-
/* @__PURE__ */ (0,
|
|
8856
|
-
/* @__PURE__ */ (0,
|
|
8857
|
-
/* @__PURE__ */ (0,
|
|
8858
|
-
/* @__PURE__ */ (0,
|
|
9205
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsxs)("div", { className: "uix-diff-viewer__actions", role: "group", "aria-label": fillLabel(labels.resolve, { path: entry.path }), children: [
|
|
9206
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsx)("button", { type: "button", className: cx("uix-btn uix-btn--primary", buttonSize), "aria-label": fillLabel(labels.acceptIncomingFor, { path: entry.path }), "aria-pressed": resolution === "accept", onClick: () => resolve(entry.path, "accept"), children: labels.acceptIncoming }),
|
|
9207
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsx)("button", { type: "button", className: cx("uix-btn uix-btn--secondary", buttonSize), "aria-label": fillLabel(labels.keepCurrentFor, { path: entry.path }), "aria-pressed": resolution === "skip", onClick: () => resolve(entry.path, "skip"), children: labels.keepCurrent }),
|
|
9208
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsx)("button", { type: "button", className: cx("uix-btn uix-btn--ghost", buttonSize), "aria-label": fillLabel(labels.markPendingFor, { path: entry.path }), "aria-pressed": resolution === "pending", onClick: () => resolve(entry.path, "pending"), children: labels.markPending })
|
|
8859
9209
|
] })
|
|
8860
9210
|
] }, entry.path);
|
|
8861
9211
|
})
|
|
8862
9212
|
] }, kind);
|
|
8863
9213
|
}),
|
|
8864
|
-
/* @__PURE__ */ (0,
|
|
9214
|
+
/* @__PURE__ */ (0, import_jsx_runtime83.jsx)("p", { className: "uix-visually-hidden", "aria-live": "polite", children: fillLabel(labels.progress, { resolved: summary.resolved, total: entries.length }) })
|
|
8865
9215
|
] });
|
|
8866
9216
|
}
|
|
8867
9217
|
// Annotate the CommonJS export names for ESM import in node:
|
|
@@ -8900,6 +9250,7 @@ function DiffViewer({
|
|
|
8900
9250
|
ContentList,
|
|
8901
9251
|
ContentListItem,
|
|
8902
9252
|
CopyButton,
|
|
9253
|
+
DAY,
|
|
8903
9254
|
DEFAULT_BRAND_PROFILE_EDITOR_LABELS,
|
|
8904
9255
|
DEFAULT_BUILDER_CANVAS_LABELS,
|
|
8905
9256
|
DEFAULT_COLOR_PICKER_LABELS,
|
|
@@ -8911,6 +9262,7 @@ function DiffViewer({
|
|
|
8911
9262
|
DEFAULT_RULE_BUILDER_LABELS,
|
|
8912
9263
|
DEFAULT_SAVE_STATUS_LABELS,
|
|
8913
9264
|
DEFAULT_SCHEDULING_CALENDAR_LABELS,
|
|
9265
|
+
DEFAULT_SCHEDULING_TIMELINE_LABELS,
|
|
8914
9266
|
DEFAULT_STEP_STATE_LABELS,
|
|
8915
9267
|
DateRangePicker,
|
|
8916
9268
|
DescriptionItem,
|
|
@@ -8932,6 +9284,7 @@ function DiffViewer({
|
|
|
8932
9284
|
Flow,
|
|
8933
9285
|
FlowNode,
|
|
8934
9286
|
ForbiddenState,
|
|
9287
|
+
HOUR,
|
|
8935
9288
|
Highlighted,
|
|
8936
9289
|
Inbox,
|
|
8937
9290
|
InboxDetail,
|
|
@@ -8989,6 +9342,7 @@ function DiffViewer({
|
|
|
8989
9342
|
SaveStatus,
|
|
8990
9343
|
SavedViewMenu,
|
|
8991
9344
|
SchedulingCalendar,
|
|
9345
|
+
SchedulingTimeline,
|
|
8992
9346
|
SearchSuggest,
|
|
8993
9347
|
SectionHead,
|
|
8994
9348
|
Segmented,
|
|
@@ -9044,6 +9398,7 @@ function DiffViewer({
|
|
|
9044
9398
|
createToastApi,
|
|
9045
9399
|
createToastStore,
|
|
9046
9400
|
cx,
|
|
9401
|
+
defaultTimelineStep,
|
|
9047
9402
|
enumerateDateSpan,
|
|
9048
9403
|
filterComboboxOptions,
|
|
9049
9404
|
findRuleNodeDepth,
|
|
@@ -9057,6 +9412,7 @@ function DiffViewer({
|
|
|
9057
9412
|
isDateUnavailable,
|
|
9058
9413
|
isRuleGroup,
|
|
9059
9414
|
layeredNeighbor,
|
|
9415
|
+
layoutLane,
|
|
9060
9416
|
layoutLayeredGraph,
|
|
9061
9417
|
layoutRelationshipGraph,
|
|
9062
9418
|
mapRuleGroup,
|
|
@@ -9070,6 +9426,8 @@ function DiffViewer({
|
|
|
9070
9426
|
parseDateValue,
|
|
9071
9427
|
parseMetricValue,
|
|
9072
9428
|
parseView,
|
|
9429
|
+
pixelsToMs,
|
|
9430
|
+
placeSpan,
|
|
9073
9431
|
relationshipNeighbors,
|
|
9074
9432
|
relativeTimeValue,
|
|
9075
9433
|
removeRuleNode,
|
|
@@ -9084,11 +9442,14 @@ function DiffViewer({
|
|
|
9084
9442
|
selectAllState,
|
|
9085
9443
|
selectRangeDate,
|
|
9086
9444
|
serializeView,
|
|
9445
|
+
shiftSpan,
|
|
9087
9446
|
shouldVirtualize,
|
|
9447
|
+
snapToStep,
|
|
9088
9448
|
startOfMonth,
|
|
9089
9449
|
stepMetricValue,
|
|
9090
9450
|
summarizeDiff,
|
|
9091
9451
|
summarizeRule,
|
|
9452
|
+
timelineTicks,
|
|
9092
9453
|
toDateKey,
|
|
9093
9454
|
toast,
|
|
9094
9455
|
toggleId,
|