@bridge-ds/toolbar 0.3.0 → 0.4.1
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 +11 -2
- package/dist/{Toolbar-DJUb3p2c.js → Toolbar-ByLHemKF.js} +146 -26
- package/dist/Toolbar-ByLHemKF.js.map +1 -0
- package/dist/{index-CCTqUFz3.js → index-cRndUN9A.js} +3 -3
- package/dist/{index-CCTqUFz3.js.map → index-cRndUN9A.js.map} +1 -1
- package/dist/index.js +1 -1
- package/dist/markers.d.ts +25 -0
- package/dist/{session-D6oH78KG.js → session-Dvma9jtT.js} +5 -1
- package/dist/session-Dvma9jtT.js.map +1 -0
- package/dist/session.d.ts +3 -0
- package/dist/together.js +1 -1
- package/dist/useMarkedChanges.d.ts +2 -0
- package/package.json +2 -2
- package/dist/Toolbar-DJUb3p2c.js.map +0 -1
- package/dist/session-D6oH78KG.js.map +0 -1
package/README.md
CHANGED
|
@@ -2,10 +2,19 @@
|
|
|
2
2
|
|
|
3
3
|
The Bridge toolbar for a product built with the Bridge design system. Bridge Studio opens the product with
|
|
4
4
|
`?bridge=<change>` ("Try it in the product"); the toolbar then lets anyone browse the real product and flip between
|
|
5
|
-
**Live product** (before) and **This change** (after), with **Show what changed
|
|
5
|
+
**Live product** (before) and **This change** (after), with **Show what changed**.
|
|
6
6
|
|
|
7
7
|
- **Code changes** (an exploration in the product's repository, a feature branch): Before is the product in
|
|
8
|
-
production, After is the branch's preview. Flipping keeps the screen and the scroll position.
|
|
8
|
+
production, After is the branch's preview. Flipping keeps the screen and the scroll position. Production is another
|
|
9
|
+
origin, so the toolbar cannot measure the difference: the change marks each new or changed area of the UI with
|
|
10
|
+
`data-bridge-change="<short plain label>"` on its outermost element (Bridge tells Claude to, in every exploration).
|
|
11
|
+
On This change those areas are outlined, counted ("1 changed", "1 / 3 changed") and stepped through like token
|
|
12
|
+
changes, with Isolate, and the Changes list names them. On Live product the bar says how many wait on This change
|
|
13
|
+
("1 changed on This change"). A change that marks nothing says so.
|
|
14
|
+
|
|
15
|
+
```tsx
|
|
16
|
+
<div role="status" data-bridge-change="Orders waiting to ship alert">30 orders are waiting to ship</div>
|
|
17
|
+
```
|
|
9
18
|
- **Token changes** of the design system: the live tokens swap in without a reload. As soon as the toolbar is open,
|
|
10
19
|
every surface that differs is outlined and counted in the bar ("13 changed", then "2 / 13 changed"). Previous and Next scroll to each one
|
|
11
20
|
in reading order and outline it stronger than the others; Isolate dims the rest of the page (Esc turns it off). The
|
|
@@ -8,8 +8,8 @@ import { jsxs, jsx, Fragment } from "react/jsx-runtime";
|
|
|
8
8
|
import { useState, useEffect, useId, useLayoutEffect, useMemo, useRef, useCallback } from "react";
|
|
9
9
|
import { ThemeProvider, Tooltip, Button, ButtonGroup, IconButton, VisuallyHidden, Kbd, Popover, PopoverTrigger, PopoverContent, Checkbox, Icon, Link, Badge } from "@bridge-ds/react";
|
|
10
10
|
import { ScanSearch, ChevronLeft, ChevronRight, GripVertical, ListChecks, ChevronUp, Check, Info, Minimize2 } from "lucide-react";
|
|
11
|
-
import { g as githubReads, D as DEFAULT_PROXY, l as loadBuild, u as useDocumentScope } from "./index-
|
|
12
|
-
import { t as tokenChanges, c as changedScreens, b as changeMode, d as readableTitle, e as toggleIncluded, r as readChanges, w as whereAmI, f as readReturn, g as readUse, h as shouldRender, O as OPEN_KEY, i as readDock, l as liveTokensUrl, n as noVisibleDifference, j as readScroll, S as SCROLL_PARAM, k as sameScreenOn, m as studioChangesUrl, o as studioChangeUrl, T as TOGETHER_EMPTY_LINE, p as contrastRatio, q as toHex, u as fromText, v as TOGETHER_HINT, x as isSubtle, y as isFlipKey, z as placeToolbar, A as togetherLabel, P as PARAM, B as changeSummary, C as dockAt, D as stepDock, E as DOCK_KEY } from "./session-
|
|
11
|
+
import { g as githubReads, D as DEFAULT_PROXY, l as loadBuild, u as useDocumentScope } from "./index-cRndUN9A.js";
|
|
12
|
+
import { t as tokenChanges, c as changedScreens, b as changeMode, d as readableTitle, M as MARKS_PARAM, e as toggleIncluded, r as readChanges, w as whereAmI, f as readReturn, g as readUse, h as shouldRender, O as OPEN_KEY, i as readDock, l as liveTokensUrl, n as noVisibleDifference, j as readScroll, S as SCROLL_PARAM, k as sameScreenOn, m as studioChangesUrl, o as studioChangeUrl, T as TOGETHER_EMPTY_LINE, p as contrastRatio, q as toHex, u as fromText, v as TOGETHER_HINT, x as isSubtle, y as isFlipKey, z as placeToolbar, A as togetherLabel, P as PARAM, B as changeSummary, C as dockAt, D as stepDock, E as DOCK_KEY } from "./session-Dvma9jtT.js";
|
|
13
13
|
const VISUAL_BRANCH = "bridge-visual";
|
|
14
14
|
const cacheKey = (n) => `bridge-admin:facts:v3:${n}`;
|
|
15
15
|
function session$1() {
|
|
@@ -461,7 +461,7 @@ function tipSide(box2, view, bar, room = TIP_ROOM) {
|
|
|
461
461
|
if (fitsBeside && box2.left >= room.width) return "left";
|
|
462
462
|
return "top";
|
|
463
463
|
}
|
|
464
|
-
const IGNORE = "[data-bridge-toolbar], [data-bridge-overlay]";
|
|
464
|
+
const IGNORE$1 = "[data-bridge-toolbar], [data-bridge-overlay]";
|
|
465
465
|
function useChangedElements(on, live, vars, screen, sheetIs = "before") {
|
|
466
466
|
const [result, setResult] = useState(null);
|
|
467
467
|
const key = vars.join(",");
|
|
@@ -470,12 +470,71 @@ function useChangedElements(on, live, vars, screen, sheetIs = "before") {
|
|
|
470
470
|
setResult(null);
|
|
471
471
|
return;
|
|
472
472
|
}
|
|
473
|
-
const run = () => setResult(changedElements(key.split(","), live, (el) => Boolean(el.closest(IGNORE)), sheetIs));
|
|
473
|
+
const run = () => setResult(changedElements(key.split(","), live, (el) => Boolean(el.closest(IGNORE$1)), sheetIs));
|
|
474
474
|
const ids = [window.setTimeout(run, 0), window.setTimeout(run, 400), window.setTimeout(run, 1200)];
|
|
475
475
|
return () => ids.forEach((id) => window.clearTimeout(id));
|
|
476
476
|
}, [on, live, key, screen, sheetIs]);
|
|
477
477
|
return result;
|
|
478
478
|
}
|
|
479
|
+
const CHANGE_ATTR = "data-bridge-change";
|
|
480
|
+
const MARKS_KEY = "bridge-admin:marks";
|
|
481
|
+
const IGNORE = "[data-bridge-toolbar], [data-bridge-overlay]";
|
|
482
|
+
function markerLabel(value) {
|
|
483
|
+
const v = (value ?? "").replace(/\s+/g, " ").trim();
|
|
484
|
+
return v ? v.charAt(0).toUpperCase() + v.slice(1) : "Changed area";
|
|
485
|
+
}
|
|
486
|
+
function markedElements(root = document) {
|
|
487
|
+
return Array.from(root.querySelectorAll(`[${CHANGE_ATTR}]`)).filter((el) => !el.closest(IGNORE)).map((el) => ({ el, pseudo: null, roots: [], props: [], label: markerLabel(el.getAttribute(CHANGE_ATTR)), keys: [], floating: false }));
|
|
488
|
+
}
|
|
489
|
+
function sameMarks(a, b) {
|
|
490
|
+
return Boolean(a) && a.length === b.length && a.every((x, i) => x.el === b[i].el && x.label === b[i].label);
|
|
491
|
+
}
|
|
492
|
+
const waitingText = (n) => n === null ? "See what changed" : `${n} changed on This change`;
|
|
493
|
+
const NO_MARKS_LINE = "This change does not mark what it changed yet. Compare Live product and This change.";
|
|
494
|
+
function readMarks(search, route, storage) {
|
|
495
|
+
const raw = new URLSearchParams(search).get(MARKS_PARAM);
|
|
496
|
+
if (raw !== null && /^\d{1,4}$/.test(raw)) {
|
|
497
|
+
try {
|
|
498
|
+
storage?.setItem(MARKS_KEY, JSON.stringify({ route, n: Number(raw) }));
|
|
499
|
+
} catch {
|
|
500
|
+
}
|
|
501
|
+
return Number(raw);
|
|
502
|
+
}
|
|
503
|
+
try {
|
|
504
|
+
const kept = JSON.parse(storage?.getItem(MARKS_KEY) ?? "null");
|
|
505
|
+
return kept && kept.route === route && typeof kept.n === "number" ? kept.n : null;
|
|
506
|
+
} catch {
|
|
507
|
+
return null;
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
const OWN = "[data-bridge-toolbar], [data-bridge-overlay]";
|
|
511
|
+
function useMarkedChanges(on, screen) {
|
|
512
|
+
const [marks, setMarks] = useState(null);
|
|
513
|
+
useEffect(() => {
|
|
514
|
+
if (!on) {
|
|
515
|
+
setMarks(null);
|
|
516
|
+
return;
|
|
517
|
+
}
|
|
518
|
+
const run = () => {
|
|
519
|
+
const next = markedElements();
|
|
520
|
+
setMarks((prev) => sameMarks(prev, next) ? prev : next);
|
|
521
|
+
};
|
|
522
|
+
const ids = [window.setTimeout(run, 0), window.setTimeout(run, 400), window.setTimeout(run, 1200)];
|
|
523
|
+
let frame = 0;
|
|
524
|
+
const mo = typeof MutationObserver === "undefined" ? null : new MutationObserver((records) => {
|
|
525
|
+
if (records.every((r) => r.target instanceof Element && r.target.closest(OWN))) return;
|
|
526
|
+
cancelAnimationFrame(frame);
|
|
527
|
+
frame = requestAnimationFrame(run);
|
|
528
|
+
});
|
|
529
|
+
mo?.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: [CHANGE_ATTR] });
|
|
530
|
+
return () => {
|
|
531
|
+
ids.forEach((id) => window.clearTimeout(id));
|
|
532
|
+
cancelAnimationFrame(frame);
|
|
533
|
+
mo?.disconnect();
|
|
534
|
+
};
|
|
535
|
+
}, [on, screen]);
|
|
536
|
+
return marks;
|
|
537
|
+
}
|
|
479
538
|
const PIN_ATTR = "data-bridge-pin";
|
|
480
539
|
const PIN_CLASS = "bridge-pin";
|
|
481
540
|
const STYLE_ATTR = "data-bridge-pinned";
|
|
@@ -1045,6 +1104,8 @@ function Toolbar({
|
|
|
1045
1104
|
const outlines = outlinePick ?? open;
|
|
1046
1105
|
const toggleOutlines = useCallback(() => setOutlinePick((p) => !(p ?? open)), [open]);
|
|
1047
1106
|
const canOutline = facts?.mode === "tokens" && (facts.tokens.length ?? 0) > 0;
|
|
1107
|
+
const isCode = !tg && Boolean(facts) && facts.mode !== "tokens";
|
|
1108
|
+
const canMark = isCode && side === "after";
|
|
1048
1109
|
const live = useLiveSheet(liveUrl, outlines && canOutline, side === "before" && facts?.mode === "tokens");
|
|
1049
1110
|
const onePairs = usePairs(tg ? null : facts, liveUrl, brand2, side === "before");
|
|
1050
1111
|
const pairs = tg ? T?.pairs ?? [] : onePairs;
|
|
@@ -1058,11 +1119,15 @@ function Toolbar({
|
|
|
1058
1119
|
screenKey,
|
|
1059
1120
|
tg ? "after" : "before"
|
|
1060
1121
|
);
|
|
1122
|
+
const marks = useMarkedChanges(canMark, screenKey);
|
|
1123
|
+
const marksOn = outlines && canMark && Boolean(marks?.length);
|
|
1124
|
+
const showing = outlinesOn || marksOn;
|
|
1125
|
+
const found = outlinesOn ? diff?.surfaces ?? null : marksOn ? marks : null;
|
|
1061
1126
|
const nameOf = (v) => facts?.tokens.find((t) => t.cssVar === v)?.name ?? v;
|
|
1062
1127
|
const [shown, setShown] = useState({ count: 0, obstacles: [] });
|
|
1063
1128
|
const setShownStable = useCallback((next) => setShown((p) => JSON.stringify(p) === JSON.stringify(next) ? p : next), []);
|
|
1064
1129
|
const outlineBoxes = useRef([]);
|
|
1065
|
-
outlineBoxes.current =
|
|
1130
|
+
outlineBoxes.current = showing ? shown.obstacles : [];
|
|
1066
1131
|
const [emphasis, setEmphasis] = useState(null);
|
|
1067
1132
|
const [flash, setFlash] = useState(false);
|
|
1068
1133
|
const [sheetOpen, setSheetOpen] = useState(false);
|
|
@@ -1073,14 +1138,14 @@ function Toolbar({
|
|
|
1073
1138
|
const reduced = useMedia("(prefers-reduced-motion: reduce)");
|
|
1074
1139
|
usePinnedBridgeTokens(liveTokensUrl(build), theme);
|
|
1075
1140
|
useEffect(() => {
|
|
1076
|
-
if (!
|
|
1141
|
+
if (!showing || reduced) {
|
|
1077
1142
|
setFlash(false);
|
|
1078
1143
|
return;
|
|
1079
1144
|
}
|
|
1080
1145
|
setFlash(true);
|
|
1081
1146
|
const id = window.setTimeout(() => setFlash(false), 1500);
|
|
1082
1147
|
return () => window.clearTimeout(id);
|
|
1083
|
-
}, [
|
|
1148
|
+
}, [showing, reduced]);
|
|
1084
1149
|
useEffect(() => {
|
|
1085
1150
|
if (!sheetOpen) setEmphasis(null);
|
|
1086
1151
|
}, [sheetOpen]);
|
|
@@ -1096,6 +1161,13 @@ function Toolbar({
|
|
|
1096
1161
|
useEffect(() => {
|
|
1097
1162
|
if (shownIn && theme !== shownIn) setShownIn(null);
|
|
1098
1163
|
}, [theme, shownIn]);
|
|
1164
|
+
const waiting = useMemo(() => isCode && side === "before" ? readMarks(window.location.search, hash, session()) : null, [isCode, side, hash]);
|
|
1165
|
+
useEffect(() => {
|
|
1166
|
+
if (!new URLSearchParams(window.location.search).has(MARKS_PARAM)) return;
|
|
1167
|
+
const url = new URL(window.location.href);
|
|
1168
|
+
url.searchParams.delete(MARKS_PARAM);
|
|
1169
|
+
window.history.replaceState(window.history.state, "", url);
|
|
1170
|
+
}, []);
|
|
1099
1171
|
useEffect(() => {
|
|
1100
1172
|
const y = readScroll(window.location.search);
|
|
1101
1173
|
if (y === null) return;
|
|
@@ -1121,16 +1193,16 @@ function Toolbar({
|
|
|
1121
1193
|
}
|
|
1122
1194
|
const here2 = { search: window.location.search, hash: window.location.hash };
|
|
1123
1195
|
if (next === "before" && build.production) {
|
|
1124
|
-
window.location.assign(sameScreenOn(build.production, here2, { change, returnTo: window.location.origin, scroll: window.scrollY }));
|
|
1196
|
+
window.location.assign(sameScreenOn(build.production, here2, { change, returnTo: window.location.origin, scroll: window.scrollY, marks: marks?.length ?? null }));
|
|
1125
1197
|
} else if (next === "after" && returnTo) {
|
|
1126
1198
|
window.location.assign(sameScreenOn(returnTo, here2, { change, scroll: window.scrollY }));
|
|
1127
1199
|
}
|
|
1128
1200
|
},
|
|
1129
|
-
[side, facts, build, change, returnTo]
|
|
1201
|
+
[side, facts, build, change, returnTo, marks]
|
|
1130
1202
|
);
|
|
1131
1203
|
useEffect(() => {
|
|
1132
1204
|
const onKey = (e) => {
|
|
1133
|
-
if (canOutline && !noDiff && isKey(e, "c")) {
|
|
1205
|
+
if ((canOutline && !noDiff || canMark && marks?.length) && isKey(e, "c")) {
|
|
1134
1206
|
e.preventDefault();
|
|
1135
1207
|
toggleOutlines();
|
|
1136
1208
|
return;
|
|
@@ -1141,7 +1213,7 @@ function Toolbar({
|
|
|
1141
1213
|
};
|
|
1142
1214
|
window.addEventListener("keydown", onKey);
|
|
1143
1215
|
return () => window.removeEventListener("keydown", onKey);
|
|
1144
|
-
}, [choose, side, canOutline, noDiff, toggleOutlines]);
|
|
1216
|
+
}, [choose, side, canOutline, canMark, marks, noDiff, toggleOutlines]);
|
|
1145
1217
|
useEffect(() => {
|
|
1146
1218
|
if (!isolate) return;
|
|
1147
1219
|
const onEscape = (e) => {
|
|
@@ -1183,7 +1255,7 @@ function Toolbar({
|
|
|
1183
1255
|
window.removeEventListener("hashchange", measure);
|
|
1184
1256
|
document.body.style.paddingBottom = "";
|
|
1185
1257
|
};
|
|
1186
|
-
}, [dock, open, facts, shown,
|
|
1258
|
+
}, [dock, open, facts, shown, showing]);
|
|
1187
1259
|
const toggleOpen = (next) => {
|
|
1188
1260
|
setOpen(next);
|
|
1189
1261
|
remember(OPEN_KEY, next ? "1" : "0");
|
|
@@ -1236,8 +1308,8 @@ function Toolbar({
|
|
|
1236
1308
|
const behind = facts?.behind ? "Live has new changes since this change started." : null;
|
|
1237
1309
|
const shared = screens?.length && screens.every((s) => s.tenant === screens[0].tenant && s.theme === screens[0].theme) ? screens[0] : null;
|
|
1238
1310
|
const shopOf = (t) => shops.find((x) => x.id === t)?.name ?? t;
|
|
1239
|
-
const surfaces = useMemo(() =>
|
|
1240
|
-
const shownCount =
|
|
1311
|
+
const surfaces = useMemo(() => found ?? [], [found]);
|
|
1312
|
+
const shownCount = showing && found ? shown.count : null;
|
|
1241
1313
|
const order = useMemo(() => {
|
|
1242
1314
|
const on = surfaces.map((s, i) => ({ s, i })).filter(({ s }) => rendered(s.el));
|
|
1243
1315
|
const places = on.map(({ s }) => {
|
|
@@ -1247,12 +1319,12 @@ function Toolbar({
|
|
|
1247
1319
|
});
|
|
1248
1320
|
return readingOrder(places).map((k) => on[k].i);
|
|
1249
1321
|
}, [surfaces]);
|
|
1250
|
-
const total =
|
|
1322
|
+
const total = showing && found ? order.length : null;
|
|
1251
1323
|
const current = position !== null ? order[position] ?? null : null;
|
|
1252
1324
|
useEffect(() => {
|
|
1253
1325
|
setPosition(null);
|
|
1254
1326
|
setAnnounce("");
|
|
1255
|
-
}, [screenKey,
|
|
1327
|
+
}, [screenKey, showing]);
|
|
1256
1328
|
useEffect(() => {
|
|
1257
1329
|
if (position !== null && position >= order.length) setPosition(null);
|
|
1258
1330
|
}, [order.length, position]);
|
|
@@ -1281,7 +1353,7 @@ function Toolbar({
|
|
|
1281
1353
|
] }) : noDiff ? /* @__PURE__ */ jsxs("p", { className: styles.note, role: "status", children: [
|
|
1282
1354
|
/* @__PURE__ */ jsx("span", { children: noDifferenceText(noDiff, shops) }),
|
|
1283
1355
|
/* @__PURE__ */ jsx(Button, { variant: "ghost", size: "md", onClick: fixNoDiff, className: styles.noteAction, children: noDiff.kind === "theme" ? `Switch to ${noDiff.touched}` : `Switch to ${brandName(shops, noDiff.touched)}` })
|
|
1284
|
-
] }) : (outlinesOn || side === "before") && live.state === "error" ? /* @__PURE__ */ jsx("p", { className: styles.note, role: "status", children: "Could not load the live product. Check your connection, then try again." }) : total === 0 ? tg ? /* @__PURE__ */ jsx("p", { className: styles.note, role: "status", children: TOGETHER_EMPTY_LINE }) : elsewhere.length ? /* @__PURE__ */ jsxs("p", { className: styles.note, role: "status", children: [
|
|
1356
|
+
] }) : open && canMark && marks?.length === 0 ? /* @__PURE__ */ jsx("p", { className: styles.note, role: "status", children: NO_MARKS_LINE }) : (outlinesOn || side === "before") && live.state === "error" ? /* @__PURE__ */ jsx("p", { className: styles.note, role: "status", children: "Could not load the live product. Check your connection, then try again." }) : total === 0 ? tg ? /* @__PURE__ */ jsx("p", { className: styles.note, role: "status", children: TOGETHER_EMPTY_LINE }) : elsewhere.length ? /* @__PURE__ */ jsxs("p", { className: styles.note, role: "status", children: [
|
|
1285
1357
|
/* @__PURE__ */ jsx("span", { children: elsewhereLine(elsewhere.map((sc) => sc.label)) }),
|
|
1286
1358
|
/* @__PURE__ */ jsxs(Button, { variant: "ghost", size: "md", render: /* @__PURE__ */ jsx("a", { href: screenHref(elsewhere[0]) }), onClick: goTo(elsewhere[0]), className: styles.noteAction, children: [
|
|
1287
1359
|
"Go to ",
|
|
@@ -1314,16 +1386,17 @@ function Toolbar({
|
|
|
1314
1386
|
const subtleOf = (before, after) => isSubtle(before, after) ? /* @__PURE__ */ jsx("span", { className: styles.subtle, children: "Subtle change" }) : null;
|
|
1315
1387
|
const roleGroups = [...visiblePairs.reduce((m, p) => m.set(p.token.name, [...m.get(p.token.name) ?? [], p]), /* @__PURE__ */ new Map())].map(([name2, list2]) => ({ name: name2, pairs: list2 }));
|
|
1316
1388
|
const tokenNames = (facts?.tokens ?? []).map((t) => t.name);
|
|
1317
|
-
const
|
|
1318
|
-
const
|
|
1319
|
-
const
|
|
1320
|
-
const
|
|
1389
|
+
const markNames = (marks ?? []).map((m) => m.label);
|
|
1390
|
+
const summary = shownCount === null ? null : marksOn ? `Marked by this change: ${markNames.slice(0, 3).join(", ")}${markNames.length > 3 ? ` and ${markNames.length - 3} more` : ""}` : surfaceLine(diff.surfaces.flatMap((s) => s.roots.map(nameOf)), total ?? shownCount);
|
|
1391
|
+
const countText = !showing ? "Show what changed" : total === null ? "Finding changes" : total === 0 ? "Nothing changed here" : position !== null ? positionLabel(position, total) : changeCount(total);
|
|
1392
|
+
const toggleTip = showing ? `${summary ? `${summary}. ` : ""}Press C to hide the outlines.` : `Outline what ${tokenNames.length === 1 ? tokenNames[0] : "this change"} changes on this screen. Press C.`;
|
|
1393
|
+
const nav2 = canOutline || canMark && marks?.length ? /* @__PURE__ */ jsx(
|
|
1321
1394
|
ChangeNav,
|
|
1322
1395
|
{
|
|
1323
1396
|
countText,
|
|
1324
1397
|
tip: toggleTip,
|
|
1325
|
-
outlinesOn,
|
|
1326
|
-
disabled: Boolean(noDiff),
|
|
1398
|
+
outlinesOn: showing,
|
|
1399
|
+
disabled: canOutline && Boolean(noDiff),
|
|
1327
1400
|
total,
|
|
1328
1401
|
isolate: isolateOn,
|
|
1329
1402
|
announce,
|
|
@@ -1331,6 +1404,15 @@ function Toolbar({
|
|
|
1331
1404
|
onStep: step,
|
|
1332
1405
|
onIsolate: setIsolate
|
|
1333
1406
|
}
|
|
1407
|
+
) : isCode && side === "before" && waiting !== 0 ? (
|
|
1408
|
+
// Live product: the marked areas are on This change. The count when the switch carried it, else where to look.
|
|
1409
|
+
/* @__PURE__ */ jsx("div", { className: styles.nav, children: /* @__PURE__ */ jsx(Tooltip, { className: PIN_CLASS, content: /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1410
|
+
"Go to This change to see ",
|
|
1411
|
+
waiting === 1 ? "it" : "them",
|
|
1412
|
+
" outlined. ",
|
|
1413
|
+
/* @__PURE__ */ jsx(Kbd, { keys: "B", size: "sm" }),
|
|
1414
|
+
" flips sides."
|
|
1415
|
+
] }), children: /* @__PURE__ */ jsx(Button, { variant: "secondary", size: "md", iconStart: ScanSearch, disabled: !canFlip, onClick: () => choose("after"), className: styles.countButton, children: waitingText(waiting) }) }) })
|
|
1334
1416
|
) : null;
|
|
1335
1417
|
const shownSurfaces = surfaces.map((s, i) => ({ s, i })).filter(({ s }) => shownRect(s.el));
|
|
1336
1418
|
const focusSurface = (i) => {
|
|
@@ -1341,6 +1423,15 @@ function Toolbar({
|
|
|
1341
1423
|
if (order.includes(i)) setPosition(order.indexOf(i));
|
|
1342
1424
|
};
|
|
1343
1425
|
const tokensOf = (x) => [...new Set(x.roots.map(nameOf))].join(", ");
|
|
1426
|
+
const focusMark = (i) => {
|
|
1427
|
+
const el = marks?.[i]?.el;
|
|
1428
|
+
if (!el) return;
|
|
1429
|
+
if (!marksOn) setOutlinePick(true);
|
|
1430
|
+
if (!isPage(el)) el.scrollIntoView({ block: "center", behavior: reduced ? "auto" : "smooth" });
|
|
1431
|
+
setEmphasis(i);
|
|
1432
|
+
if (order.includes(i)) setPosition(order.indexOf(i));
|
|
1433
|
+
};
|
|
1434
|
+
const footLine = tg ? facts ? "Screens are measured per change, not for this mix. Show what changed outlines this screen." : "Reading the changes." : !facts ? "Reading the change." : isCode ? side === "before" ? "What this change adds or changes is outlined on This change." : marks?.length ? null : NO_MARKS_LINE : "The screens this change affects are not measured yet.";
|
|
1344
1435
|
const sides2 = /* @__PURE__ */ jsx(ButtonGroup, { appearance: "attached", "aria-label": "Compare", className: styles.sides, children: ["before", "after"].map((s) => /* @__PURE__ */ jsx(
|
|
1345
1436
|
Tooltip,
|
|
1346
1437
|
{
|
|
@@ -1381,7 +1472,7 @@ function Toolbar({
|
|
|
1381
1472
|
"data-dock": place.dock,
|
|
1382
1473
|
style: place.lift ? { paddingBottom: `${place.lift}px` } : void 0,
|
|
1383
1474
|
children: [
|
|
1384
|
-
|
|
1475
|
+
showing && surfaces.length ? /* @__PURE__ */ jsx(
|
|
1385
1476
|
ChangeOutlines,
|
|
1386
1477
|
{
|
|
1387
1478
|
surfaces,
|
|
@@ -1392,6 +1483,12 @@ function Toolbar({
|
|
|
1392
1483
|
bar: () => root.current?.getBoundingClientRect() ?? null,
|
|
1393
1484
|
onShown: setShownStable,
|
|
1394
1485
|
tip: (s) => {
|
|
1486
|
+
if (marksOn) {
|
|
1487
|
+
return /* @__PURE__ */ jsx("span", { className: styles.tip, children: /* @__PURE__ */ jsxs("span", { className: styles.tipText, children: [
|
|
1488
|
+
/* @__PURE__ */ jsx("span", { children: s.label }),
|
|
1489
|
+
/* @__PURE__ */ jsx("span", { className: styles.tipStep, children: "New or changed in this change" })
|
|
1490
|
+
] }) });
|
|
1491
|
+
}
|
|
1395
1492
|
const prop = s.props.find((p) => /^rgb/.test(p.before) && /^rgb/.test(p.after));
|
|
1396
1493
|
const token = prop ? visiblePairs.find((p) => p.color && toHex(p.after) === toHex(prop.after) && toHex(p.before) === toHex(prop.before)) : null;
|
|
1397
1494
|
const name2 = token?.token.name ?? [...new Set(s.roots.map(nameOf))].slice(0, 2).join(", ");
|
|
@@ -1423,6 +1520,7 @@ function Toolbar({
|
|
|
1423
1520
|
"aria-label": `Bridge: ${label}, ${title2}`,
|
|
1424
1521
|
"data-side": side,
|
|
1425
1522
|
"data-diff-ms": outlinesOn ? diff?.ms : void 0,
|
|
1523
|
+
"data-marks": canMark ? marks?.length ?? void 0 : void 0,
|
|
1426
1524
|
"data-diff-count": shownCount ?? void 0,
|
|
1427
1525
|
"data-diff-total": total ?? void 0,
|
|
1428
1526
|
"data-diff-elements": outlinesOn ? diff?.elements.length : void 0,
|
|
@@ -1490,6 +1588,28 @@ function Toolbar({
|
|
|
1490
1588
|
"."
|
|
1491
1589
|
] }) : null
|
|
1492
1590
|
] }) : null,
|
|
1591
|
+
canMark && marks?.length ? /* @__PURE__ */ jsxs("section", { className: styles.sheetSection, "aria-label": `Changed here, ${marks.length}`, children: [
|
|
1592
|
+
/* @__PURE__ */ jsxs("p", { className: styles.sectionTitle, children: [
|
|
1593
|
+
"Changed here · ",
|
|
1594
|
+
marks.length
|
|
1595
|
+
] }),
|
|
1596
|
+
/* @__PURE__ */ jsx("ul", { className: styles.rows, children: marks.map((m, i) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(
|
|
1597
|
+
Button,
|
|
1598
|
+
{
|
|
1599
|
+
variant: "ghost",
|
|
1600
|
+
size: "md",
|
|
1601
|
+
fullWidth: true,
|
|
1602
|
+
className: styles.row,
|
|
1603
|
+
"data-emphasis": marksOn && emphasis === i || void 0,
|
|
1604
|
+
onMouseEnter: () => marksOn && setEmphasis(i),
|
|
1605
|
+
onMouseLeave: () => setEmphasis((e) => e === i ? null : e),
|
|
1606
|
+
onFocus: () => marksOn && setEmphasis(i),
|
|
1607
|
+
onBlur: () => setEmphasis((e) => e === i ? null : e),
|
|
1608
|
+
onClick: () => focusMark(i),
|
|
1609
|
+
children: /* @__PURE__ */ jsx("span", { className: styles.rowText, children: /* @__PURE__ */ jsx("span", { className: styles.rowName, children: m.label }) })
|
|
1610
|
+
}
|
|
1611
|
+
) }, i)) })
|
|
1612
|
+
] }) : null,
|
|
1493
1613
|
outlinesOn && shownSurfaces.length ? /* @__PURE__ */ jsxs("section", { className: styles.sheetSection, "aria-label": `Changed here, ${shownSurfaces.length}`, children: [
|
|
1494
1614
|
/* @__PURE__ */ jsxs("p", { className: styles.sectionTitle, children: [
|
|
1495
1615
|
"Changed here · ",
|
|
@@ -1570,7 +1690,7 @@ function Toolbar({
|
|
|
1570
1690
|
behind
|
|
1571
1691
|
] }) : null,
|
|
1572
1692
|
/* @__PURE__ */ jsx("div", { className: styles.sheetPhone, children: /* @__PURE__ */ jsx(Link, { variant: "standalone", href: studio2, className: styles.back, children: "Back to Studio" }) }),
|
|
1573
|
-
screens === null ? /* @__PURE__ */ jsx("p", { className: `${styles.note} ${styles.sheetFoot}`, children:
|
|
1693
|
+
screens === null ? footLine ? /* @__PURE__ */ jsx("p", { className: `${styles.note} ${styles.sheetFoot}`, children: footLine }) : null : screens.length === 0 ? /* @__PURE__ */ jsx("p", { className: `${styles.note} ${styles.sheetFoot}`, children: "No admin screen changes. Component examples may still change: Studio lists them." }) : null
|
|
1574
1694
|
] })
|
|
1575
1695
|
] }),
|
|
1576
1696
|
/* @__PURE__ */ jsx(Button, { variant: "ghost", size: "md", render: /* @__PURE__ */ jsx("a", { href: studio2 }), className: styles.studio, children: "Back to Studio" })
|
|
@@ -1615,4 +1735,4 @@ function useHash() {
|
|
|
1615
1735
|
export {
|
|
1616
1736
|
ToolbarRoot as default
|
|
1617
1737
|
};
|
|
1618
|
-
//# sourceMappingURL=Toolbar-
|
|
1738
|
+
//# sourceMappingURL=Toolbar-ByLHemKF.js.map
|