foss-design 0.9.11 → 0.9.12
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/dist/viewer/assets/index-BUDcnDgZ.css +2 -0
- package/dist/viewer/assets/{index-mvGp1q3N.js → index-Cm4CEv8V.js} +31 -31
- package/dist/viewer/index.html +2 -2
- package/dist/viewer-lib/index.js +276 -50
- package/dist/viewer-lib/styles.css +68 -5
- package/dist/viewer-lib/types/viewer/src/lib/viewer.d.ts +3 -0
- package/dist/viewer-lib/types/viewer/src/library.d.ts +1 -0
- package/dist/viewer-lib/types/viewer/src/pages/canvas/canvas-bar.d.ts +2 -2
- package/dist/viewer-lib/types/viewer/src/pages/canvas/layout.d.ts +2 -0
- package/dist/viewer-lib/types/viewer/src/ui/combobox.d.ts +25 -0
- package/dist/viewer-lib/types/viewer/src/ui/icon-paths.d.ts +1 -0
- package/package.json +1 -1
- package/dist/viewer/assets/index-Cy6JlR85.css +0 -2
package/dist/viewer/index.html
CHANGED
|
@@ -14,8 +14,8 @@
|
|
|
14
14
|
document.documentElement.dataset.theme = dark ? 'dark' : 'light'
|
|
15
15
|
} catch (e) {}
|
|
16
16
|
</script>
|
|
17
|
-
<script type="module" crossorigin src="./assets/index-
|
|
18
|
-
<link rel="stylesheet" crossorigin href="./assets/index-
|
|
17
|
+
<script type="module" crossorigin src="./assets/index-Cm4CEv8V.js"></script>
|
|
18
|
+
<link rel="stylesheet" crossorigin href="./assets/index-BUDcnDgZ.css">
|
|
19
19
|
</head>
|
|
20
20
|
<body>
|
|
21
21
|
<div id="root"></div>
|
package/dist/viewer-lib/index.js
CHANGED
|
@@ -2730,6 +2730,7 @@ var ICON_PATHS = {
|
|
|
2730
2730
|
tablet: "<rect width=\"16\" height=\"20\" x=\"4\" y=\"2\" rx=\"2\"/><path d=\"M12 18h.01\"/>",
|
|
2731
2731
|
note: "<path d=\"M16 3H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V8Z\"/><path d=\"M15 3v4a2 2 0 0 0 2 2h4\"/>",
|
|
2732
2732
|
globe: "<circle cx=\"12\" cy=\"12\" r=\"10\"/><path d=\"M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20\"/><path d=\"M2 12h20\"/>",
|
|
2733
|
+
share: "<path d=\"M4 12v8a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-8\"/><path d=\"m16 6-4-4-4 4\"/><path d=\"M12 2v13\"/>",
|
|
2733
2734
|
pointer: "<path d=\"M4.04 4.69a.5.5 0 0 1 .65-.65l16 6.5a.5.5 0 0 1-.06.95l-6.12 1.58a2 2 0 0 0-1.44 1.44l-1.58 6.12a.5.5 0 0 1-.95.06z\"/>",
|
|
2734
2735
|
component: "<path d=\"M5.5 8.5 9 12l-3.5 3.5L2 12l3.5-3.5Z\"/><path d=\"m12 2 3.5 3.5L12 9 8.5 5.5 12 2Z\"/><path d=\"M18.5 8.5 22 12l-3.5 3.5L15 12l3.5-3.5Z\"/><path d=\"m12 15 3.5 3.5L12 22l-3.5-3.5L12 15Z\"/>",
|
|
2735
2736
|
keyboard: "<rect width=\"20\" height=\"16\" x=\"2\" y=\"4\" rx=\"2\"/><path d=\"M6 8h.01\"/><path d=\"M10 8h.01\"/><path d=\"M14 8h.01\"/><path d=\"M18 8h.01\"/><path d=\"M8 12h.01\"/><path d=\"M12 12h.01\"/><path d=\"M16 12h.01\"/><path d=\"M7 16h10\"/>",
|
|
@@ -5222,10 +5223,10 @@ var Popper = /* @__PURE__ */ __name$9((props) => {
|
|
|
5222
5223
|
children
|
|
5223
5224
|
});
|
|
5224
5225
|
}, "Popper");
|
|
5225
|
-
var ANCHOR_NAME = "PopperAnchor";
|
|
5226
|
+
var ANCHOR_NAME$1 = "PopperAnchor";
|
|
5226
5227
|
var PopperAnchor = /* @__PURE__ */ React.forwardRef(/* @__PURE__ */ __name$9(function PopperAnchor2(props, forwardedRef) {
|
|
5227
5228
|
const { __scopePopper, virtualRef, ...anchorProps } = props;
|
|
5228
|
-
const context = usePopperContext(ANCHOR_NAME, __scopePopper);
|
|
5229
|
+
const context = usePopperContext(ANCHOR_NAME$1, __scopePopper);
|
|
5229
5230
|
const ref = React.useRef(null);
|
|
5230
5231
|
const onAnchorChange = context.onAnchorChange;
|
|
5231
5232
|
const composedRefs = useComposedRefs(forwardedRef, React.useCallback((node) => {
|
|
@@ -7263,7 +7264,7 @@ function whenMouse(handler) {
|
|
|
7263
7264
|
}
|
|
7264
7265
|
__name$2(whenMouse, "whenMouse");
|
|
7265
7266
|
var Root3 = Menu$1;
|
|
7266
|
-
var Anchor2 = MenuAnchor;
|
|
7267
|
+
var Anchor2$1 = MenuAnchor;
|
|
7267
7268
|
var Portal$1 = MenuPortal;
|
|
7268
7269
|
var Content2$2 = MenuContent;
|
|
7269
7270
|
var Label$1 = MenuLabel$1;
|
|
@@ -7315,7 +7316,7 @@ var DropdownMenuTrigger = /* @__PURE__ */ React.forwardRef(/* @__PURE__ */ __nam
|
|
|
7315
7316
|
const context = useDropdownMenuContext(TRIGGER_NAME$1, __scopeDropdownMenu);
|
|
7316
7317
|
const menuScope = useMenuScope(__scopeDropdownMenu);
|
|
7317
7318
|
const composedRefs = useComposedRefs(forwardedRef, context.triggerRef);
|
|
7318
|
-
return /* @__PURE__ */ jsx(Anchor2, {
|
|
7319
|
+
return /* @__PURE__ */ jsx(Anchor2$1, {
|
|
7319
7320
|
asChild: true,
|
|
7320
7321
|
...menuScope,
|
|
7321
7322
|
children: /* @__PURE__ */ jsx(Primitive.button, {
|
|
@@ -7828,6 +7829,22 @@ var Popover = /* @__PURE__ */ __name((props) => {
|
|
|
7828
7829
|
})
|
|
7829
7830
|
});
|
|
7830
7831
|
}, "Popover");
|
|
7832
|
+
var ANCHOR_NAME = "PopoverAnchor";
|
|
7833
|
+
var PopoverAnchor = /* @__PURE__ */ React.forwardRef(/* @__PURE__ */ __name(function PopoverAnchor2(props, forwardedRef) {
|
|
7834
|
+
const { __scopePopover, ...anchorProps } = props;
|
|
7835
|
+
const context = usePopoverContext(ANCHOR_NAME, __scopePopover);
|
|
7836
|
+
const popperScope = usePopperScope(__scopePopover);
|
|
7837
|
+
const { onCustomAnchorAdd, onCustomAnchorRemove } = context;
|
|
7838
|
+
React.useEffect(() => {
|
|
7839
|
+
onCustomAnchorAdd();
|
|
7840
|
+
return () => onCustomAnchorRemove();
|
|
7841
|
+
}, [onCustomAnchorAdd, onCustomAnchorRemove]);
|
|
7842
|
+
return /* @__PURE__ */ jsx(Anchor, {
|
|
7843
|
+
...popperScope,
|
|
7844
|
+
...anchorProps,
|
|
7845
|
+
ref: forwardedRef
|
|
7846
|
+
});
|
|
7847
|
+
}, "PopoverAnchor"));
|
|
7831
7848
|
var TRIGGER_NAME = "PopoverTrigger";
|
|
7832
7849
|
var PopoverTrigger = /* @__PURE__ */ React.forwardRef(/* @__PURE__ */ __name(function PopoverTrigger2(props, forwardedRef) {
|
|
7833
7850
|
const { __scopePopover, ...triggerProps } = props;
|
|
@@ -7990,6 +8007,7 @@ function getState(open) {
|
|
|
7990
8007
|
}
|
|
7991
8008
|
__name(getState, "getState");
|
|
7992
8009
|
var Root2 = Popover;
|
|
8010
|
+
var Anchor2 = PopoverAnchor;
|
|
7993
8011
|
var Trigger = PopoverTrigger;
|
|
7994
8012
|
var Portal = PopoverPortal;
|
|
7995
8013
|
var Content2 = PopoverContent;
|
|
@@ -11523,22 +11541,84 @@ function CanvasBar({ canvas, page, theme, onTheme, sidebar, onSidebar, onPlay, c
|
|
|
11523
11541
|
}) : null]
|
|
11524
11542
|
});
|
|
11525
11543
|
}
|
|
11526
|
-
/** The selected item's name and actions, floating over the bottom of the canvas. */
|
|
11544
|
+
/** The selected item's name and actions, floating over the bottom of the canvas; it eases in and out. */
|
|
11527
11545
|
function SelectionBar({ canvas, store, layoutItems, theme, onPlay, inspect }) {
|
|
11528
11546
|
const selected = useStore(store, (state) => state.selected);
|
|
11529
|
-
const active = useStore(store, (state) => state.active);
|
|
11530
|
-
const status = useStore(store, (state) => selected ? state.frames[selected] : void 0);
|
|
11531
11547
|
const item = layoutItems.find((i) => i.id === selected);
|
|
11532
|
-
const openUrl = useOpenUrl(canvas.id, item?.kind === "screen" || item?.kind === "url" ? item : void 0, theme);
|
|
11533
|
-
if (!item) return null;
|
|
11534
|
-
const frame = item.kind === "screen" || item.kind === "url";
|
|
11535
|
-
const reload = () => reloadFrame(document.querySelector(`[data-item="${CSS.escape(item.id)}"] iframe`));
|
|
11536
|
-
const errors = status?.errors ?? [];
|
|
11537
11548
|
return /* @__PURE__ */ jsx("div", {
|
|
11538
11549
|
"data-ui": true,
|
|
11539
11550
|
className: "pointer-events-none absolute inset-x-0 bottom-5 z-20 flex justify-center px-4",
|
|
11540
|
-
children: /* @__PURE__ */
|
|
11541
|
-
|
|
11551
|
+
children: /* @__PURE__ */ jsx(AnimatePresence, { children: item ? /* @__PURE__ */ jsx(SelectedBar, {
|
|
11552
|
+
canvas,
|
|
11553
|
+
store,
|
|
11554
|
+
item,
|
|
11555
|
+
theme,
|
|
11556
|
+
onPlay,
|
|
11557
|
+
inspect
|
|
11558
|
+
}, "bar") : null })
|
|
11559
|
+
});
|
|
11560
|
+
}
|
|
11561
|
+
function SelectedBar({ canvas, store, item, theme, onPlay, inspect }) {
|
|
11562
|
+
const { slots } = useViewer();
|
|
11563
|
+
const status = useStore(store, (state) => state.frames[item.id]);
|
|
11564
|
+
const openUrl = useOpenUrl(canvas.id, item.kind === "screen" || item.kind === "url" ? item : void 0, theme);
|
|
11565
|
+
const frame = item.kind === "screen" || item.kind === "url";
|
|
11566
|
+
const reload = () => reloadFrame(document.querySelector(`[data-item="${CSS.escape(item.id)}"] iframe`));
|
|
11567
|
+
const errors = status?.errors ?? [];
|
|
11568
|
+
return /* @__PURE__ */ jsxs(motion.div, {
|
|
11569
|
+
initial: {
|
|
11570
|
+
opacity: 0,
|
|
11571
|
+
y: 10,
|
|
11572
|
+
scale: .98
|
|
11573
|
+
},
|
|
11574
|
+
animate: {
|
|
11575
|
+
opacity: 1,
|
|
11576
|
+
y: 0,
|
|
11577
|
+
scale: 1
|
|
11578
|
+
},
|
|
11579
|
+
exit: {
|
|
11580
|
+
opacity: 0,
|
|
11581
|
+
y: 10,
|
|
11582
|
+
scale: .98,
|
|
11583
|
+
transition: {
|
|
11584
|
+
duration: .14,
|
|
11585
|
+
ease: "easeIn"
|
|
11586
|
+
}
|
|
11587
|
+
},
|
|
11588
|
+
transition: {
|
|
11589
|
+
type: "spring",
|
|
11590
|
+
duration: .26,
|
|
11591
|
+
bounce: .12
|
|
11592
|
+
},
|
|
11593
|
+
className: "relative flex w-fit max-w-[95%] min-w-0 flex-col",
|
|
11594
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
11595
|
+
className: "pointer-events-none absolute inset-x-5 bottom-full flex justify-center",
|
|
11596
|
+
children: /* @__PURE__ */ jsx(AnimatePresence, { children: frame && inspect ? /* @__PURE__ */ jsx(motion.div, {
|
|
11597
|
+
initial: {
|
|
11598
|
+
y: "100%",
|
|
11599
|
+
opacity: 0
|
|
11600
|
+
},
|
|
11601
|
+
animate: {
|
|
11602
|
+
y: 0,
|
|
11603
|
+
opacity: .9
|
|
11604
|
+
},
|
|
11605
|
+
exit: {
|
|
11606
|
+
y: "100%",
|
|
11607
|
+
opacity: 0
|
|
11608
|
+
},
|
|
11609
|
+
transition: {
|
|
11610
|
+
type: "spring",
|
|
11611
|
+
duration: .28,
|
|
11612
|
+
bounce: .15
|
|
11613
|
+
},
|
|
11614
|
+
className: "flex h-[22px] min-w-0 items-center rounded-t-[7px] border border-b-0 border-rule bg-surface/80 px-3 text-[11.5px] whitespace-nowrap text-muted backdrop-blur-md",
|
|
11615
|
+
children: /* @__PURE__ */ jsx("span", {
|
|
11616
|
+
className: "truncate",
|
|
11617
|
+
children: "Click an element to inspect it"
|
|
11618
|
+
})
|
|
11619
|
+
}, "inspect") : null })
|
|
11620
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
11621
|
+
className: "pointer-events-auto relative flex max-w-full flex-col overflow-hidden rounded-[10px] border border-rule bg-surface shadow-pop",
|
|
11542
11622
|
children: [errors.length ? /* @__PURE__ */ jsxs("div", {
|
|
11543
11623
|
className: "flex max-h-40 items-start gap-2 overflow-y-auto border-b border-rule bg-danger-soft px-3.5 py-2 font-mono text-[12px] whitespace-pre-wrap text-danger-text",
|
|
11544
11624
|
children: [/* @__PURE__ */ jsx(Icon, {
|
|
@@ -11550,29 +11630,11 @@ function SelectionBar({ canvas, store, layoutItems, theme, onPlay, inspect }) {
|
|
|
11550
11630
|
children: errors.join("\n")
|
|
11551
11631
|
})]
|
|
11552
11632
|
}) : null, /* @__PURE__ */ jsxs("div", {
|
|
11553
|
-
className: "flex h-[44px] items-center gap-1 pr-1.5 pl-3.5",
|
|
11633
|
+
className: "flex h-[44px] items-center gap-1 pr-1.5 pl-3.5 [&>:not(:first-child)]:shrink-0",
|
|
11554
11634
|
children: [
|
|
11555
|
-
/* @__PURE__ */
|
|
11556
|
-
className: "
|
|
11557
|
-
children:
|
|
11558
|
-
className: "truncate text-[13.5px] font-medium",
|
|
11559
|
-
children: item.title || item.id
|
|
11560
|
-
}), frame && active === item.id ? /* @__PURE__ */ jsxs("span", {
|
|
11561
|
-
className: "flex shrink-0 items-center gap-1.5 text-[12px] text-muted",
|
|
11562
|
-
children: [
|
|
11563
|
-
/* @__PURE__ */ jsx(Icon, {
|
|
11564
|
-
name: "pointer",
|
|
11565
|
-
size: 13
|
|
11566
|
-
}),
|
|
11567
|
-
" ",
|
|
11568
|
-
inspect ? "Inspecting" : "Interacting",
|
|
11569
|
-
" ",
|
|
11570
|
-
/* @__PURE__ */ jsx(Kbd, { children: "esc" })
|
|
11571
|
-
]
|
|
11572
|
-
}) : frame ? /* @__PURE__ */ jsx("span", {
|
|
11573
|
-
className: "shrink-0 text-[12px] text-muted",
|
|
11574
|
-
children: inspect ? "Click an element to inspect it" : "Click the screen to interact"
|
|
11575
|
-
}) : null]
|
|
11635
|
+
/* @__PURE__ */ jsx("span", {
|
|
11636
|
+
className: "min-w-0 truncate pr-2 text-[13.5px] font-medium",
|
|
11637
|
+
children: item.title || item.id
|
|
11576
11638
|
}),
|
|
11577
11639
|
frame ? /* @__PURE__ */ jsx(Tooltip, {
|
|
11578
11640
|
content: /* @__PURE__ */ jsxs("span", {
|
|
@@ -11615,6 +11677,7 @@ function SelectionBar({ canvas, store, layoutItems, theme, onPlay, inspect }) {
|
|
|
11615
11677
|
onClick: () => void copyText(item.file, "Path copied")
|
|
11616
11678
|
})
|
|
11617
11679
|
}) : null,
|
|
11680
|
+
slots.selectionActions?.(canvas.id, item),
|
|
11618
11681
|
/* @__PURE__ */ jsx(Tooltip, {
|
|
11619
11682
|
content: /* @__PURE__ */ jsxs("span", {
|
|
11620
11683
|
className: "flex items-center gap-1.5",
|
|
@@ -11631,7 +11694,7 @@ function SelectionBar({ canvas, store, layoutItems, theme, onPlay, inspect }) {
|
|
|
11631
11694
|
})
|
|
11632
11695
|
]
|
|
11633
11696
|
})]
|
|
11634
|
-
})
|
|
11697
|
+
})]
|
|
11635
11698
|
});
|
|
11636
11699
|
}
|
|
11637
11700
|
/** The inspect mode switch: a button that stays pressed while on. */
|
|
@@ -11748,7 +11811,8 @@ function layoutPage(page, sizes) {
|
|
|
11748
11811
|
y: top,
|
|
11749
11812
|
w: Math.max(width, header ? HEADER_MIN_WIDTH : 0),
|
|
11750
11813
|
h: bottom - top,
|
|
11751
|
-
header
|
|
11814
|
+
header,
|
|
11815
|
+
body: header ? header + HEADER_GAP : 0
|
|
11752
11816
|
});
|
|
11753
11817
|
y = bottom + SECTION_GAP;
|
|
11754
11818
|
}
|
|
@@ -12168,13 +12232,17 @@ var Label = memo(function Label({ placed, store }) {
|
|
|
12168
12232
|
]
|
|
12169
12233
|
});
|
|
12170
12234
|
});
|
|
12171
|
-
/**
|
|
12235
|
+
/**
|
|
12236
|
+
* A section's title in screen space, for zooms where the one on the canvas is too small to read: where
|
|
12237
|
+
* that one was, lifted only as far as it must be to clear the frame labels under it.
|
|
12238
|
+
*/
|
|
12172
12239
|
var SectionTitle = memo(function SectionTitle({ placed }) {
|
|
12173
12240
|
return /* @__PURE__ */ jsx("div", {
|
|
12174
12241
|
"data-at": "",
|
|
12175
12242
|
style: {
|
|
12176
12243
|
"--x": placed.x,
|
|
12177
|
-
"--y": placed.y
|
|
12244
|
+
"--y": placed.y,
|
|
12245
|
+
"--body": placed.body
|
|
12178
12246
|
},
|
|
12179
12247
|
className: "section-title text-[15px] leading-none font-semibold whitespace-nowrap text-ink select-none",
|
|
12180
12248
|
children: placed.section.title
|
|
@@ -12772,15 +12840,20 @@ function CanvasView({ canvas, page }) {
|
|
|
12772
12840
|
useEffect(() => {
|
|
12773
12841
|
if (picked) setInspect(true);
|
|
12774
12842
|
}, [picked]);
|
|
12843
|
+
const pickedInfo = inspection.info;
|
|
12775
12844
|
useEffect(() => {
|
|
12776
12845
|
const frame = inspection.frame;
|
|
12777
|
-
if (!frame) return;
|
|
12846
|
+
if (!frame || !pickedInfo) return;
|
|
12778
12847
|
const id = Object.entries(store.get().frameEls).find(([, el]) => el === frame)?.[0];
|
|
12779
12848
|
if (id && store.get().selected !== id) store.set((state) => ({
|
|
12780
12849
|
...state,
|
|
12781
12850
|
selected: id
|
|
12782
12851
|
}));
|
|
12783
|
-
}, [
|
|
12852
|
+
}, [
|
|
12853
|
+
inspection.frame,
|
|
12854
|
+
pickedInfo,
|
|
12855
|
+
store
|
|
12856
|
+
]);
|
|
12784
12857
|
const order = useMemo(() => frameOrder(layout), [layout]);
|
|
12785
12858
|
const key = cameraKey(canvas.id, page?.id ?? "");
|
|
12786
12859
|
const placed = useRef(false);
|
|
@@ -12895,7 +12968,8 @@ function CanvasView({ canvas, page }) {
|
|
|
12895
12968
|
onEscape() {
|
|
12896
12969
|
store.set((state) => ({
|
|
12897
12970
|
...state,
|
|
12898
|
-
active: null
|
|
12971
|
+
active: null,
|
|
12972
|
+
selected: null
|
|
12899
12973
|
}));
|
|
12900
12974
|
}
|
|
12901
12975
|
}), [
|
|
@@ -12928,12 +13002,9 @@ function CanvasView({ canvas, page }) {
|
|
|
12928
13002
|
if (e.key === "Escape") {
|
|
12929
13003
|
if (inspection.info) inspection.select(null);
|
|
12930
13004
|
else if (inspectOn) setInspect(false);
|
|
12931
|
-
else if (state.active) store.set((s) => ({
|
|
12932
|
-
...s,
|
|
12933
|
-
active: null
|
|
12934
|
-
}));
|
|
12935
|
-
else if (state.selected) store.set((s) => ({
|
|
13005
|
+
else if (state.active || state.selected) store.set((s) => ({
|
|
12936
13006
|
...s,
|
|
13007
|
+
active: null,
|
|
12937
13008
|
selected: null
|
|
12938
13009
|
}));
|
|
12939
13010
|
} else if (e.key === "i" && !mod && !e.altKey) setInspect((value) => !value);
|
|
@@ -13045,7 +13116,13 @@ function CanvasView({ canvas, page }) {
|
|
|
13045
13116
|
capture: false,
|
|
13046
13117
|
apiRef,
|
|
13047
13118
|
onPlay: play,
|
|
13048
|
-
onSelect:
|
|
13119
|
+
onSelect: (id) => {
|
|
13120
|
+
if (!id) {
|
|
13121
|
+
inspection.select(null);
|
|
13122
|
+
setInspect(false);
|
|
13123
|
+
}
|
|
13124
|
+
select(id);
|
|
13125
|
+
}
|
|
13049
13126
|
}) : /* @__PURE__ */ jsx("div", {
|
|
13050
13127
|
className: "canvas-dots flex h-full",
|
|
13051
13128
|
children: /* @__PURE__ */ jsx(Notice, {
|
|
@@ -19094,6 +19171,155 @@ function Avatar({ src, name, size = 28, shape = "circle", className }) {
|
|
|
19094
19171
|
});
|
|
19095
19172
|
}
|
|
19096
19173
|
//#endregion
|
|
19174
|
+
//#region viewer/src/ui/combobox.tsx
|
|
19175
|
+
/**
|
|
19176
|
+
* One option out of many, in a field: it shows the picked one, typing narrows the list, arrows and
|
|
19177
|
+
* Enter pick without the mouse. The list keeps to a few rows and scrolls, however many there are.
|
|
19178
|
+
*/
|
|
19179
|
+
function Combobox({ options, value, onChange, placeholder, empty = "Nothing matches", className, "aria-label": label }) {
|
|
19180
|
+
const listId = useId();
|
|
19181
|
+
const anchor = useRef(null);
|
|
19182
|
+
const field = useRef(null);
|
|
19183
|
+
const list = useRef(null);
|
|
19184
|
+
const [open, setOpen] = useState(false);
|
|
19185
|
+
const [query, setQuery] = useState("");
|
|
19186
|
+
const [active, setActive] = useState(0);
|
|
19187
|
+
const picked = options.find((option) => option.value === value);
|
|
19188
|
+
const shown = useMemo(() => {
|
|
19189
|
+
const q = query.trim().toLowerCase();
|
|
19190
|
+
return q ? options.filter((option) => `${option.label} ${option.keywords ?? ""}`.toLowerCase().includes(q)) : options;
|
|
19191
|
+
}, [options, query]);
|
|
19192
|
+
const current = Math.min(active, shown.length - 1);
|
|
19193
|
+
const show = () => {
|
|
19194
|
+
setQuery("");
|
|
19195
|
+
setActive(Math.max(0, options.findIndex((option) => option.value === value)));
|
|
19196
|
+
setOpen(true);
|
|
19197
|
+
};
|
|
19198
|
+
const pick = (option) => {
|
|
19199
|
+
onChange(option.value);
|
|
19200
|
+
setOpen(false);
|
|
19201
|
+
setQuery("");
|
|
19202
|
+
};
|
|
19203
|
+
useEffect(() => {
|
|
19204
|
+
if (open) list.current?.querySelector(`[data-index="${current}"]`)?.scrollIntoView({ block: "nearest" });
|
|
19205
|
+
}, [open, current]);
|
|
19206
|
+
return /* @__PURE__ */ jsxs(Root2, {
|
|
19207
|
+
open,
|
|
19208
|
+
onOpenChange: setOpen,
|
|
19209
|
+
children: [/* @__PURE__ */ jsx(Anchor2, {
|
|
19210
|
+
asChild: true,
|
|
19211
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
19212
|
+
ref: anchor,
|
|
19213
|
+
onClick: () => {
|
|
19214
|
+
field.current?.focus();
|
|
19215
|
+
if (!open) show();
|
|
19216
|
+
},
|
|
19217
|
+
className: cn("flex h-ctrl w-full min-w-0 cursor-text items-center gap-2 rounded-[6px] border border-rule bg-surface pr-2 pl-2 text-ctrl transition-colors hover:border-rule-strong", "focus-within:outline-2 focus-within:outline-offset-2 focus-within:outline-action", className),
|
|
19218
|
+
children: [
|
|
19219
|
+
picked?.media && !query ? /* @__PURE__ */ jsx("span", {
|
|
19220
|
+
className: "flex shrink-0",
|
|
19221
|
+
children: picked.media
|
|
19222
|
+
}) : null,
|
|
19223
|
+
/* @__PURE__ */ jsx("input", {
|
|
19224
|
+
ref: field,
|
|
19225
|
+
value: open ? query : picked?.label ?? "",
|
|
19226
|
+
placeholder: open && picked ? picked.label : placeholder,
|
|
19227
|
+
autoComplete: "off",
|
|
19228
|
+
spellCheck: false,
|
|
19229
|
+
role: "combobox",
|
|
19230
|
+
"aria-label": label,
|
|
19231
|
+
"aria-expanded": open,
|
|
19232
|
+
"aria-controls": listId,
|
|
19233
|
+
"aria-autocomplete": "list",
|
|
19234
|
+
"aria-activedescendant": open && shown[current] ? `${listId}-${current}` : void 0,
|
|
19235
|
+
onChange: (event) => {
|
|
19236
|
+
setQuery(event.target.value);
|
|
19237
|
+
setActive(0);
|
|
19238
|
+
setOpen(true);
|
|
19239
|
+
},
|
|
19240
|
+
onKeyDown: (event) => {
|
|
19241
|
+
if (event.key === "ArrowDown" || event.key === "ArrowUp") {
|
|
19242
|
+
event.preventDefault();
|
|
19243
|
+
if (!open) return show();
|
|
19244
|
+
const step = event.key === "ArrowDown" ? 1 : -1;
|
|
19245
|
+
setActive((i) => Math.min(Math.max(i + step, 0), shown.length - 1));
|
|
19246
|
+
} else if (event.key === "Enter" && open && shown[current]) {
|
|
19247
|
+
event.preventDefault();
|
|
19248
|
+
pick(shown[current]);
|
|
19249
|
+
} else if (event.key === "Escape" && open) {
|
|
19250
|
+
event.preventDefault();
|
|
19251
|
+
event.stopPropagation();
|
|
19252
|
+
setOpen(false);
|
|
19253
|
+
} else if (event.key === "Tab") setOpen(false);
|
|
19254
|
+
},
|
|
19255
|
+
className: "h-full min-w-0 grow border-0 bg-transparent p-0 text-ink outline-none placeholder:text-muted"
|
|
19256
|
+
}),
|
|
19257
|
+
/* @__PURE__ */ jsx(Icon, {
|
|
19258
|
+
name: "chevron-down",
|
|
19259
|
+
size: 16,
|
|
19260
|
+
className: cn("shrink-0 text-muted transition-transform", open && "rotate-180")
|
|
19261
|
+
})
|
|
19262
|
+
]
|
|
19263
|
+
})
|
|
19264
|
+
}), /* @__PURE__ */ jsx(Portal, { children: /* @__PURE__ */ jsx(Content2, {
|
|
19265
|
+
side: "bottom",
|
|
19266
|
+
align: "start",
|
|
19267
|
+
sideOffset: 4,
|
|
19268
|
+
collisionPadding: 12,
|
|
19269
|
+
onOpenAutoFocus: (event) => event.preventDefault(),
|
|
19270
|
+
onCloseAutoFocus: (event) => event.preventDefault(),
|
|
19271
|
+
onInteractOutside: (event) => {
|
|
19272
|
+
if (anchor.current?.contains(event.target)) event.preventDefault();
|
|
19273
|
+
},
|
|
19274
|
+
className: cn(menuSurface, "max-h-[min(296px,var(--radix-popover-content-available-height))] overflow-y-auto"),
|
|
19275
|
+
style: { width: "var(--radix-popper-anchor-width)" },
|
|
19276
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
19277
|
+
ref: list,
|
|
19278
|
+
id: listId,
|
|
19279
|
+
role: "listbox",
|
|
19280
|
+
"aria-label": label,
|
|
19281
|
+
children: shown.length ? shown.map((option, index) => /* @__PURE__ */ jsxs("div", {
|
|
19282
|
+
id: `${listId}-${index}`,
|
|
19283
|
+
"data-index": index,
|
|
19284
|
+
role: "option",
|
|
19285
|
+
"aria-selected": option.value === value,
|
|
19286
|
+
tabIndex: -1,
|
|
19287
|
+
onMouseDown: (event) => event.preventDefault(),
|
|
19288
|
+
onMouseMove: () => index !== current && setActive(index),
|
|
19289
|
+
onClick: () => pick(option),
|
|
19290
|
+
className: cn("flex min-h-[44px] cursor-pointer items-center gap-2.5 px-2 py-1.5 text-[13.5px]", index === current && "bg-soft"),
|
|
19291
|
+
children: [
|
|
19292
|
+
option.media ? /* @__PURE__ */ jsx("span", {
|
|
19293
|
+
className: "flex shrink-0",
|
|
19294
|
+
children: option.media
|
|
19295
|
+
}) : null,
|
|
19296
|
+
/* @__PURE__ */ jsxs("span", {
|
|
19297
|
+
className: "flex min-w-0 grow flex-col gap-0.5",
|
|
19298
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
19299
|
+
className: "truncate font-medium text-ink",
|
|
19300
|
+
children: option.label
|
|
19301
|
+
}), option.sub ? /* @__PURE__ */ jsx("span", {
|
|
19302
|
+
className: "truncate text-[12px] text-muted",
|
|
19303
|
+
children: option.sub
|
|
19304
|
+
}) : null]
|
|
19305
|
+
}),
|
|
19306
|
+
/* @__PURE__ */ jsx("span", {
|
|
19307
|
+
className: cn("flex w-4 shrink-0 text-ink", option.value !== value && "invisible"),
|
|
19308
|
+
children: /* @__PURE__ */ jsx(Icon, {
|
|
19309
|
+
name: "check",
|
|
19310
|
+
size: 16
|
|
19311
|
+
})
|
|
19312
|
+
})
|
|
19313
|
+
]
|
|
19314
|
+
}, option.value)) : /* @__PURE__ */ jsx("div", {
|
|
19315
|
+
className: "px-3 py-2.5 text-[13px] text-muted",
|
|
19316
|
+
children: empty
|
|
19317
|
+
})
|
|
19318
|
+
})
|
|
19319
|
+
}) })]
|
|
19320
|
+
});
|
|
19321
|
+
}
|
|
19322
|
+
//#endregion
|
|
19097
19323
|
//#region viewer/src/ui/copy-button.tsx
|
|
19098
19324
|
/** A ghost "Copy" button that turns into "Copied" with a check for a moment after it copies. */
|
|
19099
19325
|
function CopyButton({ text, label = "Copy", done = "Copied", className }) {
|
|
@@ -19479,4 +19705,4 @@ function TextArea({ label, hint, error, className, id, disabled, rows = 4, ...re
|
|
|
19479
19705
|
});
|
|
19480
19706
|
}
|
|
19481
19707
|
//#endregion
|
|
19482
|
-
export { ApiError, Avatar, Badge, Bar, Button, ButtonAnchor, ButtonLink, Content, CopyButton, CornerPlate, Count, DesignViewer, Dialog, GroupRow, Icon, IconButton, KV, Kbd, Mark, Menu, MenuItem, MenuLabel, MenuSeparator, Meter, Mono, Muted, NavLabel, Notice, NoticeCard, PageHead, Panel, PanelBody, PanelFoot, PanelHead, PanelTabs, Row, RowLink, Segmented, Sheet, Skeleton, SkeletonRows, SlidePanel, Strip, SubNav, Switch, THead, TextArea, TextField, ThemeMenu, Toaster, Tooltip, TooltipProvider, Two, Wordmark, buttonClass, cn, copyText, floatingSurface, followLink, frameSrc, iconButtonClass, initials, listenToFrame, localSource, menuItemClass, menuSurface, resolveUrl, sendTheme, setThemePref, staticSource, toast, useBarCompact, useIsPhone, useTheme, useThemePref };
|
|
19708
|
+
export { ApiError, Avatar, Badge, Bar, Button, ButtonAnchor, ButtonLink, Combobox, Content, CopyButton, CornerPlate, Count, DesignViewer, Dialog, GroupRow, Icon, IconButton, KV, Kbd, Mark, Menu, MenuItem, MenuLabel, MenuSeparator, Meter, Mono, Muted, NavLabel, Notice, NoticeCard, PageHead, Panel, PanelBody, PanelFoot, PanelHead, PanelTabs, Row, RowLink, Segmented, Sheet, Skeleton, SkeletonRows, SlidePanel, Strip, SubNav, Switch, THead, TextArea, TextField, ThemeMenu, Toaster, Tooltip, TooltipProvider, Two, Wordmark, buttonClass, cn, copyText, floatingSurface, followLink, frameSrc, iconButtonClass, initials, listenToFrame, localSource, menuItemClass, menuSurface, resolveUrl, sendTheme, setThemePref, staticSource, toast, useBarCompact, useIsPhone, useTheme, useThemePref };
|
|
@@ -74,6 +74,7 @@
|
|
|
74
74
|
--animate-spin: spin 1s linear infinite;
|
|
75
75
|
--animate-pulse: pulse 2s cubic-bezier(.4, 0, .6, 1) infinite;
|
|
76
76
|
--blur-sm: 8px;
|
|
77
|
+
--blur-md: 12px;
|
|
77
78
|
--default-transition-duration: .15s;
|
|
78
79
|
--default-transition-timing-function: cubic-bezier(.4, 0, .2, 1);
|
|
79
80
|
--default-font-family: "IBM Plex Sans", system-ui, sans-serif;
|
|
@@ -417,6 +418,10 @@
|
|
|
417
418
|
pointer-events: none;
|
|
418
419
|
}
|
|
419
420
|
|
|
421
|
+
.invisible {
|
|
422
|
+
visibility: hidden;
|
|
423
|
+
}
|
|
424
|
+
|
|
420
425
|
.visible {
|
|
421
426
|
visibility: visible;
|
|
422
427
|
}
|
|
@@ -465,6 +470,10 @@
|
|
|
465
470
|
inset-inline: 0;
|
|
466
471
|
}
|
|
467
472
|
|
|
473
|
+
.inset-x-5 {
|
|
474
|
+
inset-inline: calc(var(--spacing) * 5);
|
|
475
|
+
}
|
|
476
|
+
|
|
468
477
|
.inset-x-6 {
|
|
469
478
|
inset-inline: calc(var(--spacing) * 6);
|
|
470
479
|
}
|
|
@@ -525,6 +534,10 @@
|
|
|
525
534
|
bottom: calc(var(--spacing) * 5);
|
|
526
535
|
}
|
|
527
536
|
|
|
537
|
+
.bottom-full {
|
|
538
|
+
bottom: 100%;
|
|
539
|
+
}
|
|
540
|
+
|
|
528
541
|
.left-0 {
|
|
529
542
|
left: 0;
|
|
530
543
|
}
|
|
@@ -894,6 +907,10 @@
|
|
|
894
907
|
max-height: min(56vh, 520px);
|
|
895
908
|
}
|
|
896
909
|
|
|
910
|
+
.max-h-\[min\(296px\,var\(--radix-popover-content-available-height\)\)\] {
|
|
911
|
+
max-height: min(296px, var(--radix-popover-content-available-height));
|
|
912
|
+
}
|
|
913
|
+
|
|
897
914
|
.max-h-\[min\(560px\,76vh\)\] {
|
|
898
915
|
max-height: min(560px, 76vh);
|
|
899
916
|
}
|
|
@@ -914,6 +931,10 @@
|
|
|
914
931
|
min-height: 38px;
|
|
915
932
|
}
|
|
916
933
|
|
|
934
|
+
.min-h-\[44px\] {
|
|
935
|
+
min-height: 44px;
|
|
936
|
+
}
|
|
937
|
+
|
|
917
938
|
.min-h-\[46px\] {
|
|
918
939
|
min-height: 46px;
|
|
919
940
|
}
|
|
@@ -940,6 +961,10 @@
|
|
|
940
961
|
}
|
|
941
962
|
}
|
|
942
963
|
|
|
964
|
+
.w-4 {
|
|
965
|
+
width: calc(var(--spacing) * 4);
|
|
966
|
+
}
|
|
967
|
+
|
|
943
968
|
.w-5 {
|
|
944
969
|
width: calc(var(--spacing) * 5);
|
|
945
970
|
}
|
|
@@ -1028,6 +1053,10 @@
|
|
|
1028
1053
|
max-width: 80%;
|
|
1029
1054
|
}
|
|
1030
1055
|
|
|
1056
|
+
.max-w-\[95\%\] {
|
|
1057
|
+
max-width: 95%;
|
|
1058
|
+
}
|
|
1059
|
+
|
|
1031
1060
|
.max-w-\[260px\] {
|
|
1032
1061
|
max-width: 260px;
|
|
1033
1062
|
}
|
|
@@ -1130,6 +1159,10 @@
|
|
|
1130
1159
|
translate: var(--tw-translate-x) var(--tw-translate-y);
|
|
1131
1160
|
}
|
|
1132
1161
|
|
|
1162
|
+
.rotate-180 {
|
|
1163
|
+
rotate: 180deg;
|
|
1164
|
+
}
|
|
1165
|
+
|
|
1133
1166
|
.transform {
|
|
1134
1167
|
transform: var(--tw-rotate-x, ) var(--tw-rotate-y, ) var(--tw-rotate-z, ) var(--tw-skew-x, ) var(--tw-skew-y, );
|
|
1135
1168
|
}
|
|
@@ -1138,10 +1171,6 @@
|
|
|
1138
1171
|
animation: .16s ease-out q-fade-in;
|
|
1139
1172
|
}
|
|
1140
1173
|
|
|
1141
|
-
.animate-\[q-pop_120ms_ease-out\] {
|
|
1142
|
-
animation: .12s ease-out q-pop;
|
|
1143
|
-
}
|
|
1144
|
-
|
|
1145
1174
|
.animate-pulse {
|
|
1146
1175
|
animation: var(--animate-pulse);
|
|
1147
1176
|
}
|
|
@@ -1170,6 +1199,10 @@
|
|
|
1170
1199
|
cursor: pointer;
|
|
1171
1200
|
}
|
|
1172
1201
|
|
|
1202
|
+
.cursor-text {
|
|
1203
|
+
cursor: text;
|
|
1204
|
+
}
|
|
1205
|
+
|
|
1173
1206
|
.touch-none {
|
|
1174
1207
|
touch-action: none;
|
|
1175
1208
|
}
|
|
@@ -1376,6 +1409,11 @@
|
|
|
1376
1409
|
border-radius: 3.40282e38px;
|
|
1377
1410
|
}
|
|
1378
1411
|
|
|
1412
|
+
.rounded-t-\[7px\] {
|
|
1413
|
+
border-top-left-radius: 7px;
|
|
1414
|
+
border-top-right-radius: 7px;
|
|
1415
|
+
}
|
|
1416
|
+
|
|
1379
1417
|
.rounded-t-\[14px\] {
|
|
1380
1418
|
border-top-left-radius: 14px;
|
|
1381
1419
|
border-top-right-radius: 14px;
|
|
@@ -1411,6 +1449,11 @@
|
|
|
1411
1449
|
border-bottom-width: 1px;
|
|
1412
1450
|
}
|
|
1413
1451
|
|
|
1452
|
+
.border-b-0 {
|
|
1453
|
+
border-bottom-style: var(--tw-border-style);
|
|
1454
|
+
border-bottom-width: 0;
|
|
1455
|
+
}
|
|
1456
|
+
|
|
1414
1457
|
.border-l {
|
|
1415
1458
|
border-left-style: var(--tw-border-style);
|
|
1416
1459
|
border-left-width: 1px;
|
|
@@ -1558,6 +1601,16 @@
|
|
|
1558
1601
|
}
|
|
1559
1602
|
}
|
|
1560
1603
|
|
|
1604
|
+
.bg-surface\/80 {
|
|
1605
|
+
background-color: var(--surface);
|
|
1606
|
+
}
|
|
1607
|
+
|
|
1608
|
+
@supports (color: color-mix(in lab, red, red)) {
|
|
1609
|
+
.bg-surface\/80 {
|
|
1610
|
+
background-color: color-mix(in oklab, var(--surface) 80%, transparent);
|
|
1611
|
+
}
|
|
1612
|
+
}
|
|
1613
|
+
|
|
1561
1614
|
.bg-surface\/90 {
|
|
1562
1615
|
background-color: var(--surface);
|
|
1563
1616
|
}
|
|
@@ -2186,6 +2239,12 @@
|
|
|
2186
2239
|
filter: var(--tw-blur, ) var(--tw-brightness, ) var(--tw-contrast, ) var(--tw-grayscale, ) var(--tw-hue-rotate, ) var(--tw-invert, ) var(--tw-saturate, ) var(--tw-sepia, ) var(--tw-drop-shadow, );
|
|
2187
2240
|
}
|
|
2188
2241
|
|
|
2242
|
+
.backdrop-blur-md {
|
|
2243
|
+
--tw-backdrop-blur: blur(var(--blur-md));
|
|
2244
|
+
-webkit-backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
|
|
2245
|
+
backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
|
|
2246
|
+
}
|
|
2247
|
+
|
|
2189
2248
|
.backdrop-blur-sm {
|
|
2190
2249
|
--tw-backdrop-blur: blur(var(--blur-sm));
|
|
2191
2250
|
-webkit-backdrop-filter: var(--tw-backdrop-blur, ) var(--tw-backdrop-brightness, ) var(--tw-backdrop-contrast, ) var(--tw-backdrop-grayscale, ) var(--tw-backdrop-hue-rotate, ) var(--tw-backdrop-invert, ) var(--tw-backdrop-opacity, ) var(--tw-backdrop-saturate, ) var(--tw-backdrop-sepia, );
|
|
@@ -2512,6 +2571,10 @@
|
|
|
2512
2571
|
flex-wrap: wrap;
|
|
2513
2572
|
}
|
|
2514
2573
|
}
|
|
2574
|
+
|
|
2575
|
+
.\[\&\>\:not\(\:first-child\)\]\:shrink-0 > :not(:first-child) {
|
|
2576
|
+
flex-shrink: 0;
|
|
2577
|
+
}
|
|
2515
2578
|
}
|
|
2516
2579
|
|
|
2517
2580
|
@font-face {
|
|
@@ -3082,9 +3145,9 @@
|
|
|
3082
3145
|
}
|
|
3083
3146
|
|
|
3084
3147
|
.canvas-overlay .section-title {
|
|
3148
|
+
translate: 0 max(-100%, min(0px, calc(var(--body) * var(--z) * 1px - 44px)));
|
|
3085
3149
|
padding-bottom: 8px;
|
|
3086
3150
|
display: none;
|
|
3087
|
-
translate: 0 -100%;
|
|
3088
3151
|
}
|
|
3089
3152
|
|
|
3090
3153
|
.canvas-overlay[data-titles="on"] .section-title {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { CanvasItem } from '../../../src/shared/types';
|
|
1
2
|
import { type ReactNode } from 'react';
|
|
2
3
|
import type { ViewerSource } from './source';
|
|
3
4
|
/** Places where an app that embeds the viewer adds its own controls. */
|
|
@@ -28,6 +29,8 @@ export interface ViewerSlots {
|
|
|
28
29
|
canvasesAfter?: ReactNode;
|
|
29
30
|
/** Below the panels of the home page, full width. */
|
|
30
31
|
homeAfter?: ReactNode;
|
|
32
|
+
/** In the bar of the item selected on a canvas, before the way to zoom to it: sharing that screen, say. */
|
|
33
|
+
selectionActions?: (canvasId: string, item: CanvasItem) => ReactNode;
|
|
31
34
|
/**
|
|
32
35
|
* On a screen's full-window page, the corner plate with the way out: `note` is a muted line under it
|
|
33
36
|
* (whose content the screen is), `actions` sit next to the way out, and with `badge` the plate folds
|
|
@@ -16,6 +16,7 @@ export { Avatar, initials } from './ui/avatar';
|
|
|
16
16
|
export { Badge, Count, type Tone } from './ui/badge';
|
|
17
17
|
export { Button, ButtonAnchor, type ButtonKind, ButtonLink, type ButtonProps, buttonClass, IconButton, type IconButtonProps, iconButtonClass, } from './ui/button';
|
|
18
18
|
export { Segmented, Switch } from './ui/choice';
|
|
19
|
+
export { Combobox, type ComboboxOption } from './ui/combobox';
|
|
19
20
|
export { CopyButton } from './ui/copy-button';
|
|
20
21
|
export { Dialog } from './ui/dialog';
|
|
21
22
|
export { Icon, type IconName } from './ui/icon';
|