@cueplusplus/ui 0.11.0 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +251 -0
- package/dist/elements/scroll-anchor.js +4 -2
- package/dist/index.d.ts +4 -2
- package/dist/index.js +2 -1
- package/dist/layout/_ground.d.ts +22 -0
- package/dist/layout/_ground.js +9 -0
- package/dist/layout/bento.js +1 -1
- package/dist/layout/frames.d.ts +70 -0
- package/dist/layout/frames.js +298 -0
- package/dist/layout/index.d.ts +4 -2
- package/dist/layout/index.js +2 -1
- package/dist/layout/preview.d.ts +50 -3
- package/dist/layout/preview.js +179 -31
- package/dist/overlays/drawer.js +1 -1
- package/manifest/components/activity-graph.json +2 -1
- package/manifest/components/agent-card.json +2 -1
- package/manifest/components/agent-pile.json +2 -1
- package/manifest/components/background-inbox.json +2 -1
- package/manifest/components/bento.json +1 -1
- package/manifest/components/breadcrumb.json +2 -1
- package/manifest/components/chart-tooltip-content.json +2 -1
- package/manifest/components/checkpoint-history.json +2 -1
- package/manifest/components/code-diff.json +2 -1
- package/manifest/components/combobox.json +2 -1
- package/manifest/components/comparison-card.json +2 -1
- package/manifest/components/composer-attachment-chip.json +2 -1
- package/manifest/components/composer-context.json +2 -1
- package/manifest/components/composer-model-item.json +2 -1
- package/manifest/components/composer-person-item.json +2 -1
- package/manifest/components/computer-use.json +2 -1
- package/manifest/components/confidence-marker.json +2 -1
- package/manifest/components/context-breakdown.json +2 -1
- package/manifest/components/context-usage.json +2 -1
- package/manifest/components/conversation-search.json +2 -1
- package/manifest/components/cost-meter.json +2 -1
- package/manifest/components/day-separator.json +2 -1
- package/manifest/components/document-reference.json +2 -1
- package/manifest/components/elements-command-palette.json +2 -1
- package/manifest/components/elements-timeline.json +2 -1
- package/manifest/components/elicitation-form.json +2 -1
- package/manifest/components/file-tree.json +2 -1
- package/manifest/components/flow-graph.json +4 -2
- package/manifest/components/frac.json +1 -1
- package/manifest/components/frames.json +210 -0
- package/manifest/components/group-bar.json +2 -1
- package/manifest/components/inline-citation.json +2 -1
- package/manifest/components/job-progress.json +2 -1
- package/manifest/components/log-viewer.json +2 -1
- package/manifest/components/map-answer.json +2 -1
- package/manifest/components/math-block.json +1 -1
- package/manifest/components/mcp-server-panel.json +2 -1
- package/manifest/components/memory-chips.json +2 -1
- package/manifest/components/message-actions.json +2 -1
- package/manifest/components/message-attachments.json +2 -1
- package/manifest/components/message-queue.json +2 -1
- package/manifest/components/message-timing.json +2 -1
- package/manifest/components/meter.json +1 -1
- package/manifest/components/model-picker.json +2 -1
- package/manifest/components/multi-select.json +2 -1
- package/manifest/components/onboarding.json +2 -1
- package/manifest/components/preview.json +85 -8
- package/manifest/components/prompt-library.json +2 -1
- package/manifest/components/queue-dock.json +2 -1
- package/manifest/components/quote-reply.json +2 -1
- package/manifest/components/reasoning-effort.json +2 -1
- package/manifest/components/reasoning-panel.json +2 -1
- package/manifest/components/regenerate-menu.json +2 -1
- package/manifest/components/research-report.json +2 -1
- package/manifest/components/retrieval-chunks.json +2 -1
- package/manifest/components/reviewable-diff.json +2 -1
- package/manifest/components/schedule-card.json +2 -1
- package/manifest/components/score-breakdown.json +2 -1
- package/manifest/components/scroll-anchor.json +2 -1
- package/manifest/components/segmented-control.json +2 -1
- package/manifest/components/settings-panel.json +2 -1
- package/manifest/components/shared-conversation.json +2 -1
- package/manifest/components/sources.json +2 -1
- package/manifest/components/speaker-identity.json +2 -1
- package/manifest/components/spec-sheet.json +2 -1
- package/manifest/components/spectrum-visualizer.json +2 -1
- package/manifest/components/stepper.json +2 -1
- package/manifest/components/streaming-text.json +2 -1
- package/manifest/components/sub.json +1 -1
- package/manifest/components/subagent-list.json +4 -2
- package/manifest/components/sup.json +1 -1
- package/manifest/components/swap-label.json +2 -1
- package/manifest/components/thread-list.json +2 -1
- package/manifest/components/thread-search.json +2 -1
- package/manifest/components/todo-list.json +2 -1
- package/manifest/components/tool-group.json +2 -1
- package/manifest/components/trace-waterfall.json +2 -1
- package/manifest/components/tree.json +2 -1
- package/manifest/components/universe-grid.json +2 -1
- package/manifest/components/usage-chart.json +2 -1
- package/manifest/components/voice-conversation.json +2 -1
- package/manifest/components/web-search.json +2 -1
- package/manifest/fixtures.json +665 -0
- package/manifest/manifest.json +97 -84
- package/manifest/tokens.json +1 -1
- package/package.json +5 -5
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { cn } from "../lib/cn.js";
|
|
3
|
+
import { GROUND_CLASSES } from "./_ground.js";
|
|
4
|
+
import * as React from "react";
|
|
5
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
+
//#region src/layout/frames.tsx
|
|
7
|
+
/** One arrow press where nothing on the page has declared the space ladder's top rung. */
|
|
8
|
+
const STEP_FALLBACK = 32;
|
|
9
|
+
/** What a rem is worth where no document can be asked — `use-density.ts`'s own assumption. */
|
|
10
|
+
const ASSUMED_ROOT_FONT_SIZE = 16;
|
|
11
|
+
/** The root's font size, for a rung declared in rem. */
|
|
12
|
+
function rootFontSize() {
|
|
13
|
+
if (typeof document === "undefined") return ASSUMED_ROOT_FONT_SIZE;
|
|
14
|
+
const size = Number.parseFloat(getComputedStyle(document.documentElement).fontSize);
|
|
15
|
+
return Number.isFinite(size) && size > 0 ? size : ASSUMED_ROOT_FONT_SIZE;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* One rung of `--cue-space-8` in CSS pixels, read off the canvas itself.
|
|
19
|
+
*
|
|
20
|
+
* Off the canvas and not off the root, because the rung is a density token and
|
|
21
|
+
* a canvas may sit inside a `<Density>` island — a compact board steps by a
|
|
22
|
+
* compact rung, which is the whole point of spending a token instead of a
|
|
23
|
+
* number. Read at the keypress rather than cached: the density under it can
|
|
24
|
+
* change between two presses and nothing re-renders when it does.
|
|
25
|
+
*
|
|
26
|
+
* `null` is not a return value here. A page that declared nothing — a consumer
|
|
27
|
+
* who imported no stylesheet, a server's first paint, jsdom — still has to move
|
|
28
|
+
* when a reader presses an arrow, so there is a fallback and it is a number
|
|
29
|
+
* this file owns.
|
|
30
|
+
*/
|
|
31
|
+
function rungOf(canvas) {
|
|
32
|
+
if (typeof window === "undefined") return STEP_FALLBACK;
|
|
33
|
+
const declared = window.getComputedStyle(canvas).getPropertyValue("--cue-space-8").trim();
|
|
34
|
+
const length = Number.parseFloat(declared);
|
|
35
|
+
if (!Number.isFinite(length) || length <= 0) return STEP_FALLBACK;
|
|
36
|
+
return declared.endsWith("rem") ? length * rootFontSize() : length;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Where a drag may not start: the elements whose whole job is to be pressed.
|
|
40
|
+
*
|
|
41
|
+
* Matched with `closest` and not on the target alone, because a control in this
|
|
42
|
+
* house is usually a box drawn round something else — an icon, a span, a label.
|
|
43
|
+
* A drag that starts on the icon started on the button, and a pan that began
|
|
44
|
+
* there would take the pointer capture with it and the press would never land.
|
|
45
|
+
*
|
|
46
|
+
* **The `[role=…]` half is the same sentence about controls this library draws
|
|
47
|
+
* out of a `div`.** A `DropdownMenu.Item` is a `<div role="menuitem">` whose
|
|
48
|
+
* label is a `<span>` inside it; an `option`, a `tab`, a `treeitem` are all that
|
|
49
|
+
* shape. Without them here a reader who clicked a menu row *on its words* had
|
|
50
|
+
* the canvas take the pointer capture and the `click` retargeted away — the row
|
|
51
|
+
* worked from the keyboard and worked on its padding, and did nothing where the
|
|
52
|
+
* text was. That was reported against the frame name menu and is a defect of
|
|
53
|
+
* this predicate rather than of that menu.
|
|
54
|
+
*
|
|
55
|
+
* The list is ARIA's **standalone widget roles** — the ones that *are* a control
|
|
56
|
+
* rather than a box holding controls, so a composite (`menu`, `listbox`,
|
|
57
|
+
* `tablist`, `tree`, `radiogroup`, `toolbar`, `grid`) is deliberately absent:
|
|
58
|
+
* those are chrome, and a drag on a menu's own padding is a pan. Three
|
|
59
|
+
* standalone ones are absent too, each for its own reason — `progressbar` is
|
|
60
|
+
* read and never operated, `tabpanel` is the content a `tab` switches to rather
|
|
61
|
+
* than the thing pressed, and `gridcell` is a box holding content, so a drag
|
|
62
|
+
* across a table inside a frame stays a pan.
|
|
63
|
+
*
|
|
64
|
+
* An allowlist and not a denylist of container roles, because the two fail in
|
|
65
|
+
* opposite directions: a role missing from this list leaves the old behaviour
|
|
66
|
+
* (the element itself is still matched by {@link ROLE_BEARING}), while a
|
|
67
|
+
* container role missing from a denylist would silently stop the board panning.
|
|
68
|
+
*/
|
|
69
|
+
const CONTROLS = "button, a, input, select, textarea, [role=button], [role=checkbox], [role=link], [role=menuitem], [role=menuitemcheckbox], [role=menuitemradio], [role=option], [role=radio], [role=scrollbar], [role=searchbox], [role=separator], [role=slider], [role=spinbutton], [role=switch], [role=tab], [role=textbox], [role=treeitem]";
|
|
70
|
+
/**
|
|
71
|
+
* And the element directly under the pointer, if it bears a role of its own.
|
|
72
|
+
*
|
|
73
|
+
* On the target alone — `matches` and never `closest` — and that is the whole
|
|
74
|
+
* difference between a canvas that pans and one that only offers to. A
|
|
75
|
+
* `Preview` in its frame presentation is a `role="group"` and this canvas is a
|
|
76
|
+
* `role="region"`, so nearly every point on a board has a role-bearing
|
|
77
|
+
* ancestor. A board is mostly frames, and "drag to pan" that worked only in the
|
|
78
|
+
* gaps between them would be a hint that lies. So a role-bearing *ancestor* is
|
|
79
|
+
* a frame's chrome and a drag there is a pan; only a role-bearing element under
|
|
80
|
+
* the pointer itself is something to press rather than something to grab.
|
|
81
|
+
*
|
|
82
|
+
* That is still true, and it is not the whole rule: the ancestors that are
|
|
83
|
+
* *controls* rather than chrome are named in {@link CONTROLS} and matched with
|
|
84
|
+
* `closest` there. This line stays `matches` for everything else, which is what
|
|
85
|
+
* keeps a `role="group"` frame a thing to grab.
|
|
86
|
+
*/
|
|
87
|
+
const ROLE_BEARING = "[role]";
|
|
88
|
+
/** Whether a pointer that went down here is pressing something rather than grabbing the board. */
|
|
89
|
+
function isControl(target, canvas) {
|
|
90
|
+
if (target === canvas) return false;
|
|
91
|
+
return target.closest(CONTROLS) !== null || target.matches(ROLE_BEARING);
|
|
92
|
+
}
|
|
93
|
+
/** Static class per height, off the two the spec measured. Tailwind scans text. */
|
|
94
|
+
const HEIGHT_CLASSES = {
|
|
95
|
+
short: "h-[18.5rem]",
|
|
96
|
+
tall: "h-[27rem]"
|
|
97
|
+
};
|
|
98
|
+
/**
|
|
99
|
+
* The box: the height, the ground, the border, and the positioning context the
|
|
100
|
+
* hint needs.
|
|
101
|
+
*
|
|
102
|
+
* Two elements and not one, because the hint has to stay in the corner while
|
|
103
|
+
* the frames move under it. A hint absolutely positioned inside the scroller
|
|
104
|
+
* would slide away with the first pan; one positioned against a box the
|
|
105
|
+
* scroller fills stays where a reader left it. The ground is on the box for the
|
|
106
|
+
* same reason — a board's grid does not move with its art.
|
|
107
|
+
*/
|
|
108
|
+
const ROOT_CLASS = "relative min-w-0 overflow-hidden rounded-(--radius-surface) border border-border";
|
|
109
|
+
/**
|
|
110
|
+
* The scroller: a row of frames, sideways only, with a rung of the space
|
|
111
|
+
* ladder's top between them.
|
|
112
|
+
*
|
|
113
|
+
* `overflow-y: hidden` is the design and not an oversight — the board is "not
|
|
114
|
+
* very high, not full screen", and a canvas that scrolled both ways would be a
|
|
115
|
+
* viewport a reader can get lost in. `scroll-smooth` pairs with
|
|
116
|
+
* `motion-reduce:scroll-auto` so the preference is honoured declaratively;
|
|
117
|
+
* there is no frame loop here for `reduced-motion.test.ts` to find, and there
|
|
118
|
+
* must not be.
|
|
119
|
+
*/
|
|
120
|
+
const CANVAS_CLASS = "flex h-full min-w-0 items-start gap-(--cue-space-8) overflow-x-auto overflow-y-hidden scroll-smooth p-(--cue-space-6) outline-none motion-reduce:scroll-auto focus-visible:outline-2 focus-visible:outline-solid focus-visible:-outline-offset-2 focus-visible:outline-accent";
|
|
121
|
+
/** The affordance, and only where there is something to afford. */
|
|
122
|
+
const PANNABLE_CLASS = "cursor-grab";
|
|
123
|
+
/**
|
|
124
|
+
* While panning: the grabbing cursor, no text selection, and **no smooth
|
|
125
|
+
* scrolling**. `scroll-behavior: smooth` animates every `scrollLeft` write, and
|
|
126
|
+
* a drag writes one per pointer move — the canvas would lag the pointer by a
|
|
127
|
+
* whole animation. `twMerge` resolves this against `scroll-smooth` above,
|
|
128
|
+
* last one wins.
|
|
129
|
+
*/
|
|
130
|
+
const PANNING_CLASS = "cursor-grabbing scroll-auto select-none";
|
|
131
|
+
/** The line in the corner. `pointer-events-none`, or it would swallow the drag it describes. */
|
|
132
|
+
const HINT_CLASS = "pointer-events-none absolute right-(--cue-space-4) bottom-(--cue-space-3) z-10 font-mono text-(length:--cue-text-micro) text-fg-subtle";
|
|
133
|
+
/**
|
|
134
|
+
* The canvas: a short, wide, focusable scroll region that holds frames.
|
|
135
|
+
*
|
|
136
|
+
* **It knows nothing about its children.** It does not count them, index them
|
|
137
|
+
* or select one — a canvas that knew its frames would be a manifest API, and
|
|
138
|
+
* this is a slot API. `hint` is where a caller puts the count it knows and this
|
|
139
|
+
* does not.
|
|
140
|
+
*
|
|
141
|
+
* @example
|
|
142
|
+
* <Frames.Root label="Button frames" hint="drag to pan · 8 frames">
|
|
143
|
+
* <Preview presentation="frame" label="Tone" count={4}>…</Preview>
|
|
144
|
+
* </Frames.Root>
|
|
145
|
+
*/
|
|
146
|
+
const FramesRoot = React.forwardRef(function FramesRoot({ children, label, height = "short", ground = "dots", hint, pan = true, className, ...elementProps }, ref) {
|
|
147
|
+
const drag = React.useRef(null);
|
|
148
|
+
const canvasRef = React.useRef(null);
|
|
149
|
+
const [panning, setPanning] = React.useState(false);
|
|
150
|
+
React.useEffect(() => {
|
|
151
|
+
if (pan) return;
|
|
152
|
+
const started = drag.current;
|
|
153
|
+
if (started === null) return;
|
|
154
|
+
canvasRef.current?.releasePointerCapture?.(started.id);
|
|
155
|
+
drag.current = null;
|
|
156
|
+
setPanning(false);
|
|
157
|
+
}, [pan]);
|
|
158
|
+
const scroll = (event) => {
|
|
159
|
+
if (event.defaultPrevented || event.target !== event.currentTarget) return;
|
|
160
|
+
const canvas = event.currentTarget;
|
|
161
|
+
let next = null;
|
|
162
|
+
if (event.key === "ArrowRight") next = canvas.scrollLeft + rungOf(canvas);
|
|
163
|
+
else if (event.key === "ArrowLeft") next = canvas.scrollLeft - rungOf(canvas);
|
|
164
|
+
else if (event.key === "PageDown") next = canvas.scrollLeft + canvas.clientWidth;
|
|
165
|
+
else if (event.key === "PageUp") next = canvas.scrollLeft - canvas.clientWidth;
|
|
166
|
+
else if (event.key === "Home") next = 0;
|
|
167
|
+
else if (event.key === "End") next = canvas.scrollWidth;
|
|
168
|
+
if (next === null) return;
|
|
169
|
+
event.preventDefault();
|
|
170
|
+
canvas.scrollLeft = Math.max(0, next);
|
|
171
|
+
};
|
|
172
|
+
const pointer = {
|
|
173
|
+
onPointerDown: (event) => {
|
|
174
|
+
if (event.button !== 0) return;
|
|
175
|
+
const canvas = event.currentTarget;
|
|
176
|
+
const target = event.target;
|
|
177
|
+
if (target !== null && isControl(target, canvas)) return;
|
|
178
|
+
canvas.setPointerCapture?.(event.pointerId);
|
|
179
|
+
drag.current = {
|
|
180
|
+
x: event.clientX,
|
|
181
|
+
left: canvas.scrollLeft,
|
|
182
|
+
id: event.pointerId
|
|
183
|
+
};
|
|
184
|
+
setPanning(true);
|
|
185
|
+
},
|
|
186
|
+
onPointerMove: (event) => {
|
|
187
|
+
const started = drag.current;
|
|
188
|
+
if (started === null) return;
|
|
189
|
+
event.currentTarget.scrollLeft = Math.max(0, started.left - (event.clientX - started.x));
|
|
190
|
+
},
|
|
191
|
+
onPointerUp: (event) => {
|
|
192
|
+
if (drag.current === null) return;
|
|
193
|
+
event.currentTarget.releasePointerCapture?.(event.pointerId);
|
|
194
|
+
drag.current = null;
|
|
195
|
+
setPanning(false);
|
|
196
|
+
},
|
|
197
|
+
onPointerCancel: () => {
|
|
198
|
+
drag.current = null;
|
|
199
|
+
setPanning(false);
|
|
200
|
+
}
|
|
201
|
+
};
|
|
202
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
203
|
+
...elementProps,
|
|
204
|
+
ref,
|
|
205
|
+
"data-slot": "frames",
|
|
206
|
+
className: cn(ROOT_CLASS, HEIGHT_CLASSES[height], GROUND_CLASSES[ground], className),
|
|
207
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
208
|
+
ref: canvasRef,
|
|
209
|
+
role: "region",
|
|
210
|
+
tabIndex: 0,
|
|
211
|
+
"aria-label": label,
|
|
212
|
+
"data-slot": "frames-canvas",
|
|
213
|
+
"data-panning": panning ? "true" : void 0,
|
|
214
|
+
className: cn(CANVAS_CLASS, pan && PANNABLE_CLASS, panning && PANNING_CLASS),
|
|
215
|
+
onKeyDown: scroll,
|
|
216
|
+
...pan ? pointer : {},
|
|
217
|
+
children
|
|
218
|
+
}), hint === void 0 ? null : /* @__PURE__ */ jsx("span", {
|
|
219
|
+
"data-slot": "frames-hint",
|
|
220
|
+
className: HINT_CLASS,
|
|
221
|
+
children: hint
|
|
222
|
+
})]
|
|
223
|
+
});
|
|
224
|
+
});
|
|
225
|
+
/** One cell: the specimen, and the line under it. */
|
|
226
|
+
const ITEM_CLASS = "flex min-w-0 shrink-0 flex-col items-center gap-(--cue-space-2) rounded-(--radius-control) p-(--cue-space-2)";
|
|
227
|
+
/** The one a reader is inspecting. An outline and not a border: a border would move the cell. */
|
|
228
|
+
const ITEM_SELECTED_CLASS = "outline-2 outline-solid -outline-offset-1 outline-accent";
|
|
229
|
+
const ITEM_BODY_CLASS = "flex min-w-0 items-center justify-center";
|
|
230
|
+
/**
|
|
231
|
+
* The caption, and the two properties that decide whether it is painted.
|
|
232
|
+
*
|
|
233
|
+
* Properties and not props threaded down from the frame: the switch belongs to
|
|
234
|
+
* the frame — a reader turns captions off for a whole frame from its settings
|
|
235
|
+
* popover, never for one item — and a property is how a switch reaches every
|
|
236
|
+
* descendant without every descendant declaring it.
|
|
237
|
+
*
|
|
238
|
+
* **`opacity`, never `visibility`.** Zero opacity keeps the box *and* keeps the
|
|
239
|
+
* node in the accessibility tree, which is exactly what §4.1 Decision 4
|
|
240
|
+
* refuses to give up; `visibility: hidden` would keep the box and drop the
|
|
241
|
+
* node. `pointer-events` rides with it so an unpainted caption cannot be
|
|
242
|
+
* clicked or dragged over — two properties because `opacity` wants a number
|
|
243
|
+
* and `pointer-events` wants a keyword, and a custom property is untyped text
|
|
244
|
+
* that cannot be both.
|
|
245
|
+
*
|
|
246
|
+
* The **fallbacks** are what make an item legal outside a Preview: nothing
|
|
247
|
+
* declares either property there, so the caption resolves to `1` and `auto` and
|
|
248
|
+
* behaves like any other line, rather than inheriting the empty string and
|
|
249
|
+
* vanishing.
|
|
250
|
+
*/
|
|
251
|
+
const ITEM_CAPTION_CLASS = "min-w-0 truncate text-center font-mono text-(length:--cue-text-micro) text-fg-subtle [opacity:var(--preview-captions,1)] [pointer-events:var(--preview-captions-pe,auto)]";
|
|
252
|
+
/**
|
|
253
|
+
* A design canvas: frames side by side, each holding one axis of one component.
|
|
254
|
+
*
|
|
255
|
+
* `Frames.Root` is the canvas — short, wide, scrollable sideways, focusable,
|
|
256
|
+
* and pannable with the pointer. `Frames.Item` is one captioned cell, and it is
|
|
257
|
+
* used **inside a `Preview`** rather than inside the Root. The two are apart
|
|
258
|
+
* because that is how they are used, and a props-only API cannot say it.
|
|
259
|
+
*
|
|
260
|
+
* **The canvas knows nothing about its children.** It does not count them, does
|
|
261
|
+
* not index them and does not select one; `hint` is where a caller puts what it
|
|
262
|
+
* knows. A canvas that knew its frames would be a manifest API, and this is a
|
|
263
|
+
* slot API.
|
|
264
|
+
*
|
|
265
|
+
* @example
|
|
266
|
+
* <Frames.Root label="Button frames" hint="drag to pan · 3 frames">
|
|
267
|
+
* <Preview presentation="frame" label="Tone" count={3} name={<ToneMenu />}>
|
|
268
|
+
* <div className="flex flex-wrap items-end gap-(--cue-space-6)">
|
|
269
|
+
* <Frames.Item caption="accent"><Button tone="accent">Take cue</Button></Frames.Item>
|
|
270
|
+
* <Frames.Item caption="ok"><Button tone="ok">Take cue</Button></Frames.Item>
|
|
271
|
+
* <Frames.Item caption="warn"><Button tone="warn">Take cue</Button></Frames.Item>
|
|
272
|
+
* </div>
|
|
273
|
+
* </Preview>
|
|
274
|
+
* </Frames.Root>
|
|
275
|
+
*/
|
|
276
|
+
const Frames = {
|
|
277
|
+
Root: FramesRoot,
|
|
278
|
+
Item: React.forwardRef(function FramesItem({ children, caption, selected = false, className, ...elementProps }, ref) {
|
|
279
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
280
|
+
...elementProps,
|
|
281
|
+
ref,
|
|
282
|
+
"data-slot": "frames-item",
|
|
283
|
+
"data-selected": selected ? "true" : void 0,
|
|
284
|
+
className: cn(ITEM_CLASS, selected && ITEM_SELECTED_CLASS, className),
|
|
285
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
286
|
+
"data-slot": "frames-item-body",
|
|
287
|
+
className: ITEM_BODY_CLASS,
|
|
288
|
+
children
|
|
289
|
+
}), caption === void 0 ? null : /* @__PURE__ */ jsx("span", {
|
|
290
|
+
"data-slot": "frames-item-caption",
|
|
291
|
+
className: ITEM_CAPTION_CLASS,
|
|
292
|
+
children: caption
|
|
293
|
+
})]
|
|
294
|
+
});
|
|
295
|
+
})
|
|
296
|
+
};
|
|
297
|
+
//#endregion
|
|
298
|
+
export { Frames };
|
package/dist/layout/index.d.ts
CHANGED
|
@@ -8,10 +8,12 @@ import { Breadcrumb, BreadcrumbItem, BreadcrumbProps } from "./breadcrumb.js";
|
|
|
8
8
|
import { Card, CardContentProps, CardDescriptionProps, CardFooterProps, CardHeaderProps, CardRootProps, CardTitleProps } from "./card.js";
|
|
9
9
|
import { Collapsible, CollapsiblePanelProps, CollapsibleRootProps, CollapsibleTriggerProps, Disclosure, DisclosureProps } from "./collapsible.js";
|
|
10
10
|
import { DescriptionList, DescriptionListDetailProps, DescriptionListLayout, DescriptionListRootProps, DescriptionListTermProps } from "./description-list.js";
|
|
11
|
+
import { PreviewGround } from "./_ground.js";
|
|
12
|
+
import { Frames, FramesHeight, FramesItemProps, FramesRootProps } from "./frames.js";
|
|
11
13
|
import { Grid, GridColumns, GridProps } from "./grid.js";
|
|
12
14
|
import { Item, ItemProps, itemVariants } from "./item.js";
|
|
13
15
|
import { Pagination, PaginationEntry, PaginationProps, paginationRange } from "./pagination.js";
|
|
14
|
-
import { Preview, PreviewAxis, PreviewProps, PreviewResizeOptions } from "./preview.js";
|
|
16
|
+
import { Preview, PreviewAxis, PreviewPresentation, PreviewProps, PreviewResizeOptions } from "./preview.js";
|
|
15
17
|
import { Stepper, StepperProps, StepperState, StepperStep } from "./stepper.js";
|
|
16
18
|
import { Timeline, TimelineContentProps, TimelineItemProps, TimelineMarkerProps, TimelineRootProps } from "./timeline.js";
|
|
17
|
-
export { Accordion, type AccordionHeaderProps, type AccordionItemProps, type AccordionPanelProps, type AccordionRootProps, type AccordionTriggerProps, Bento, type BentoColumns, type BentoMinHeight, type BentoRootProps, type BentoRowSpan, type BentoRows, type BentoSpan, type BentoTileProps, Breadcrumb, type BreadcrumbItem, type BreadcrumbProps, Card, type CardContentProps, type CardDescriptionProps, type CardFooterProps, type CardHeaderProps, type CardRootProps, type CardTitleProps, Collapsible, type CollapsiblePanelProps, type CollapsibleRootProps, type CollapsibleTriggerProps, Container, type ContainerProps, type ContainerWidth, DescriptionList, type DescriptionListDetailProps, type DescriptionListLayout, type DescriptionListRootProps, type DescriptionListTermProps, Disclosure, type DisclosureProps, Grid, type GridColumns, type GridProps, Item, type ItemProps, Link, type LinkProps, Pagination, type PaginationEntry, type PaginationProps, Preview, type PreviewAxis, type PreviewProps, type PreviewResizeOptions, Sidebar, type SidebarItemProps, type SidebarRailProps, type SidebarRootProps, type SidebarSectionProps, type SpaceStep, Stack, type StackAlign, type StackJustify, type StackProps, Stepper, type StepperProps, type StepperState, type StepperStep, Timeline, type TimelineContentProps, type TimelineItemProps, type TimelineMarkerProps, type TimelineRootProps, itemVariants, linkVariants, paginationRange, useSidebar };
|
|
19
|
+
export { Accordion, type AccordionHeaderProps, type AccordionItemProps, type AccordionPanelProps, type AccordionRootProps, type AccordionTriggerProps, Bento, type BentoColumns, type BentoMinHeight, type BentoRootProps, type BentoRowSpan, type BentoRows, type BentoSpan, type BentoTileProps, Breadcrumb, type BreadcrumbItem, type BreadcrumbProps, Card, type CardContentProps, type CardDescriptionProps, type CardFooterProps, type CardHeaderProps, type CardRootProps, type CardTitleProps, Collapsible, type CollapsiblePanelProps, type CollapsibleRootProps, type CollapsibleTriggerProps, Container, type ContainerProps, type ContainerWidth, DescriptionList, type DescriptionListDetailProps, type DescriptionListLayout, type DescriptionListRootProps, type DescriptionListTermProps, Disclosure, type DisclosureProps, Frames, type FramesHeight, type FramesItemProps, type FramesRootProps, Grid, type GridColumns, type GridProps, Item, type ItemProps, Link, type LinkProps, Pagination, type PaginationEntry, type PaginationProps, Preview, type PreviewAxis, type PreviewGround, type PreviewPresentation, type PreviewProps, type PreviewResizeOptions, Sidebar, type SidebarItemProps, type SidebarRailProps, type SidebarRootProps, type SidebarSectionProps, type SpaceStep, Stack, type StackAlign, type StackJustify, type StackProps, Stepper, type StepperProps, type StepperState, type StepperStep, Timeline, type TimelineContentProps, type TimelineItemProps, type TimelineMarkerProps, type TimelineRootProps, itemVariants, linkVariants, paginationRange, useSidebar };
|
package/dist/layout/index.js
CHANGED
|
@@ -8,10 +8,11 @@ import { Breadcrumb } from "./breadcrumb.js";
|
|
|
8
8
|
import { Card } from "./card.js";
|
|
9
9
|
import { Collapsible, Disclosure } from "./collapsible.js";
|
|
10
10
|
import { DescriptionList } from "./description-list.js";
|
|
11
|
+
import { Frames } from "./frames.js";
|
|
11
12
|
import { Grid } from "./grid.js";
|
|
12
13
|
import { Item, itemVariants } from "./item.js";
|
|
13
14
|
import { Pagination, paginationRange } from "./pagination.js";
|
|
14
15
|
import { Preview } from "./preview.js";
|
|
15
16
|
import { Stepper } from "./stepper.js";
|
|
16
17
|
import { Timeline } from "./timeline.js";
|
|
17
|
-
export { Accordion, Bento, Breadcrumb, Card, Collapsible, Container, DescriptionList, Disclosure, Grid, Item, Link, Pagination, Preview, Sidebar, Stack, Stepper, Timeline, itemVariants, linkVariants, paginationRange, useSidebar };
|
|
18
|
+
export { Accordion, Bento, Breadcrumb, Card, Collapsible, Container, DescriptionList, Disclosure, Frames, Grid, Item, Link, Pagination, Preview, Sidebar, Stack, Stepper, Timeline, itemVariants, linkVariants, paginationRange, useSidebar };
|
package/dist/layout/preview.d.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
|
+
import { PreviewGround } from "./_ground.js";
|
|
1
2
|
import * as React from "react";
|
|
2
3
|
import { Density, FontName, Mode, ThemeName } from "@cueplusplus/theme-base";
|
|
3
4
|
//#region src/layout/preview.d.ts
|
|
5
|
+
/** Where the chrome sits and what the stage's ground is. */
|
|
6
|
+
type PreviewPresentation = "panel" | "frame";
|
|
4
7
|
/** Which edges of the stage a reader may drag. */
|
|
5
8
|
type PreviewAxis = "x" | "y" | "both";
|
|
6
9
|
/** How far a resizable stage may go, in CSS pixels, and along which axes. */
|
|
@@ -74,11 +77,51 @@ interface PreviewProps extends Omit<React.ComponentPropsWithoutRef<"div">, "chil
|
|
|
74
77
|
tools?: React.ReactNode;
|
|
75
78
|
/** The strip under the stage: the thin text and the way out. Drawn outside the stage. */
|
|
76
79
|
footer?: React.ReactNode;
|
|
80
|
+
/**
|
|
81
|
+
* `"panel"` (the default, and what every existing caller gets): a bordered
|
|
82
|
+
* card, `tools` floating at the stage's top right, `footer` under it.
|
|
83
|
+
* `"frame"`: a design-canvas frame — the label row drawn *above* the stage
|
|
84
|
+
* rather than over it, four crosshair corners at the stage's outer corners,
|
|
85
|
+
* and a transparent stage so whatever the frame sits on shows through.
|
|
86
|
+
*/
|
|
87
|
+
presentation?: PreviewPresentation;
|
|
88
|
+
/**
|
|
89
|
+
* The label row's leading slot, drawn only in `"frame"`. A plain node, or a
|
|
90
|
+
* control: apps/docs passes a `DropdownMenu` whose trigger is the frame's
|
|
91
|
+
* name. Unset, the row opens with `label` as text.
|
|
92
|
+
*
|
|
93
|
+
* A slot and not a built-in menu, because `Preview` imports no overlay today
|
|
94
|
+
* and `/` draws seventeen of it under a 766-byte headroom.
|
|
95
|
+
*/
|
|
96
|
+
name?: React.ReactNode;
|
|
97
|
+
/** The count drawn after the name — how many items this frame holds. Frame only. */
|
|
98
|
+
count?: number;
|
|
99
|
+
/**
|
|
100
|
+
* The stage's ground. Defaults to `"dots"` in `"panel"` and `"none"` in
|
|
101
|
+
* `"frame"`, where the canvas under it already carries a ground and two dot
|
|
102
|
+
* grids at different pitches read as a moiré.
|
|
103
|
+
*/
|
|
104
|
+
ground?: PreviewGround;
|
|
105
|
+
/**
|
|
106
|
+
* Whether `Frames.Item` captions are shown inside this stage. Defaults to
|
|
107
|
+
* `true`. Off is paint and nothing more: a hidden caption is still rendered,
|
|
108
|
+
* still in the tree and still read aloud (§4.1 Decision 4).
|
|
109
|
+
*/
|
|
110
|
+
captions?: boolean;
|
|
77
111
|
}
|
|
78
112
|
/**
|
|
79
|
-
* A
|
|
113
|
+
* A card for one component: a stage that is its own theme island, a slot for
|
|
80
114
|
* tools at the top right, and a footer.
|
|
81
115
|
*
|
|
116
|
+
* **Two presentations, one stage.** `"panel"`, the default and what every
|
|
117
|
+
* existing caller gets, is that card: a border, a fill, a dot grid under the
|
|
118
|
+
* specimen, and the tools floating over the stage's top right. `"frame"` is a
|
|
119
|
+
* design-canvas frame — no card, no border, no fill; the name, the count and
|
|
120
|
+
* the tools sit in a row *above* the stage rather than over it, four crosshairs
|
|
121
|
+
* mark the stage's outer corners, and the stage paints nothing by default, so
|
|
122
|
+
* whatever canvas the frame sits on shows through. Everything below holds in
|
|
123
|
+
* both.
|
|
124
|
+
*
|
|
82
125
|
* **The stage is the island; the chrome is not.** `theme`, `mode`, `density`
|
|
83
126
|
* and `font` land on the stage element only, and the stage republishes the
|
|
84
127
|
* theme and density contexts so an overlay opened on it follows it. The tools,
|
|
@@ -94,7 +137,7 @@ interface PreviewProps extends Omit<React.ComponentPropsWithoutRef<"div">, "chil
|
|
|
94
137
|
* that is under `maxWidth`. Not `Resizable`, which is split panes on an
|
|
95
138
|
* optional peer.
|
|
96
139
|
*
|
|
97
|
-
* Props, not a compound: one stage and
|
|
140
|
+
* Props, not a compound: one stage and its slots, each saying what it is.
|
|
98
141
|
*
|
|
99
142
|
* @example
|
|
100
143
|
* <Preview label="Button preview" tools={<IconButton aria-label="Configure Button" icon={Wrench} />}>
|
|
@@ -104,7 +147,11 @@ interface PreviewProps extends Omit<React.ComponentPropsWithoutRef<"div">, "chil
|
|
|
104
147
|
* <Preview label="Chip preview" theme="terminal" density="compact" resizable>
|
|
105
148
|
* <Chip tone="accent">Standby</Chip>
|
|
106
149
|
* </Preview>
|
|
150
|
+
* @example
|
|
151
|
+
* <Preview label="Button" presentation="frame" count={3}>
|
|
152
|
+
* <Button variant="primary">Take cue</Button>
|
|
153
|
+
* </Preview>
|
|
107
154
|
*/
|
|
108
155
|
declare const Preview: React.ForwardRefExoticComponent<PreviewProps & React.RefAttributes<HTMLDivElement>>;
|
|
109
156
|
//#endregion
|
|
110
|
-
export { Preview, PreviewAxis, PreviewProps, PreviewResizeOptions };
|
|
157
|
+
export { Preview, PreviewAxis, type PreviewGround, PreviewPresentation, PreviewProps, PreviewResizeOptions };
|