@ai-matrx/canvas 0.5.3 → 0.6.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/CHANGELOG.md +27 -0
- package/README.md +6 -0
- package/dist/index.cjs +45 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +45 -9
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +247 -59
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +1 -1
- package/dist/react.d.ts +1 -1
- package/dist/react.js +251 -62
- package/dist/react.js.map +1 -1
- package/dist/styles.css +66 -27
- package/dist/{toggleKind-BD78LnMB.d.cts → toggleKind-DhDmWExm.d.cts} +27 -1
- package/dist/{toggleKind-BD78LnMB.d.ts → toggleKind-DhDmWExm.d.ts} +27 -1
- package/package.json +1 -1
package/dist/react.cjs
CHANGED
|
@@ -78,6 +78,7 @@ var import_react2 = require("react");
|
|
|
78
78
|
var CANVAS_MAIN_WINDOW = "main";
|
|
79
79
|
var CANVAS_LAUNCHER_KIND = "canvas.launcher";
|
|
80
80
|
var CANVAS_HISTORY_LIMIT = 50;
|
|
81
|
+
var CANVAS_KEEP_ALIVE_DEPTH = 5;
|
|
81
82
|
var CANVAS_MIN_WIDTH = 360;
|
|
82
83
|
var CANVAS_DEFAULT_WIDTH = 640;
|
|
83
84
|
var CANVAS_MIN_SPLIT_FRACTION = 0.12;
|
|
@@ -436,8 +437,10 @@ function sendHome(state, itemId, home, activate) {
|
|
|
436
437
|
next = insertInto(next, homeFrame.focusedPaneId, itemId, activate);
|
|
437
438
|
return activate ? withFrame(next, target, { focusedPaneId: homeFrame.focusedPaneId }) : next;
|
|
438
439
|
}
|
|
439
|
-
function newItem(kind, key, title, data, now,
|
|
440
|
+
function newItem(kind, key, title, data, now, steps) {
|
|
440
441
|
const id = canvasItemId(kind, key);
|
|
442
|
+
const history = steps?.history ?? [];
|
|
443
|
+
const kept = steps?.kept ?? [];
|
|
441
444
|
return {
|
|
442
445
|
id,
|
|
443
446
|
kind,
|
|
@@ -446,12 +449,14 @@ function newItem(kind, key, title, data, now, history) {
|
|
|
446
449
|
data,
|
|
447
450
|
openedAt: now,
|
|
448
451
|
updatedAt: now,
|
|
449
|
-
instance
|
|
450
|
-
|
|
452
|
+
// A reused instance is the SAME live body coming back (Back, or returning to a kept step).
|
|
453
|
+
instance: steps?.instance ?? `${now.toString(36)}:${id}`,
|
|
454
|
+
...history.length > 0 ? { history: history.slice(-CANVAS_HISTORY_LIMIT) } : {},
|
|
455
|
+
...kept.length > 0 ? { kept: kept.slice(-CANVAS_KEEP_ALIVE_DEPTH) } : {}
|
|
451
456
|
};
|
|
452
457
|
}
|
|
453
458
|
function historyEntry(item) {
|
|
454
|
-
return { kind: item.kind, key: item.key, title: item.title, data: item.data };
|
|
459
|
+
return { kind: item.kind, key: item.key, title: item.title, data: item.data, ...item.instance ? { instance: item.instance } : {} };
|
|
455
460
|
}
|
|
456
461
|
function replaceInPlace(state, current, next) {
|
|
457
462
|
const pane = paneOf(state, current.id);
|
|
@@ -480,17 +485,25 @@ function sanitizeHistory(raw) {
|
|
|
480
485
|
if (!entry || typeof entry !== "object") continue;
|
|
481
486
|
const e = entry;
|
|
482
487
|
if (typeof e.kind !== "string" || typeof e.key !== "string") continue;
|
|
483
|
-
out.push({
|
|
488
|
+
out.push({
|
|
489
|
+
kind: e.kind,
|
|
490
|
+
key: e.key,
|
|
491
|
+
title: typeof e.title === "string" ? e.title : null,
|
|
492
|
+
data: e.data ?? null,
|
|
493
|
+
...typeof e.instance === "string" && e.instance ? { instance: e.instance } : {}
|
|
494
|
+
});
|
|
484
495
|
}
|
|
485
496
|
return out.slice(-CANVAS_HISTORY_LIMIT);
|
|
486
497
|
}
|
|
487
498
|
function sanitizeItem(item) {
|
|
488
499
|
const history = sanitizeHistory(item.history);
|
|
489
|
-
const
|
|
500
|
+
const kept = sanitizeHistory(item.kept).slice(-CANVAS_KEEP_ALIVE_DEPTH);
|
|
501
|
+
const { history: _history, kept: _kept, instance, ...rest } = item;
|
|
490
502
|
return {
|
|
491
503
|
...rest,
|
|
492
504
|
...typeof instance === "string" && instance ? { instance } : {},
|
|
493
|
-
...history.length > 0 ? { history } : {}
|
|
505
|
+
...history.length > 0 ? { history } : {},
|
|
506
|
+
...kept.length > 0 ? { kept } : {}
|
|
494
507
|
};
|
|
495
508
|
}
|
|
496
509
|
function clampWidth(width) {
|
|
@@ -677,7 +690,22 @@ function canvasReducer(state = createInitialCanvasState(), action) {
|
|
|
677
690
|
return current.kind === CANVAS_LAUNCHER_KIND ? canvasReducer(focused, canvasActions.closeItem(itemId)) : focused;
|
|
678
691
|
}
|
|
679
692
|
const history = [...current.history ?? [], historyEntry(current)];
|
|
680
|
-
|
|
693
|
+
const keptAll = current.kept ?? [];
|
|
694
|
+
const keptIndex = keptAll.findIndex((entry) => canvasItemId(entry.kind, entry.key) === targetId);
|
|
695
|
+
const revived = keptIndex >= 0 ? keptAll[keptIndex] : void 0;
|
|
696
|
+
const kept = keptAll.filter((_, i) => i !== keptIndex);
|
|
697
|
+
return replaceInPlace(
|
|
698
|
+
state,
|
|
699
|
+
current,
|
|
700
|
+
newItem(
|
|
701
|
+
to.kind,
|
|
702
|
+
to.key,
|
|
703
|
+
to.title !== void 0 ? to.title : revived?.title ?? null,
|
|
704
|
+
to.data !== void 0 ? to.data : revived?.data ?? null,
|
|
705
|
+
now,
|
|
706
|
+
{ history, kept, instance: revived?.instance }
|
|
707
|
+
)
|
|
708
|
+
);
|
|
681
709
|
}
|
|
682
710
|
case `${P}back`: {
|
|
683
711
|
const { itemId, now } = action.payload;
|
|
@@ -690,7 +718,12 @@ function canvasReducer(state = createInitialCanvasState(), action) {
|
|
|
690
718
|
if (state.items[targetId]) {
|
|
691
719
|
return focusExisting(canvasReducer(state, canvasActions.closeItem(itemId)), targetId);
|
|
692
720
|
}
|
|
693
|
-
|
|
721
|
+
const kept = [...(current.kept ?? []).filter((k) => canvasItemId(k.kind, k.key) !== itemId), historyEntry(current)];
|
|
722
|
+
return replaceInPlace(
|
|
723
|
+
state,
|
|
724
|
+
current,
|
|
725
|
+
newItem(entry.kind, entry.key, entry.title, entry.data, now, { history: history.slice(0, -1), kept, instance: entry.instance })
|
|
726
|
+
);
|
|
694
727
|
}
|
|
695
728
|
case `${P}closeItem`: {
|
|
696
729
|
const { itemId } = action.payload;
|
|
@@ -1425,6 +1458,7 @@ var NO_HISTORY = Object.freeze([]);
|
|
|
1425
1458
|
var selectCanvasCanGoBack = (s, itemId) => (s.items[itemId]?.history?.length ?? 0) > 0;
|
|
1426
1459
|
|
|
1427
1460
|
// src/core/presentation.ts
|
|
1461
|
+
var CANVAS_PHONE_MAX_WIDTH = 767;
|
|
1428
1462
|
var CANVAS_NARROW_WIDTH = 480;
|
|
1429
1463
|
var SQUARE_BAND = 1.2;
|
|
1430
1464
|
function canvasOrientation(width, height) {
|
|
@@ -1673,8 +1707,7 @@ function createLauncherEntryStore() {
|
|
|
1673
1707
|
}
|
|
1674
1708
|
};
|
|
1675
1709
|
}
|
|
1676
|
-
var
|
|
1677
|
-
var isPhoneViewport = () => typeof window !== "undefined" && window.innerWidth <= PHONE_MAX_WIDTH;
|
|
1710
|
+
var isPhoneViewport = () => typeof window !== "undefined" && window.innerWidth <= CANVAS_PHONE_MAX_WIDTH;
|
|
1678
1711
|
var isMacPlatform = () => typeof navigator !== "undefined" && /mac|iphone|ipad/i.test(navigator.userAgentData?.platform ?? navigator.platform ?? "");
|
|
1679
1712
|
function escapeBelongsElsewhere(event) {
|
|
1680
1713
|
if (event.defaultPrevented) return true;
|
|
@@ -1977,9 +2010,26 @@ var LayoutGridIcon = (p) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Glyph,
|
|
|
1977
2010
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("rect", { width: "7", height: "7", x: "14", y: "14", rx: "1" }),
|
|
1978
2011
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("rect", { width: "7", height: "7", x: "3", y: "14", rx: "1" })
|
|
1979
2012
|
] });
|
|
2013
|
+
var ChevronLeftIcon = (p) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Glyph, { ...p, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "m15 18-6-6 6-6" }) });
|
|
2014
|
+
var ChevronRightIcon = (p) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Glyph, { ...p, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "m9 18 6-6-6-6" }) });
|
|
1980
2015
|
|
|
1981
2016
|
// src/react/chrome.tsx
|
|
1982
2017
|
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
2018
|
+
var useIsoLayoutEffect = typeof window === "undefined" ? import_react3.useEffect : import_react3.useLayoutEffect;
|
|
2019
|
+
function useTruncated(title) {
|
|
2020
|
+
const ref = (0, import_react3.useRef)(null);
|
|
2021
|
+
const [truncated, setTruncated] = (0, import_react3.useState)(false);
|
|
2022
|
+
useIsoLayoutEffect(() => {
|
|
2023
|
+
const el = ref.current;
|
|
2024
|
+
if (!el) return void 0;
|
|
2025
|
+
const check = () => setTruncated(el.scrollWidth - el.clientWidth > 1);
|
|
2026
|
+
check();
|
|
2027
|
+
const observer = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(check);
|
|
2028
|
+
observer?.observe(el);
|
|
2029
|
+
return () => observer?.disconnect();
|
|
2030
|
+
}, [title]);
|
|
2031
|
+
return { ref, truncated };
|
|
2032
|
+
}
|
|
1983
2033
|
var cx = (...names) => names.filter(Boolean).join(" ");
|
|
1984
2034
|
function useTooltip(text) {
|
|
1985
2035
|
const internals = useOptionalCanvasInternals();
|
|
@@ -2119,6 +2169,7 @@ function CanvasPanelEmpty({ children, className }) {
|
|
|
2119
2169
|
}
|
|
2120
2170
|
var CanvasTab = (0, import_react3.forwardRef)(function CanvasTab2({ title, icon, note, active, onSelect, onClose, className, onKeyDown, onClick, ...rest }, ref) {
|
|
2121
2171
|
const shown = title || "New tab";
|
|
2172
|
+
const name = useTruncated(shown);
|
|
2122
2173
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
2123
2174
|
"div",
|
|
2124
2175
|
{
|
|
@@ -2128,6 +2179,7 @@ var CanvasTab = (0, import_react3.forwardRef)(function CanvasTab2({ title, icon,
|
|
|
2128
2179
|
tabIndex: active ? 0 : -1,
|
|
2129
2180
|
"data-slot": "browser-tab",
|
|
2130
2181
|
"data-active": active ? "" : void 0,
|
|
2182
|
+
"data-truncated": name.truncated ? "" : void 0,
|
|
2131
2183
|
title: shown,
|
|
2132
2184
|
className: cx("mxc-tab", className),
|
|
2133
2185
|
...rest,
|
|
@@ -2145,7 +2197,7 @@ var CanvasTab = (0, import_react3.forwardRef)(function CanvasTab2({ title, icon,
|
|
|
2145
2197
|
},
|
|
2146
2198
|
children: [
|
|
2147
2199
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mxc-tab-icon", children: icon }),
|
|
2148
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mxc-tab-title", children: shown }),
|
|
2200
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { ref: name.ref, className: "mxc-tab-title", children: shown }),
|
|
2149
2201
|
note ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mxc-tab-note", "data-slot": "browser-tab-note", children: note }) : null,
|
|
2150
2202
|
onClose ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
2151
2203
|
"button",
|
|
@@ -2312,6 +2364,21 @@ function useChoices() {
|
|
|
2312
2364
|
}
|
|
2313
2365
|
return { contextual, global };
|
|
2314
2366
|
}
|
|
2367
|
+
var FOLLOW_UP_MS = 600;
|
|
2368
|
+
function swallowFollowUpClicks() {
|
|
2369
|
+
if (typeof window === "undefined") return;
|
|
2370
|
+
const types = ["pointerdown", "mousedown", "pointerup", "mouseup", "click", "dblclick"];
|
|
2371
|
+
const swallow = (event) => {
|
|
2372
|
+
if (event.detail >= 2 || event.type === "dblclick") {
|
|
2373
|
+
event.preventDefault();
|
|
2374
|
+
event.stopPropagation();
|
|
2375
|
+
}
|
|
2376
|
+
};
|
|
2377
|
+
for (const type of types) window.addEventListener(type, swallow, true);
|
|
2378
|
+
setTimeout(() => {
|
|
2379
|
+
for (const type of types) window.removeEventListener(type, swallow, true);
|
|
2380
|
+
}, FOLLOW_UP_MS);
|
|
2381
|
+
}
|
|
2315
2382
|
function LauncherGrid({ onChoose }) {
|
|
2316
2383
|
const { contextual, global } = useChoices();
|
|
2317
2384
|
if (contextual.length === 0 && global.length === 0) return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(CanvasPanelEmpty, { children: "Nothing to open" });
|
|
@@ -2319,10 +2386,23 @@ function LauncherGrid({ onChoose }) {
|
|
|
2319
2386
|
label ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("h3", { className: "mxc-launcher-heading", children: label }) : null,
|
|
2320
2387
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "mxc-launcher-grid", children: choices.map((choice) => {
|
|
2321
2388
|
const Icon = choice.icon;
|
|
2322
|
-
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2389
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
2390
|
+
"button",
|
|
2391
|
+
{
|
|
2392
|
+
type: "button",
|
|
2393
|
+
className: "mxc-launcher-item",
|
|
2394
|
+
onClick: (event) => {
|
|
2395
|
+
if (event.detail >= 2) return;
|
|
2396
|
+
swallowFollowUpClicks();
|
|
2397
|
+
onChoose(choice.input);
|
|
2398
|
+
},
|
|
2399
|
+
children: [
|
|
2400
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Icon, { className: "mxc-launcher-icon" }),
|
|
2401
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: choice.label })
|
|
2402
|
+
]
|
|
2403
|
+
},
|
|
2404
|
+
choice.id
|
|
2405
|
+
);
|
|
2326
2406
|
}) })
|
|
2327
2407
|
] });
|
|
2328
2408
|
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "mxc-launcher", children: [
|
|
@@ -2435,6 +2515,10 @@ var CanvasSlotsContext = (0, import_react6.createContext)(null);
|
|
|
2435
2515
|
function useCanvasSlots() {
|
|
2436
2516
|
return (0, import_react6.useContext)(CanvasSlotsContext);
|
|
2437
2517
|
}
|
|
2518
|
+
var CanvasSinglePaneContext = (0, import_react6.createContext)(false);
|
|
2519
|
+
function useCanvasSinglePane() {
|
|
2520
|
+
return (0, import_react6.useContext)(CanvasSinglePaneContext);
|
|
2521
|
+
}
|
|
2438
2522
|
function useSlotSize(slots, paneId) {
|
|
2439
2523
|
return (0, import_react6.useSyncExternalStore)(
|
|
2440
2524
|
slots.subscribe,
|
|
@@ -2445,7 +2529,7 @@ function useSlotSize(slots, paneId) {
|
|
|
2445
2529
|
|
|
2446
2530
|
// src/react/bodies.tsx
|
|
2447
2531
|
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
2448
|
-
var
|
|
2532
|
+
var useIsoLayoutEffect2 = typeof window === "undefined" ? import_react7.useEffect : import_react7.useLayoutEffect;
|
|
2449
2533
|
var LAZY = /* @__PURE__ */ Symbol.for("ai-matrx.canvas.lazy");
|
|
2450
2534
|
function kindComponent(kind) {
|
|
2451
2535
|
if (kind.component) return kind.component;
|
|
@@ -2466,19 +2550,36 @@ function usePanePresentation(slots, paneId, isFullscreen, paneCount) {
|
|
|
2466
2550
|
var hostKey = (item) => item.instance ?? item.id;
|
|
2467
2551
|
var SEP2 = "";
|
|
2468
2552
|
var ROW = "";
|
|
2553
|
+
function bornAt(instance, fallback) {
|
|
2554
|
+
const stamp = instance ? Number.parseInt(instance.slice(0, instance.indexOf(":")), 36) : Number.NaN;
|
|
2555
|
+
return Number.isFinite(stamp) ? stamp : fallback;
|
|
2556
|
+
}
|
|
2557
|
+
function keptCanvasSteps(item) {
|
|
2558
|
+
const back = (item.history ?? []).slice(-CANVAS_KEEP_ALIVE_DEPTH);
|
|
2559
|
+
const forward = (item.kept ?? []).slice(-CANVAS_KEEP_ALIVE_DEPTH);
|
|
2560
|
+
return [...back, ...forward].filter((entry) => !!entry.instance);
|
|
2561
|
+
}
|
|
2469
2562
|
function layerSignature(state, windowId, onlyPane) {
|
|
2470
2563
|
const frame2 = canvasWindowFrame(state, windowId);
|
|
2471
2564
|
if (!frame2) return "";
|
|
2472
2565
|
const rows = [];
|
|
2566
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2567
|
+
const add = (hostId, born, fields) => {
|
|
2568
|
+
if (seen.has(hostId)) return;
|
|
2569
|
+
seen.add(hostId);
|
|
2570
|
+
rows.push({ born, hostId, row: [hostId, ...fields].join(SEP2) });
|
|
2571
|
+
};
|
|
2473
2572
|
const paneIds = listPaneIds(frame2.layout);
|
|
2474
2573
|
for (const paneId of onlyPane ? [onlyPane] : paneIds) {
|
|
2475
2574
|
const pane = state.panes[paneId];
|
|
2476
2575
|
for (const itemId of pane?.itemIds ?? []) {
|
|
2477
2576
|
const item = state.items[itemId];
|
|
2478
|
-
if (item)
|
|
2577
|
+
if (!item) continue;
|
|
2578
|
+
add(hostKey(item), bornAt(item.instance, item.openedAt), [itemId, paneId, pane?.activeItemId === itemId ? "1" : "0", "0"]);
|
|
2579
|
+
for (const step of keptCanvasSteps(item)) add(step.instance, bornAt(step.instance, item.openedAt), [itemId, paneId, "0", "1"]);
|
|
2479
2580
|
}
|
|
2480
2581
|
}
|
|
2481
|
-
rows.sort((a, b) => a.
|
|
2582
|
+
rows.sort((a, b) => a.born - b.born || a.hostId.localeCompare(b.hostId));
|
|
2482
2583
|
const head = [frame2.isOpen ? "1" : "0", frame2.isFullscreen ? "1" : "0", frame2.focusedPaneId, String(paneIds.length)].join(SEP2);
|
|
2483
2584
|
return [head, ...rows.map((r) => r.row)].join(ROW);
|
|
2484
2585
|
}
|
|
@@ -2492,8 +2593,8 @@ function parseSignature(signature) {
|
|
|
2492
2593
|
focusedPaneId,
|
|
2493
2594
|
paneCount: Number(count) || 1,
|
|
2494
2595
|
placed: rows.map((row) => {
|
|
2495
|
-
const [hostId = "", itemId = "", paneId = "", active] = row.split(SEP2);
|
|
2496
|
-
return { hostId, itemId, paneId, active: active === "1" };
|
|
2596
|
+
const [hostId = "", itemId = "", paneId = "", active, kept] = row.split(SEP2);
|
|
2597
|
+
return { hostId, itemId, paneId, active: active === "1", kept: kept === "1" };
|
|
2497
2598
|
})
|
|
2498
2599
|
};
|
|
2499
2600
|
}
|
|
@@ -2540,21 +2641,23 @@ function CanvasBodyLayer() {
|
|
|
2540
2641
|
const { windowId, layer } = useCanvasInternals();
|
|
2541
2642
|
const slots = useCanvasSlots();
|
|
2542
2643
|
const signature = useCanvasState((s) => layerSignature(s, windowId));
|
|
2644
|
+
const single = useCanvasSinglePane();
|
|
2543
2645
|
const root = (0, import_react7.useRef)(null);
|
|
2544
2646
|
const [placement] = (0, import_react7.useState)(
|
|
2545
2647
|
() => slots ? createPlacement(() => root.current, slots, () => layer.native.remeasure()) : null
|
|
2546
2648
|
);
|
|
2547
|
-
|
|
2548
|
-
|
|
2649
|
+
useIsoLayoutEffect2(() => placement?.place());
|
|
2650
|
+
useIsoLayoutEffect2(() => slots && placement ? slots.subscribe(placement.place) : void 0, [slots, placement]);
|
|
2549
2651
|
const shape = parseSignature(signature);
|
|
2550
2652
|
if (!slots || !placement || !shape) return null;
|
|
2551
|
-
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { ref: root, className: "mxc-bodies", "data-mxc-bodies": windowId, children: shape.placed.map(({ hostId, itemId, paneId, active }) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
2653
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { ref: root, className: "mxc-bodies", "data-mxc-bodies": windowId, children: shape.placed.map(({ hostId, itemId, paneId, active, kept }) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
2552
2654
|
BodyHost,
|
|
2553
2655
|
{
|
|
2554
2656
|
hostId,
|
|
2555
2657
|
itemId,
|
|
2658
|
+
kept,
|
|
2556
2659
|
paneId,
|
|
2557
|
-
visible: shape.isOpen && active,
|
|
2660
|
+
visible: shape.isOpen && active && (!single || paneId === shape.focusedPaneId),
|
|
2558
2661
|
focused: active && shape.focusedPaneId === paneId,
|
|
2559
2662
|
isFullscreen: shape.isFullscreen,
|
|
2560
2663
|
paneCount: shape.paneCount,
|
|
@@ -2568,11 +2671,12 @@ function CanvasPaneInlineBodies({ paneId, slots }) {
|
|
|
2568
2671
|
const { windowId } = useCanvasInternals();
|
|
2569
2672
|
const shape = parseSignature(useCanvasState((s) => layerSignature(s, windowId, paneId)));
|
|
2570
2673
|
if (!shape) return null;
|
|
2571
|
-
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_jsx_runtime6.Fragment, { children: shape.placed.map(({ hostId, itemId, active }) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
2674
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_jsx_runtime6.Fragment, { children: shape.placed.map(({ hostId, itemId, active, kept }) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
2572
2675
|
BodyHost,
|
|
2573
2676
|
{
|
|
2574
2677
|
hostId,
|
|
2575
2678
|
itemId,
|
|
2679
|
+
kept,
|
|
2576
2680
|
paneId,
|
|
2577
2681
|
visible: active,
|
|
2578
2682
|
focused: active && shape.focusedPaneId === paneId,
|
|
@@ -2584,9 +2688,22 @@ function CanvasPaneInlineBodies({ paneId, slots }) {
|
|
|
2584
2688
|
hostId
|
|
2585
2689
|
)) });
|
|
2586
2690
|
}
|
|
2691
|
+
function stepAsItem(step, openedAt) {
|
|
2692
|
+
return {
|
|
2693
|
+
id: canvasItemId(step.kind, step.key),
|
|
2694
|
+
kind: step.kind,
|
|
2695
|
+
key: step.key,
|
|
2696
|
+
title: step.title,
|
|
2697
|
+
data: step.data,
|
|
2698
|
+
openedAt,
|
|
2699
|
+
updatedAt: openedAt,
|
|
2700
|
+
...step.instance ? { instance: step.instance } : {}
|
|
2701
|
+
};
|
|
2702
|
+
}
|
|
2587
2703
|
var BodyHost = (0, import_react7.memo)(function BodyHost2({
|
|
2588
2704
|
hostId,
|
|
2589
2705
|
itemId,
|
|
2706
|
+
kept,
|
|
2590
2707
|
paneId,
|
|
2591
2708
|
visible,
|
|
2592
2709
|
focused,
|
|
@@ -2597,7 +2714,14 @@ var BodyHost = (0, import_react7.memo)(function BodyHost2({
|
|
|
2597
2714
|
}) {
|
|
2598
2715
|
const canvas = useCanvas();
|
|
2599
2716
|
const { windowId, ports } = useCanvasInternals();
|
|
2600
|
-
const
|
|
2717
|
+
const live = useCanvasState((s) => kept ? void 0 : s.items[itemId]);
|
|
2718
|
+
const step = useCanvasState((s) => {
|
|
2719
|
+
const ownerItem = kept ? s.items[itemId] : void 0;
|
|
2720
|
+
return ownerItem ? keptCanvasSteps(ownerItem).find((e) => e.instance === hostId) : void 0;
|
|
2721
|
+
});
|
|
2722
|
+
const owner = useCanvasState((s) => kept ? s.items[itemId]?.openedAt : void 0);
|
|
2723
|
+
const keptItem = (0, import_react7.useMemo)(() => step ? stepAsItem(step, owner ?? 0) : void 0, [step, owner]);
|
|
2724
|
+
const item = kept ? keptItem : live;
|
|
2601
2725
|
const kind = useItemKind(item?.kind ?? "");
|
|
2602
2726
|
const element = (0, import_react7.useRef)(null);
|
|
2603
2727
|
const [everShown, setEverShown] = (0, import_react7.useState)(visible);
|
|
@@ -2605,7 +2729,7 @@ var BodyHost = (0, import_react7.memo)(function BodyHost2({
|
|
|
2605
2729
|
const mounted = kind?.unmountWhenHidden ? visible : everShown;
|
|
2606
2730
|
const presentation = usePanePresentation(slots, paneId, isFullscreen, paneCount);
|
|
2607
2731
|
const drop = usePaneDrop(paneId, () => slots.section(paneId));
|
|
2608
|
-
|
|
2732
|
+
useIsoLayoutEffect2(() => {
|
|
2609
2733
|
const el = element.current;
|
|
2610
2734
|
if (!placement || !el) return void 0;
|
|
2611
2735
|
return placement.register(hostId, { element: el, paneId });
|
|
@@ -2621,6 +2745,7 @@ var BodyHost = (0, import_react7.memo)(function BodyHost2({
|
|
|
2621
2745
|
"data-visible": visible ? "true" : "false",
|
|
2622
2746
|
"data-kind": item.kind,
|
|
2623
2747
|
"data-item": item.id,
|
|
2748
|
+
"data-kept": kept ? "" : void 0,
|
|
2624
2749
|
"data-pane": paneId,
|
|
2625
2750
|
inert: !visible,
|
|
2626
2751
|
"aria-hidden": visible ? void 0 : true,
|
|
@@ -2702,8 +2827,8 @@ function NativeBody({ itemId, windowId, visible, children }) {
|
|
|
2702
2827
|
const rect = { ...toCanvasRect(box), devicePixelRatio: window.devicePixelRatio || 1 };
|
|
2703
2828
|
layer.native.report(itemId, rect, { visible: !layer.isBlocked(), windowId });
|
|
2704
2829
|
};
|
|
2705
|
-
|
|
2706
|
-
|
|
2830
|
+
useIsoLayoutEffect2(() => measure.current());
|
|
2831
|
+
useIsoLayoutEffect2(() => {
|
|
2707
2832
|
const el = ref.current;
|
|
2708
2833
|
const run = () => measure.current();
|
|
2709
2834
|
const observer = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(run);
|
|
@@ -2759,7 +2884,7 @@ var ItemBoundary = class extends import_react7.Component {
|
|
|
2759
2884
|
var import_react8 = require("react");
|
|
2760
2885
|
var Menu = __toESM(require("@radix-ui/react-dropdown-menu"), 1);
|
|
2761
2886
|
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
2762
|
-
var
|
|
2887
|
+
var useIsoLayoutEffect3 = typeof window === "undefined" ? import_react8.useEffect : import_react8.useLayoutEffect;
|
|
2763
2888
|
function itemTitle(item, kind) {
|
|
2764
2889
|
if (item.title) return item.title;
|
|
2765
2890
|
if (item.kind === CANVAS_LAUNCHER_KIND) return "New tab";
|
|
@@ -2773,6 +2898,25 @@ function itemTitle(item, kind) {
|
|
|
2773
2898
|
return kind?.label ?? item.kind;
|
|
2774
2899
|
}
|
|
2775
2900
|
var isMac = () => typeof navigator !== "undefined" && /mac|iphone|ipad/i.test(navigator.platform ?? "");
|
|
2901
|
+
function windowTabsSignature(state, windowId) {
|
|
2902
|
+
const frame2 = canvasWindowFrame(state, windowId);
|
|
2903
|
+
if (!frame2) return "";
|
|
2904
|
+
const rows = [];
|
|
2905
|
+
for (const paneId of listPaneIds(frame2.layout)) {
|
|
2906
|
+
for (const itemId of state.panes[paneId]?.itemIds ?? []) rows.push(`${itemId}${paneId}`);
|
|
2907
|
+
}
|
|
2908
|
+
return rows.join("");
|
|
2909
|
+
}
|
|
2910
|
+
function parseWindowTabs(signature) {
|
|
2911
|
+
if (!signature) return [];
|
|
2912
|
+
const perPane = /* @__PURE__ */ new Map();
|
|
2913
|
+
return signature.split("").map((row) => {
|
|
2914
|
+
const [itemId = "", paneId = ""] = row.split("");
|
|
2915
|
+
const index = perPane.get(paneId) ?? 0;
|
|
2916
|
+
perPane.set(paneId, index + 1);
|
|
2917
|
+
return { itemId, paneId, index };
|
|
2918
|
+
});
|
|
2919
|
+
}
|
|
2776
2920
|
function CanvasPaneView({ paneId }) {
|
|
2777
2921
|
const canvas = useCanvas();
|
|
2778
2922
|
const { windowId, tabStrip } = useCanvasInternals();
|
|
@@ -2791,11 +2935,13 @@ function CanvasPaneView({ paneId }) {
|
|
|
2791
2935
|
const role = useCanvasState((s) => windowId === CANVAS_MAIN_WINDOW ? "main" : s.windows[windowId]?.role ?? "window");
|
|
2792
2936
|
const canGoBack = useCanvasState((s) => active ? selectCanvasCanGoBack(s, active.id) : false);
|
|
2793
2937
|
const kind = useItemKind(active?.kind ?? "");
|
|
2938
|
+
const singlePane = useCanvasSinglePane();
|
|
2939
|
+
const windowTabs = useCanvasState((s) => singlePane ? windowTabsSignature(s, windowId) : "");
|
|
2794
2940
|
const sectionRef = (0, import_react8.useRef)(null);
|
|
2795
2941
|
const bodyRef = (0, import_react8.useRef)(null);
|
|
2796
2942
|
const presentation = usePanePresentation(slots, paneId, isFullscreen, paneCount);
|
|
2797
2943
|
const drop = usePaneDrop(paneId, () => sectionRef.current);
|
|
2798
|
-
|
|
2944
|
+
useIsoLayoutEffect3(() => {
|
|
2799
2945
|
const body = bodyRef.current;
|
|
2800
2946
|
const section = sectionRef.current;
|
|
2801
2947
|
if (body) slots.set(paneId, body);
|
|
@@ -2810,7 +2956,8 @@ function CanvasPaneView({ paneId }) {
|
|
|
2810
2956
|
const Leading = kind?.HeaderLeading;
|
|
2811
2957
|
const Action = kind?.HeaderAction;
|
|
2812
2958
|
const Toolbar = kind?.Toolbar;
|
|
2813
|
-
const
|
|
2959
|
+
const tabs = singlePane ? parseWindowTabs(windowTabs) : pane.itemIds.map((itemId, index) => ({ itemId, paneId, index }));
|
|
2960
|
+
const single = tabStrip === "auto" && tabs.length === 1 && active;
|
|
2814
2961
|
const closeLabel = role === "pop-out" && paneCount === 1 ? "Close window" : paneCount > 1 ? "Close pane" : "Close canvas";
|
|
2815
2962
|
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
2816
2963
|
CanvasPanel,
|
|
@@ -2823,7 +2970,7 @@ function CanvasPaneView({ paneId }) {
|
|
|
2823
2970
|
"data-mxc-pane": paneId,
|
|
2824
2971
|
header: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
|
|
2825
2972
|
canGoBack && active ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CanvasHeaderButton, { className: "mxc-back", label: "Back", onClick: () => void canvas.back(active.id), children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ArrowLeftIcon, {}) }) : null,
|
|
2826
|
-
single && active ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SingleTitle, { item: active, kind }) :
|
|
2973
|
+
single && active ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SingleTitle, { item: active, kind }) : tabs.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(TabStrip, { tabs, activeItemId: pane.activeItemId }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "mxc-panel-title", children: "New tab" }),
|
|
2827
2974
|
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CanvasHeaderButton, { className: "mxc-new-tab", label: "New tab", onClick: () => void canvas.newTab(paneId), children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(PlusIcon, {}) })
|
|
2828
2975
|
] }),
|
|
2829
2976
|
leading: Leading && kindProps ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Leading, { ...kindProps }) : null,
|
|
@@ -2872,38 +3019,71 @@ function SingleTitle({ item, kind }) {
|
|
|
2872
3019
|
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { type: "button", className: "mxc-tab-close", "data-slot": "browser-tab-close", "aria-label": `Close ${title}`, onClick: () => canvas.close(item.id), children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CloseIcon, {}) })
|
|
2873
3020
|
] });
|
|
2874
3021
|
}
|
|
2875
|
-
function TabStrip({
|
|
3022
|
+
function TabStrip({ tabs, activeItemId }) {
|
|
2876
3023
|
const strip = (0, import_react8.useRef)(null);
|
|
2877
|
-
|
|
3024
|
+
const [overflow, setOverflow] = (0, import_react8.useState)({ start: false, end: false });
|
|
3025
|
+
const measure = (0, import_react8.useRef)(() => void 0);
|
|
3026
|
+
measure.current = () => {
|
|
3027
|
+
const el = strip.current;
|
|
3028
|
+
if (!el) return;
|
|
3029
|
+
const start = el.scrollLeft > 1;
|
|
3030
|
+
const end = el.scrollLeft + el.clientWidth < el.scrollWidth - 1;
|
|
3031
|
+
setOverflow((prev) => prev.start === start && prev.end === end ? prev : { start, end });
|
|
3032
|
+
};
|
|
3033
|
+
const tabKey = tabs.map((tab) => tab.itemId).join("|");
|
|
3034
|
+
useIsoLayoutEffect3(() => {
|
|
2878
3035
|
const el = strip.current;
|
|
2879
3036
|
if (!el) return void 0;
|
|
2880
3037
|
const reveal = () => {
|
|
2881
3038
|
const tab = el.querySelector('[role="tab"][aria-selected="true"]');
|
|
2882
|
-
if (
|
|
2883
|
-
|
|
2884
|
-
|
|
2885
|
-
|
|
2886
|
-
|
|
3039
|
+
if (tab) {
|
|
3040
|
+
const left = tab.offsetLeft;
|
|
3041
|
+
const right = left + tab.offsetWidth;
|
|
3042
|
+
if (left < el.scrollLeft) el.scrollLeft = left;
|
|
3043
|
+
else if (right > el.scrollLeft + el.clientWidth) el.scrollLeft = right - el.clientWidth;
|
|
3044
|
+
}
|
|
3045
|
+
measure.current();
|
|
2887
3046
|
};
|
|
2888
3047
|
reveal();
|
|
2889
3048
|
const observer = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(reveal);
|
|
2890
3049
|
observer?.observe(el);
|
|
2891
|
-
const
|
|
2892
|
-
if (activeTab) observer?.observe(activeTab);
|
|
3050
|
+
for (const tab of el.querySelectorAll('[role="tab"]')) observer?.observe(tab);
|
|
2893
3051
|
return () => observer?.disconnect();
|
|
2894
|
-
}, [activeItemId,
|
|
2895
|
-
|
|
3052
|
+
}, [activeItemId, tabKey]);
|
|
3053
|
+
const page = (direction) => {
|
|
3054
|
+
const el = strip.current;
|
|
3055
|
+
if (!el) return;
|
|
3056
|
+
const by = Math.max(48, Math.round(el.clientWidth * 0.8)) * direction;
|
|
3057
|
+
if (typeof el.scrollBy === "function") el.scrollBy({ left: by, behavior: "smooth" });
|
|
3058
|
+
else el.scrollLeft += by;
|
|
3059
|
+
};
|
|
3060
|
+
const overflowing = overflow.start || overflow.end;
|
|
3061
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
2896
3062
|
"div",
|
|
2897
3063
|
{
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
"
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
|
|
2906
|
-
|
|
3064
|
+
className: "mxc-tabstrip",
|
|
3065
|
+
"data-overflow": overflowing ? "" : void 0,
|
|
3066
|
+
"data-overflow-start": overflow.start ? "" : void 0,
|
|
3067
|
+
"data-overflow-end": overflow.end ? "" : void 0,
|
|
3068
|
+
children: [
|
|
3069
|
+
overflowing ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CanvasHeaderButton, { className: "mxc-tabs-scroll", label: "Scroll tabs left", available: overflow.start, onClick: () => page(-1), children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ChevronLeftIcon, {}) }) : null,
|
|
3070
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
3071
|
+
"div",
|
|
3072
|
+
{
|
|
3073
|
+
ref: strip,
|
|
3074
|
+
className: "mxc-tabs",
|
|
3075
|
+
role: "tablist",
|
|
3076
|
+
"aria-label": "Canvas tabs",
|
|
3077
|
+
onScroll: () => measure.current(),
|
|
3078
|
+
onWheel: (event) => {
|
|
3079
|
+
const el = strip.current;
|
|
3080
|
+
if (el && Math.abs(event.deltaY) > Math.abs(event.deltaX)) el.scrollLeft += event.deltaY;
|
|
3081
|
+
},
|
|
3082
|
+
children: tabs.map((tab) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ItemTab, { itemId: tab.itemId, paneId: tab.paneId, index: tab.index, active: tab.itemId === activeItemId }, tab.itemId))
|
|
3083
|
+
}
|
|
3084
|
+
),
|
|
3085
|
+
overflowing ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CanvasHeaderButton, { className: "mxc-tabs-scroll", label: "Scroll tabs right", available: overflow.end, onClick: () => page(1), children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ChevronRightIcon, {}) }) : null
|
|
3086
|
+
]
|
|
2907
3087
|
}
|
|
2908
3088
|
);
|
|
2909
3089
|
}
|
|
@@ -3027,7 +3207,7 @@ function safeMenu(build) {
|
|
|
3027
3207
|
|
|
3028
3208
|
// src/react/CanvasColumn.tsx
|
|
3029
3209
|
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
3030
|
-
var
|
|
3210
|
+
var useIsoLayoutEffect4 = typeof window === "undefined" ? import_react9.useEffect : import_react9.useLayoutEffect;
|
|
3031
3211
|
function subscribeViewport(listener) {
|
|
3032
3212
|
window.addEventListener("resize", listener);
|
|
3033
3213
|
return () => window.removeEventListener("resize", listener);
|
|
@@ -3056,7 +3236,10 @@ function CanvasColumn({ className, style, onLiveWidth, placement = "docked" }) {
|
|
|
3056
3236
|
const isFullscreen = useCanvasState((s) => selectCanvasIsFullscreen(s, windowId));
|
|
3057
3237
|
const width = useCanvasState((s) => selectCanvasWidth(s, windowId));
|
|
3058
3238
|
const layout = useCanvasState((s) => selectCanvasLayout(s, windowId));
|
|
3239
|
+
const focusedPaneId = useCanvasState((s) => selectCanvasFocusedPaneId(s, windowId));
|
|
3059
3240
|
const region = useRegionWidth();
|
|
3241
|
+
const viewport = useViewportWidth();
|
|
3242
|
+
const singlePane = placement === "docked" && viewport > 0 && viewport <= CANVAS_PHONE_MAX_WIDTH;
|
|
3060
3243
|
const [dragWidth, setDragWidth] = (0, import_react9.useState)(null);
|
|
3061
3244
|
const [slots] = (0, import_react9.useState)(createCanvasSlots);
|
|
3062
3245
|
const ref = (0, import_react9.useRef)(null);
|
|
@@ -3121,10 +3304,10 @@ function CanvasColumn({ className, style, onLiveWidth, placement = "docked" }) {
|
|
|
3121
3304
|
}
|
|
3122
3305
|
}
|
|
3123
3306
|
) : null,
|
|
3124
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.
|
|
3125
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "mxc-layout", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(LayoutNodeView, { node: layout }) }),
|
|
3307
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CanvasSlotsContext.Provider, { value: slots, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(CanvasSinglePaneContext.Provider, { value: singlePane, children: [
|
|
3308
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "mxc-layout", "data-single-pane": singlePane ? "" : void 0, children: singlePane ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CanvasPaneView, { paneId: presentedPane(layout, focusedPaneId) }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(LayoutNodeView, { node: layout }) }),
|
|
3126
3309
|
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CanvasBodyLayer, {})
|
|
3127
|
-
] })
|
|
3310
|
+
] }) })
|
|
3128
3311
|
] })
|
|
3129
3312
|
}
|
|
3130
3313
|
);
|
|
@@ -3172,13 +3355,17 @@ function WidthHandle({ width, region, onDrag }) {
|
|
|
3172
3355
|
}
|
|
3173
3356
|
);
|
|
3174
3357
|
}
|
|
3358
|
+
function presentedPane(layout, focused) {
|
|
3359
|
+
const ids = listPaneIds(layout);
|
|
3360
|
+
return ids.find((id) => id === focused) ?? ids[0];
|
|
3361
|
+
}
|
|
3175
3362
|
function LayoutNodeView({ node }) {
|
|
3176
3363
|
if (node.type === "pane") return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CanvasPaneView, { paneId: node.paneId });
|
|
3177
3364
|
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(SplitView, { node });
|
|
3178
3365
|
}
|
|
3179
3366
|
function useMeasuredWidth(ref, enabled) {
|
|
3180
3367
|
const [width, setWidth] = (0, import_react9.useState)(0);
|
|
3181
|
-
|
|
3368
|
+
useIsoLayoutEffect4(() => {
|
|
3182
3369
|
const el = ref.current;
|
|
3183
3370
|
if (!enabled || !el) return;
|
|
3184
3371
|
setWidth(el.getBoundingClientRect().width);
|
|
@@ -3274,6 +3461,7 @@ function CanvasToggle({
|
|
|
3274
3461
|
ariaLabel: isOpen ? "Hide canvas" : "Show canvas",
|
|
3275
3462
|
tooltip: `${isOpen ? "Hide canvas" : "Show canvas"}${hint ? ` (${hint})` : ""}`,
|
|
3276
3463
|
icon: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(PanelRightIcon, {}),
|
|
3464
|
+
pressed: isOpen,
|
|
3277
3465
|
onClick: () => controller.toggle()
|
|
3278
3466
|
}
|
|
3279
3467
|
),
|