@crewlethq/ui 0.26.0 → 0.27.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -204,6 +204,22 @@ places:
204
204
  - A surface that pans or zooms dispatches `LAYER_REPOSITION_EVENT` on its host
205
205
  when the content beneath it moves, and every panel anchored inside follows.
206
206
 
207
+ ## Changes in 0.27.1
208
+
209
+ **`useSlideKeys` answers every key with the newest handlers.** It re-added its document listener after each render, so after every step there was a gap, between the new slide's commit and the effect that re-added the listener, in which a quick second press (a clicker held down, two taps) reached the previous slide's handlers and moved to the slide already shown: the press was lost. The hook now keeps one listener for as long as it is `enabled` and reads the handlers from a ref it brings up to date as each render commits, before the browser can dispatch another event. A show whose stage stays mounted across slides, as `SlideStage fit="view"` does, met the gap on almost every quick press.
210
+
211
+ Nothing to change: handlers that close over the current slide are right as they are.
212
+
213
+ ## Changes in 0.27.0
214
+
215
+ **`SlideStage` presents in the page with `fit="view"`.** A slide presented inside a page sits below a title, a description and tabs, so a stage as tall as its column ran past the foot of the window and hid the bottom of the slide and the controls under it. A `view` stage letterboxes its slide as `contain` does, in a box whose height is measured: the room from the top of the stage's parent (the show: the stage and its controls) to the foot of its scrollport, less what else the parent holds and its `scroll-margin-bottom`, or the slide's height at the stage's width if that is less. The room is measured with the scrollport at its top, so it does not change as the reader scrolls, and again whenever the view, the show or the stage is resized. A show too low on the page to get half of what it asks takes the scrollport's whole height and is scrolled into view, clear of its `scroll-margin-top`. In full screen the stage fills its box, sharing a flex column with the show's controls.
216
+
217
+ What to change:
218
+
219
+ - A show presented in the page uses `fit="view"` in place of a box sized from the window's height, and lets the show's own height follow its content.
220
+ - The show sets `scroll-margin-top` to the height of anything sticky over the view, and `scroll-margin-bottom` to the gap it keeps from the foot of the view.
221
+ - `fit="contain"` is unchanged, for a box whose height the host already decides.
222
+
207
223
  ## Changes in 0.26.0
208
224
 
209
225
  **`@crewlethq/artifact-kit` binds a page's sheet to the runtime the engine serves**, `window.crewlet` contract 1.0 (the engine's `docs/reference/artifact-runtime.md`). The kit was written against a runtime the engine never served: it asked for a `data` capability the runtime calls `db`, so every page's sheet said it could not load, and it called methods the runtime does not have. The sheet now:
@@ -1,5 +1,5 @@
1
- export { PresenterView, formatStopwatch } from '../chunk-HONZQ4UR.js';
2
- import '../chunk-KNLJL3VP.js';
1
+ export { PresenterView, formatStopwatch } from '../chunk-OGAAHVF6.js';
2
+ import '../chunk-O63MWA4G.js';
3
3
  import '../chunk-OG6CL3EB.js';
4
4
  import '../chunk-HMPFGIWM.js';
5
5
  import '../chunk-R25RGPUB.js';
@@ -1,5 +1,5 @@
1
- export { SLIDE_COMPARE_LABELS, SlideCompare } from '../chunk-Z54BPRL6.js';
2
- import '../chunk-KNLJL3VP.js';
1
+ export { SLIDE_COMPARE_LABELS, SlideCompare } from '../chunk-ALMSY7RL.js';
2
+ import '../chunk-O63MWA4G.js';
3
3
  import '../chunk-OG6CL3EB.js';
4
4
  import '../chunk-HMPFGIWM.js';
5
5
  import '../chunk-R25RGPUB.js';
@@ -1,5 +1,5 @@
1
- export { SlideFilmstrip } from '../chunk-KSSSFLE2.js';
2
- import '../chunk-KNLJL3VP.js';
1
+ export { SlideFilmstrip } from '../chunk-LR5QTFOE.js';
2
+ import '../chunk-O63MWA4G.js';
3
3
  import '../chunk-XJ2QEBMM.js';
4
4
  import '../chunk-HMPFGIWM.js';
5
5
  import '../chunk-R25RGPUB.js';
@@ -1,5 +1,5 @@
1
- export { SlideGrid } from '../chunk-Q4A5CGUB.js';
2
- import '../chunk-KNLJL3VP.js';
1
+ export { SlideGrid } from '../chunk-3C3BRIMY.js';
2
+ import '../chunk-O63MWA4G.js';
3
3
  import '../chunk-HMPFGIWM.js';
4
4
  import '../chunk-R25RGPUB.js';
5
5
  import '../chunk-ODEQTPFM.js';
@@ -9,8 +9,11 @@ export declare const SLIDE_HEIGHT = 1080;
9
9
  * thumbnail, a grid card, the editor's slide.
10
10
  * - `contain`: as large as fits inside its container both ways, centred, the
11
11
  * rest letterboxed. Present, full screen.
12
+ * - `view`: Present in the page. As `contain`, in a box as tall as lets the
13
+ * stage's parent (the show: the stage and its controls) be seen whole, from
14
+ * its top to the foot of the view; in full screen, the whole box.
12
15
  */
13
- export type SlideStageFit = 'width' | 'contain';
16
+ export type SlideStageFit = 'width' | 'contain' | 'view';
14
17
  export interface SlideStageProps {
15
18
  /** The slide, laid out at the stage's own size (1920 by 1080 by default). */
16
19
  children: ReactNode;
@@ -36,6 +39,14 @@ export interface SlideStageProps {
36
39
  * show the same line breaks. Reflowing it to the box would move every pinned
37
40
  * element relative to the text beside it.
38
41
  *
42
+ * SEEN WHOLE IN THE PAGE (`fit="view"`): the stage's height is measured too,
43
+ * as the room from its parent's top to the foot of the scrollport less what
44
+ * else the parent holds, or the slide's height at the stage's width if that
45
+ * is less, so the slide's foot and the controls under it are never below the
46
+ * fold. A parent too low on the page to get half of that takes the whole view
47
+ * and is scrolled to, clear of its `scroll-margin-top` and
48
+ * `scroll-margin-bottom`. The parent's height follows its content.
49
+ *
39
50
  * MEASURED, NOT GUESSED: the scale is the box's own size over the stage's,
40
51
  * read whenever the box resizes, so a filmstrip that narrows or a window that
41
52
  * goes full screen redraws at the new size. A `scale` given outright is used
@@ -0,0 +1,38 @@
1
+ import { type RefObject } from 'react';
2
+ /**
3
+ * How tall a `fit="view"` stage may be so that its show is seen whole.
4
+ *
5
+ * THE SHOW IS THE STAGE'S PARENT: the stage and whatever the parent sets
6
+ * around it (a count, Previous and Next), all of which must be on screen
7
+ * together. No length in a stylesheet can say how tall that may be, because it
8
+ * is the view's height less whatever the page sets above the show (a title, a
9
+ * description, tabs), and that wraps differently on every window. So it is
10
+ * MEASURED, after layout and again whenever the view, the show or the stage
11
+ * is resized.
12
+ *
13
+ * The show asks for the stage at its full width plus the rest of the show, and
14
+ * is given that or the room from its top to the foot of its scrollport,
15
+ * measured with the scrollport at its top, whichever is less. When that room
16
+ * would shrink it below half of what it asks, it is too low on the page to be
17
+ * read there: it takes the scrollport's whole height instead and is scrolled
18
+ * into view. The show's `scroll-margin-top` and `scroll-margin-bottom` are
19
+ * kept clear, so a sticky bar over the view and the page's own foot are never
20
+ * covered.
21
+ */
22
+ export interface StageFit {
23
+ /** The stage's height, in CSS pixels. */
24
+ height: number;
25
+ /** Whether the show only fits once it is scrolled into view. */
26
+ scroll: boolean;
27
+ }
28
+ /** The nearest ancestor that scrolls vertically, or null when the window does. */
29
+ export declare function scrollportOf(el: Element): HTMLElement | null;
30
+ /** The fit of `stage`, whose slide is `ratio` (height over width) of its width. */
31
+ export declare function fitInView(stage: HTMLElement, ratio: number): StageFit;
32
+ /**
33
+ * The height a `fit="view"` stage takes, or null when it is not measured: off,
34
+ * not yet laid out, or in full screen, where the stage fills its box. A show
35
+ * that only fits once scrolled into view is scrolled there when it is first
36
+ * measured.
37
+ */
38
+ export declare function useFitInView(stage: RefObject<HTMLElement | null>, enabled: boolean, ratio: number): number | null;
@@ -1,4 +1,4 @@
1
- export { SLIDE_HEIGHT, SLIDE_WIDTH, SlideStage, useSlideKeys } from '../chunk-KNLJL3VP.js';
1
+ export { SLIDE_HEIGHT, SLIDE_WIDTH, SlideStage, useSlideKeys } from '../chunk-O63MWA4G.js';
2
2
  import '../chunk-HMPFGIWM.js';
3
3
  import '../chunk-R25RGPUB.js';
4
4
  import '../chunk-ODEQTPFM.js';
@@ -17,5 +17,14 @@ export interface SlideKeys {
17
17
  * its key wherever focus is. A key a field is typing, a composition is using,
18
18
  * or a nearer surface (a menu, a dialog) already handled is left alone, and
19
19
  * modified keys are the browser's.
20
+ *
21
+ * THE NEWEST HANDLERS ANSWER EVERY KEY. A show's handlers close over the slide
22
+ * it is on, so a key must never reach the handlers of a slide already left.
23
+ * They are read from a ref the hook brings up to date as each render commits,
24
+ * before the browser can dispatch another event, and the listener itself
25
+ * stays put. Re-adding the listener after each render instead left a gap
26
+ * after every step, between the new slide's commit and the effect that
27
+ * re-added it, where a quick second press (a clicker held down, or two taps)
28
+ * went to the old slide's handlers and moved to the slide already shown.
20
29
  */
21
30
  export declare function useSlideKeys({ onNext, onPrevious, onFirst, onLast, onExit, enabled }: SlideKeys): void;
@@ -16,6 +16,22 @@
16
16
  height: 100%;
17
17
  }
18
18
 
19
+ /* Until it is measured, and wherever it is not (no layout), a view stage is
20
+ its slide's shape at its width. In full screen it fills the box, sharing a
21
+ flex column with the show's controls. */
22
+ .crewlet-slide-stage--view {
23
+ flex: none;
24
+ aspect-ratio: var(--crewlet-slide-stage-ratio, 16 / 9);
25
+ }
26
+
27
+ :fullscreen .crewlet-slide-stage--view,
28
+ .crewlet-slide-stage--view:fullscreen {
29
+ flex: 1 1 0;
30
+ min-height: 0;
31
+ height: 100%;
32
+ aspect-ratio: auto;
33
+ }
34
+
19
35
  .crewlet-slide-stage__frame {
20
36
  position: absolute;
21
37
  top: 0;
@@ -1,4 +1,4 @@
1
- import { SlideStage } from './chunk-KNLJL3VP.js';
1
+ import { SlideStage } from './chunk-O63MWA4G.js';
2
2
  import { cx } from './chunk-ODEQTPFM.js';
3
3
  import './SlideGrid-RT6QEQEE.css';
4
4
  import { EyeOffGlyph } from '@crewlethq/icons/glyphs';
@@ -1,4 +1,4 @@
1
- import { SlideStage } from './chunk-KNLJL3VP.js';
1
+ import { SlideStage } from './chunk-O63MWA4G.js';
2
2
  import { Button } from './chunk-OG6CL3EB.js';
3
3
  import { cx } from './chunk-ODEQTPFM.js';
4
4
  import './SlideCompare-MGM3U2ME.css';
@@ -1,4 +1,4 @@
1
- import { SlideStage } from './chunk-KNLJL3VP.js';
1
+ import { SlideStage } from './chunk-O63MWA4G.js';
2
2
  import { useReorder } from './chunk-XJ2QEBMM.js';
3
3
  import { VisuallyHidden } from './chunk-BZFWDIV6.js';
4
4
  import { cx } from './chunk-ODEQTPFM.js';
@@ -0,0 +1,172 @@
1
+ import { isComposing } from './chunk-R25RGPUB.js';
2
+ import { cx } from './chunk-ODEQTPFM.js';
3
+ import './SlideStage-KGRRALXR.css';
4
+ import { useRef, useState, useLayoutEffect, useEffect } from 'react';
5
+ import { jsx } from 'react/jsx-runtime';
6
+
7
+ function scrollportOf(el) {
8
+ for (let p = el.parentElement; p; p = p.parentElement) {
9
+ if (/^(auto|scroll)$/.test(getComputedStyle(p).overflowY)) return p;
10
+ }
11
+ return null;
12
+ }
13
+ var px = (value) => {
14
+ const n = parseFloat(value);
15
+ return Number.isFinite(n) ? n : 0;
16
+ };
17
+ function fitInView(stage, ratio) {
18
+ const show = stage.parentElement ?? stage;
19
+ const port = scrollportOf(show);
20
+ const box = show.getBoundingClientRect();
21
+ const top = port ? box.top - port.getBoundingClientRect().top - port.clientTop + port.scrollTop : box.top + window.scrollY;
22
+ const view = port ? port.clientHeight : document.documentElement.clientHeight;
23
+ const margins = getComputedStyle(show);
24
+ const above = px(margins.scrollMarginTop);
25
+ const below = px(margins.scrollMarginBottom);
26
+ const rest = show === stage ? 0 : Math.max(0, show.offsetHeight - stage.offsetHeight);
27
+ const need = stage.clientWidth * ratio + rest;
28
+ const room = view - top - below;
29
+ const scroll = room < need / 2;
30
+ const height = Math.min(need, scroll ? view - above - below : room);
31
+ return { height: Math.max(0, height - rest), scroll };
32
+ }
33
+ function inFullscreen(el) {
34
+ const full = typeof document === "undefined" ? null : document.fullscreenElement;
35
+ return !!full && full.contains(el);
36
+ }
37
+ function useFitInView(stage, enabled, ratio) {
38
+ const [height, setHeight] = useState(null);
39
+ useLayoutEffect(() => {
40
+ const el = stage.current;
41
+ if (!el || !enabled) return void 0;
42
+ let first = true;
43
+ const measure = () => {
44
+ if (inFullscreen(el)) {
45
+ setHeight(null);
46
+ return;
47
+ }
48
+ const fit = fitInView(el, ratio);
49
+ setHeight(Math.floor(fit.height));
50
+ if (first && fit.scroll) (el.parentElement ?? el).scrollIntoView?.({ block: "start" });
51
+ first = false;
52
+ };
53
+ measure();
54
+ document.addEventListener("fullscreenchange", measure);
55
+ if (typeof ResizeObserver === "undefined") {
56
+ return () => document.removeEventListener("fullscreenchange", measure);
57
+ }
58
+ const watch = new ResizeObserver(measure);
59
+ watch.observe(el);
60
+ if (el.parentElement) watch.observe(el.parentElement);
61
+ watch.observe(scrollportOf(el) ?? document.documentElement);
62
+ return () => {
63
+ watch.disconnect();
64
+ document.removeEventListener("fullscreenchange", measure);
65
+ };
66
+ }, [stage, enabled, ratio]);
67
+ return enabled ? height : null;
68
+ }
69
+ var SLIDE_WIDTH = 1920;
70
+ var SLIDE_HEIGHT = 1080;
71
+ function SlideStage({
72
+ children,
73
+ label,
74
+ fit = "width",
75
+ scale,
76
+ width = SLIDE_WIDTH,
77
+ height = SLIDE_HEIGHT,
78
+ className
79
+ }) {
80
+ const box = useRef(null);
81
+ const viewHeight = useFitInView(box, fit === "view" && scale === void 0, height / width);
82
+ const [measured, setMeasured] = useState({
83
+ scale: 0,
84
+ left: 0,
85
+ top: 0
86
+ });
87
+ useLayoutEffect(() => {
88
+ const el = box.current;
89
+ if (!el || scale !== void 0) return void 0;
90
+ const read = () => {
91
+ const w = el.clientWidth;
92
+ const h = el.clientHeight;
93
+ if (fit !== "width") {
94
+ const s2 = Math.min(w / width, h / height);
95
+ setMeasured({ scale: s2, left: (w - width * s2) / 2, top: (h - height * s2) / 2 });
96
+ } else {
97
+ setMeasured({ scale: w / width, left: 0, top: 0 });
98
+ }
99
+ };
100
+ read();
101
+ if (typeof ResizeObserver === "undefined") return void 0;
102
+ const observer = new ResizeObserver(read);
103
+ observer.observe(el);
104
+ return () => observer.disconnect();
105
+ }, [fit, scale, width, height, viewHeight]);
106
+ const s = scale ?? measured.scale;
107
+ const boxStyle = fit === "width" || scale !== void 0 ? { aspectRatio: `${width} / ${height}`, ...scale !== void 0 ? { width: width * scale } : {} } : fit === "view" ? {
108
+ "--crewlet-slide-stage-ratio": `${width} / ${height}`,
109
+ ...viewHeight !== null ? { height: viewHeight } : {}
110
+ } : {};
111
+ const frameStyle = {
112
+ width,
113
+ height,
114
+ transform: `translate(${scale === void 0 ? measured.left : 0}px, ${scale === void 0 ? measured.top : 0}px) scale(${s})`,
115
+ // Hidden until measured, so a slide is never painted at full size for
116
+ // one frame inside a thumbnail.
117
+ visibility: s > 0 ? "visible" : "hidden"
118
+ };
119
+ return /* @__PURE__ */ jsx(
120
+ "div",
121
+ {
122
+ ref: box,
123
+ className: cx("crewlet-slide-stage", `crewlet-slide-stage--${fit}`, className),
124
+ style: boxStyle,
125
+ role: "group",
126
+ "aria-roledescription": "slide",
127
+ "aria-label": label,
128
+ children: /* @__PURE__ */ jsx("div", { className: "crewlet-slide-stage__frame", style: frameStyle, children })
129
+ }
130
+ );
131
+ }
132
+ function typing(target) {
133
+ if (!(target instanceof HTMLElement)) return false;
134
+ return target.isContentEditable || ["INPUT", "TEXTAREA", "SELECT"].includes(target.tagName);
135
+ }
136
+ function useSlideKeys({ onNext, onPrevious, onFirst, onLast, onExit, enabled = true }) {
137
+ const keys = useRef({ onNext, onPrevious, onFirst, onLast, onExit });
138
+ useLayoutEffect(() => {
139
+ keys.current = { onNext, onPrevious, onFirst, onLast, onExit };
140
+ });
141
+ useEffect(() => {
142
+ if (!enabled) return void 0;
143
+ const onKeyDown = (event) => {
144
+ if (event.defaultPrevented || isComposing(event) || typing(event.target)) return;
145
+ if (event.altKey || event.ctrlKey || event.metaKey) return;
146
+ const { onNext: onNext2, onPrevious: onPrevious2, onFirst: onFirst2, onLast: onLast2, onExit: onExit2 } = keys.current;
147
+ const act = {
148
+ ArrowRight: onNext2,
149
+ ArrowDown: onNext2,
150
+ PageDown: onNext2,
151
+ " ": onNext2,
152
+ Enter: onNext2,
153
+ ArrowLeft: onPrevious2,
154
+ ArrowUp: onPrevious2,
155
+ PageUp: onPrevious2,
156
+ Backspace: onPrevious2,
157
+ Home: onFirst2,
158
+ End: onLast2,
159
+ Escape: onExit2
160
+ };
161
+ const fn = act[event.key];
162
+ if (!fn) return;
163
+ if ((event.key === "Enter" || event.key === " ") && event.target instanceof HTMLButtonElement) return;
164
+ event.preventDefault();
165
+ fn();
166
+ };
167
+ document.addEventListener("keydown", onKeyDown);
168
+ return () => document.removeEventListener("keydown", onKeyDown);
169
+ }, [enabled]);
170
+ }
171
+
172
+ export { SLIDE_HEIGHT, SLIDE_WIDTH, SlideStage, useSlideKeys };
@@ -1,4 +1,4 @@
1
- import { SlideStage } from './chunk-KNLJL3VP.js';
1
+ import { SlideStage } from './chunk-O63MWA4G.js';
2
2
  import { Button } from './chunk-OG6CL3EB.js';
3
3
  import { IconButton } from './chunk-4FQT6ZAY.js';
4
4
  import { cx } from './chunk-ODEQTPFM.js';
@@ -1,30 +1,30 @@
1
1
  import '../chunk-SLRKS5PF.js';
2
- export { VersionTimeline } from '../chunk-W4XYY73O.js';
2
+ export { TreeCanvas } from '../chunk-RSC7UJCR.js';
3
3
  export { WidgetFrame } from '../chunk-BQYQWJPK.js';
4
4
  export { ElementToPngError, elementToPng, serializeElement, toCsv } from '../chunk-UOR7TOAU.js';
5
- export { Timeline, TimelineItem } from '../chunk-AUQPBL4O.js';
6
5
  export { ToastProvider, Toaster, useToast } from '../chunk-QH3AKP2N.js';
7
- export { TreeCanvas } from '../chunk-RSC7UJCR.js';
8
6
  export { VERSION_COMPARE_LABELS, VERSION_COMPARE_LENSES, VersionCompare } from '../chunk-EHQTPVV4.js';
7
+ export { VersionTimeline } from '../chunk-W4XYY73O.js';
8
+ export { Timeline, TimelineItem } from '../chunk-AUQPBL4O.js';
9
9
  export { TagsInput } from '../chunk-2CQLNML5.js';
10
10
  export { Text } from '../chunk-IKBK4A5O.js';
11
11
  export { ThemeGallery } from '../chunk-C2FRTWKO.js';
12
12
  export { ThemeSwatch } from '../chunk-MNFU2RNT.js';
13
13
  export { DensitySwitcher, ThemeSwitcher } from '../chunk-WJDQ7XQA.js';
14
+ export { DEFAULT_TIME_WINDOW_LABELS, TIME_WINDOW_SPANS, TimeWindowPicker, describeTimeWindow, isTimeWindowSet, parseTimeWindowDuration, resolveTimeWindow, timeWindowMatchesPreset } from '../chunk-LREN6TUG.js';
14
15
  export { ThemeToggle } from '../chunk-NP2C4Y4E.js';
15
16
  export { applyStoredPreferences, resolveTheme, useDensityPreference, useSystemTheme, useThemePreference } from '../chunk-Z24ZUSTX.js';
16
- export { DEFAULT_TIME_WINDOW_LABELS, TIME_WINDOW_SPANS, TimeWindowPicker, describeTimeWindow, isTimeWindowSet, parseTimeWindowDuration, resolveTimeWindow, timeWindowMatchesPreset } from '../chunk-LREN6TUG.js';
17
17
  export { Stepper } from '../chunk-5QWIJSQM.js';
18
18
  export { Switcher } from '../chunk-5OY4LJFH.js';
19
19
  export { Table } from '../chunk-V2N3BMOT.js';
20
20
  export { TABLE_TAGS_CELL_LABELS, TableDateCell, TableEntityCell, TableKeyCell, TableNumberCell, TableStatusCell, TableTagsCell, TableTextCell } from '../chunk-LFNUH4GY.js';
21
21
  export { NavGroup, NavItem, SidebarNav } from '../chunk-UCCC7YVZ.js';
22
- export { SLIDE_COMPARE_LABELS, SlideCompare } from '../chunk-Z54BPRL6.js';
23
- export { SlideFilmstrip } from '../chunk-KSSSFLE2.js';
24
- export { SlideGrid } from '../chunk-Q4A5CGUB.js';
22
+ export { SLIDE_COMPARE_LABELS, SlideCompare } from '../chunk-ALMSY7RL.js';
23
+ export { SlideFilmstrip } from '../chunk-LR5QTFOE.js';
24
+ export { SlideGrid } from '../chunk-3C3BRIMY.js';
25
25
  export { StatCard } from '../chunk-IKB6HFGK.js';
26
26
  export { StatGroup } from '../chunk-JXRI5YD2.js';
27
- export { SearchTrigger } from '../chunk-6DRDCT22.js';
27
+ export { Section } from '../chunk-FAQGGX2Z.js';
28
28
  export { SegmentedMeter, segmentedMeterLabel } from '../chunk-4AK52VHB.js';
29
29
  export { ARTIFACT_ROLES, SHAREABLE_ROLES, ShareDialog, roleAtLeast } from '../chunk-URUGEAFB.js';
30
30
  export { Select } from '../chunk-FC4YTTFJ.js';
@@ -37,12 +37,13 @@ export { QR_DARK, QR_LIGHT, QR_QUIET_ZONE, QrCode, qrModulePath, qrModules } fro
37
37
  export { ReadingPane, ReadingPaneByline, ReadingPaneLead, ReadingPaneOutcome, ReadingPaneQuote, ReadingPaneReasoning, ReadingPaneSection, ReadingPaneTitle } from '../chunk-ZAJHGDAW.js';
38
38
  export { FRAME_HELLO_TIMEOUT_MS, SandboxedFrame } from '../chunk-VYDFB6PJ.js';
39
39
  export { Skeleton } from '../chunk-W5J7R5EB.js';
40
- export { Section } from '../chunk-FAQGGX2Z.js';
40
+ export { SearchTrigger } from '../chunk-6DRDCT22.js';
41
41
  export { PinTile } from '../chunk-6MIXD6IW.js';
42
42
  export { PresenceStack } from '../chunk-ODT5H4MN.js';
43
- export { PresenterView, formatStopwatch } from '../chunk-HONZQ4UR.js';
44
- export { SLIDE_HEIGHT, SLIDE_WIDTH, SlideStage, useSlideKeys } from '../chunk-KNLJL3VP.js';
43
+ export { PresenterView, formatStopwatch } from '../chunk-OGAAHVF6.js';
44
+ export { SLIDE_HEIGHT, SLIDE_WIDTH, SlideStage, useSlideKeys } from '../chunk-O63MWA4G.js';
45
45
  export { PricingCard } from '../chunk-DQSXWQMJ.js';
46
+ export { NewItemsNotice } from '../chunk-PXU6HOZB.js';
46
47
  export { FactLine, ObjectHeader, SetByLine } from '../chunk-VGE3G3T4.js';
47
48
  export { OrgNodeDisclosure, OrgNodeLabel, OrgNodeLead } from '../chunk-TBMDMXEX.js';
48
49
  export { OrgTable, OrgTableActions, OrgTableAdd, OrgTableName } from '../chunk-AMNN4WDX.js';
@@ -53,16 +54,15 @@ export { Outline, scrollToHeading, useActiveHeading } from '../chunk-A5YKNRG6.js
53
54
  export { PEOPLE_RAIL_LABELS, PeopleRail, peopleRailKey } from '../chunk-FVLCTCMV.js';
54
55
  import '../chunk-CENOOTAV.js';
55
56
  export { LIVE_CURSOR_HIDE_MS, LIVE_CURSOR_REST_MS, LiveCursor } from '../chunk-5XACKNYR.js';
57
+ export { ListInput } from '../chunk-D5JZN3ML.js';
56
58
  export { MARKDOWN_FORMATS, MarkdownEditor, formatMarkdown, insertMarkdown, markdownWords } from '../chunk-LZHLSQYK.js';
57
59
  export { MERGE_CONFLICTS_LABELS, MergeConflicts } from '../chunk-RWA4H2TV.js';
58
60
  import '../chunk-FQCLKD7U.js';
59
61
  export { DEFAULT_METER_THRESHOLDS, METER_STATES, Meter, meterState, meterStateTone, meterTone, progressTone } from '../chunk-UGNUUVRI.js';
60
- export { NewItemsNotice } from '../chunk-PXU6HOZB.js';
61
62
  export { AutoGrid, Inline, Spacer, Stack } from '../chunk-ZAC7SKUN.js';
62
- export { LinkInterstitial, openExternal } from '../chunk-L2OQRPXJ.js';
63
63
  export { Link } from '../chunk-FBSEJO2C.js';
64
+ export { LinkInterstitial, openExternal } from '../chunk-L2OQRPXJ.js';
64
65
  export { List, ListItem } from '../chunk-DS2C73RJ.js';
65
- export { ListInput } from '../chunk-D5JZN3ML.js';
66
66
  export { Highlight, highlightRanges, highlightTerms } from '../chunk-H6VKCIWV.js';
67
67
  import '../chunk-FFMCMSJB.js';
68
68
  export { IconTile } from '../chunk-IXJHTFXG.js';
@@ -71,12 +71,12 @@ export { InboxGroup, InboxList, InboxMore, InboxRow, InboxToggle } from '../chun
71
71
  export { EntityChip } from '../chunk-4KWOKX2B.js';
72
72
  export { ErrorBoundary } from '../chunk-XX2VQE55.js';
73
73
  export { Eyebrow } from '../chunk-RK4XPHVG.js';
74
- export { FactList } from '../chunk-JI5AVQLA.js';
75
74
  export { FILTER_CHIP_ATTRIBUTE, FilterChip, FilterChipGroup } from '../chunk-5YLON2PW.js';
76
75
  export { FollowBanner } from '../chunk-FW7HN6AP.js';
77
76
  export { DEFAULT_FRAME_THEME, EXTERNAL_URL_MAX, FRAME_BRIDGE, FRAME_MESSAGE, FRAME_ORIGIN_MODES, FRAME_SANDBOX_TOKENS, applyFrameTheme, checkFrameSandbox, externalUrl, frameFragment, frameOriginMatches, frameThemeMessage, httpOrigin, isFocusExit, isFrameNonce, negotiateBridge, parseFrameFragment, portTargetOrigin, readFrameHello, readFramePortMessage, readFrameTheme, readOpenLink } from '../chunk-F6V2PTN6.js';
78
77
  export { DENSITY_PREFERENCES, PALETTE_ID, THEME_PREFERENCES, applyDensity, applyPalette, applyTheme, isDensityPreference, isPaletteId, isThemePreference } from '../chunk-ZXXDZJQN.js';
79
78
  export { useFullscreen } from '../chunk-XDTYBF2F.js';
79
+ export { FactList } from '../chunk-JI5AVQLA.js';
80
80
  export { DIFF_SUMMARY_LABELS, DIFF_VIEW_LABELS, DiffSummary, DiffView, MAX_DIFF_LINES, collapseDiff, diffLines, diffStat, firstChangedLines, splitLines } from '../chunk-BVWSLXTY.js';
81
81
  export { Disclosure } from '../chunk-S4RCG44T.js';
82
82
  export { Divider } from '../chunk-6KWNXIDE.js';
@@ -93,8 +93,8 @@ export { DATASET_SOURCE_KINDS, DatasetSource, DatasetSourceList } from '../chunk
93
93
  export { Tag } from '../chunk-GFV4LJHH.js';
94
94
  export { StatusDot } from '../chunk-WIATRXEJ.js';
95
95
  export { DEFAULT_DATE_TIME_PICKER_LABELS, DateTimePicker } from '../chunk-WG5WUFBX.js';
96
- export { DescriptionList, DescriptionListItem } from '../chunk-F2XSYBKH.js';
97
96
  export { DIFF_LIST_LABELS, DiffList } from '../chunk-LFHCXZO5.js';
97
+ export { DescriptionList, DescriptionListItem } from '../chunk-F2XSYBKH.js';
98
98
  export { Combobox } from '../chunk-QS4ZGTEU.js';
99
99
  export { CommandPalette } from '../chunk-GTLJXJ3U.js';
100
100
  export { ConfirmModal, Modal } from '../chunk-F4DPAJCN.js';
@@ -140,9 +140,8 @@ export { ARTIFACT_KINDS, ArtifactCard, ArtifactKindGlyph } from '../chunk-6J35F3
140
140
  export { PRINCIPAL_KINDS, PrincipalAvatar } from '../chunk-4KP4RC3O.js';
141
141
  export { RelativeTime, currentNow, formatElapsed, formatExact, formatRelative, formatUntil, toISO, toInstant, useNow } from '../chunk-3CZ7XAVY.js';
142
142
  export { EMPTY_VALUE, EmptyValue } from '../chunk-EUCC37WY.js';
143
- export { AuthLayout } from '../chunk-WHZFDS62.js';
144
- export { BrandLockup } from '../chunk-7KBNFFM3.js';
145
143
  export { AvatarStack, avatarStackLabel } from '../chunk-UAN5NE7M.js';
144
+ export { AuthLayout } from '../chunk-WHZFDS62.js';
146
145
  export { AvatarPicker } from '../chunk-PRNX5AFE.js';
147
146
  export { HuePicker } from '../chunk-SGIQCI6Y.js';
148
147
  export { SegmentedControl } from '../chunk-RCQXUT5K.js';
@@ -152,6 +151,7 @@ export { NODE_HUES, NODE_HUE_NAMES, isNodeHue } from '../chunk-AYKXMIOR.js';
152
151
  export { CHARACTER_PICKER_COLUMNS, CharacterPicker } from '../chunk-HVIX5ECM.js';
153
152
  import '../chunk-RKKO7QHH.js';
154
153
  export { AVATAR_CHARACTER_FULL_DETAIL, AVATAR_CORNER_RATIO, AVATAR_SIZES, AVATAR_STATUSES, AVATAR_STATUS_LABELS, Avatar, avatarCorner, avatarInitialsName, avatarPixels, avatarTint, getInitials } from '../chunk-5OM447RW.js';
154
+ export { BrandLockup } from '../chunk-7KBNFFM3.js';
155
155
  export { ACCESS_DENIED_REASONS, AccessDeniedCard } from '../chunk-G3EEUNZQ.js';
156
156
  export { EmptyState } from '../chunk-RA2ULG6H.js';
157
157
  export { Card } from '../chunk-YZCJ63JF.js';
@@ -167,9 +167,9 @@ export { Menu } from '../chunk-UFKUWVMV.js';
167
167
  export { Button, ButtonLink } from '../chunk-OG6CL3EB.js';
168
168
  export { LAYER_GAP, LAYER_REPOSITION_EVENT, LayerHost, outsideBounds, placePopup, useLayerContainer, viewportBounds } from '../chunk-HMPFGIWM.js';
169
169
  export { focusables, isComposing, isModalLayerOpen, layerCount, useBodyScrollLock, useModalLayer, usePopupLayer } from '../chunk-R25RGPUB.js';
170
- export { ArrangeBoard } from '../chunk-QO7QEQKV.js';
171
170
  export { ArrangeFrame, useGridResize } from '../chunk-DEJHAOC5.js';
172
171
  export { Announcer, announce, useAnnouncer } from '../chunk-RSAQOKH3.js';
173
172
  export { IconButton } from '../chunk-4FQT6ZAY.js';
174
173
  export { VisuallyHidden } from '../chunk-BZFWDIV6.js';
174
+ export { ArrangeBoard } from '../chunk-QO7QEQKV.js';
175
175
  export { cx } from '../chunk-ODEQTPFM.js';
package/dist/index.js CHANGED
@@ -1,30 +1,30 @@
1
1
  import './chunk-SLRKS5PF.js';
2
- export { VersionTimeline } from './chunk-W4XYY73O.js';
2
+ export { TreeCanvas } from './chunk-RSC7UJCR.js';
3
3
  export { WidgetFrame } from './chunk-BQYQWJPK.js';
4
4
  export { ElementToPngError, elementToPng, serializeElement, toCsv } from './chunk-UOR7TOAU.js';
5
- export { Timeline, TimelineItem } from './chunk-AUQPBL4O.js';
6
5
  export { ToastProvider, Toaster, useToast } from './chunk-QH3AKP2N.js';
7
- export { TreeCanvas } from './chunk-RSC7UJCR.js';
8
6
  export { VERSION_COMPARE_LABELS, VERSION_COMPARE_LENSES, VersionCompare } from './chunk-EHQTPVV4.js';
7
+ export { VersionTimeline } from './chunk-W4XYY73O.js';
8
+ export { Timeline, TimelineItem } from './chunk-AUQPBL4O.js';
9
9
  export { TagsInput } from './chunk-2CQLNML5.js';
10
10
  export { Text } from './chunk-IKBK4A5O.js';
11
11
  export { ThemeGallery } from './chunk-C2FRTWKO.js';
12
12
  export { ThemeSwatch } from './chunk-MNFU2RNT.js';
13
13
  export { DensitySwitcher, ThemeSwitcher } from './chunk-WJDQ7XQA.js';
14
+ export { DEFAULT_TIME_WINDOW_LABELS, TIME_WINDOW_SPANS, TimeWindowPicker, describeTimeWindow, isTimeWindowSet, parseTimeWindowDuration, resolveTimeWindow, timeWindowMatchesPreset } from './chunk-LREN6TUG.js';
14
15
  export { ThemeToggle } from './chunk-NP2C4Y4E.js';
15
16
  export { applyStoredPreferences, resolveTheme, useDensityPreference, useSystemTheme, useThemePreference } from './chunk-Z24ZUSTX.js';
16
- export { DEFAULT_TIME_WINDOW_LABELS, TIME_WINDOW_SPANS, TimeWindowPicker, describeTimeWindow, isTimeWindowSet, parseTimeWindowDuration, resolveTimeWindow, timeWindowMatchesPreset } from './chunk-LREN6TUG.js';
17
17
  export { Stepper } from './chunk-5QWIJSQM.js';
18
18
  export { Switcher } from './chunk-5OY4LJFH.js';
19
19
  export { Table } from './chunk-V2N3BMOT.js';
20
20
  export { TABLE_TAGS_CELL_LABELS, TableDateCell, TableEntityCell, TableKeyCell, TableNumberCell, TableStatusCell, TableTagsCell, TableTextCell } from './chunk-LFNUH4GY.js';
21
21
  export { NavGroup, NavItem, SidebarNav } from './chunk-UCCC7YVZ.js';
22
- export { SLIDE_COMPARE_LABELS, SlideCompare } from './chunk-Z54BPRL6.js';
23
- export { SlideFilmstrip } from './chunk-KSSSFLE2.js';
24
- export { SlideGrid } from './chunk-Q4A5CGUB.js';
22
+ export { SLIDE_COMPARE_LABELS, SlideCompare } from './chunk-ALMSY7RL.js';
23
+ export { SlideFilmstrip } from './chunk-LR5QTFOE.js';
24
+ export { SlideGrid } from './chunk-3C3BRIMY.js';
25
25
  export { StatCard } from './chunk-IKB6HFGK.js';
26
26
  export { StatGroup } from './chunk-JXRI5YD2.js';
27
- export { SearchTrigger } from './chunk-6DRDCT22.js';
27
+ export { Section } from './chunk-FAQGGX2Z.js';
28
28
  export { SegmentedMeter, segmentedMeterLabel } from './chunk-4AK52VHB.js';
29
29
  export { ARTIFACT_ROLES, SHAREABLE_ROLES, ShareDialog, roleAtLeast } from './chunk-URUGEAFB.js';
30
30
  export { Select } from './chunk-FC4YTTFJ.js';
@@ -37,12 +37,13 @@ export { QR_DARK, QR_LIGHT, QR_QUIET_ZONE, QrCode, qrModulePath, qrModules } fro
37
37
  export { ReadingPane, ReadingPaneByline, ReadingPaneLead, ReadingPaneOutcome, ReadingPaneQuote, ReadingPaneReasoning, ReadingPaneSection, ReadingPaneTitle } from './chunk-ZAJHGDAW.js';
38
38
  export { FRAME_HELLO_TIMEOUT_MS, SandboxedFrame } from './chunk-VYDFB6PJ.js';
39
39
  export { Skeleton } from './chunk-W5J7R5EB.js';
40
- export { Section } from './chunk-FAQGGX2Z.js';
40
+ export { SearchTrigger } from './chunk-6DRDCT22.js';
41
41
  export { PinTile } from './chunk-6MIXD6IW.js';
42
42
  export { PresenceStack } from './chunk-ODT5H4MN.js';
43
- export { PresenterView, formatStopwatch } from './chunk-HONZQ4UR.js';
44
- export { SLIDE_HEIGHT, SLIDE_WIDTH, SlideStage, useSlideKeys } from './chunk-KNLJL3VP.js';
43
+ export { PresenterView, formatStopwatch } from './chunk-OGAAHVF6.js';
44
+ export { SLIDE_HEIGHT, SLIDE_WIDTH, SlideStage, useSlideKeys } from './chunk-O63MWA4G.js';
45
45
  export { PricingCard } from './chunk-DQSXWQMJ.js';
46
+ export { NewItemsNotice } from './chunk-PXU6HOZB.js';
46
47
  export { FactLine, ObjectHeader, SetByLine } from './chunk-VGE3G3T4.js';
47
48
  export { OrgNodeDisclosure, OrgNodeLabel, OrgNodeLead } from './chunk-TBMDMXEX.js';
48
49
  export { OrgTable, OrgTableActions, OrgTableAdd, OrgTableName } from './chunk-AMNN4WDX.js';
@@ -53,16 +54,15 @@ export { Outline, scrollToHeading, useActiveHeading } from './chunk-A5YKNRG6.js'
53
54
  export { PEOPLE_RAIL_LABELS, PeopleRail, peopleRailKey } from './chunk-FVLCTCMV.js';
54
55
  import './chunk-CENOOTAV.js';
55
56
  export { LIVE_CURSOR_HIDE_MS, LIVE_CURSOR_REST_MS, LiveCursor } from './chunk-5XACKNYR.js';
57
+ export { ListInput } from './chunk-D5JZN3ML.js';
56
58
  export { MARKDOWN_FORMATS, MarkdownEditor, formatMarkdown, insertMarkdown, markdownWords } from './chunk-LZHLSQYK.js';
57
59
  export { MERGE_CONFLICTS_LABELS, MergeConflicts } from './chunk-RWA4H2TV.js';
58
60
  import './chunk-FQCLKD7U.js';
59
61
  export { DEFAULT_METER_THRESHOLDS, METER_STATES, Meter, meterState, meterStateTone, meterTone, progressTone } from './chunk-UGNUUVRI.js';
60
- export { NewItemsNotice } from './chunk-PXU6HOZB.js';
61
62
  export { AutoGrid, Inline, Spacer, Stack } from './chunk-ZAC7SKUN.js';
62
- export { LinkInterstitial, openExternal } from './chunk-L2OQRPXJ.js';
63
63
  export { Link } from './chunk-FBSEJO2C.js';
64
+ export { LinkInterstitial, openExternal } from './chunk-L2OQRPXJ.js';
64
65
  export { List, ListItem } from './chunk-DS2C73RJ.js';
65
- export { ListInput } from './chunk-D5JZN3ML.js';
66
66
  export { Highlight, highlightRanges, highlightTerms } from './chunk-H6VKCIWV.js';
67
67
  import './chunk-FFMCMSJB.js';
68
68
  export { IconTile } from './chunk-IXJHTFXG.js';
@@ -71,12 +71,12 @@ export { InboxGroup, InboxList, InboxMore, InboxRow, InboxToggle } from './chunk
71
71
  export { EntityChip } from './chunk-4KWOKX2B.js';
72
72
  export { ErrorBoundary } from './chunk-XX2VQE55.js';
73
73
  export { Eyebrow } from './chunk-RK4XPHVG.js';
74
- export { FactList } from './chunk-JI5AVQLA.js';
75
74
  export { FILTER_CHIP_ATTRIBUTE, FilterChip, FilterChipGroup } from './chunk-5YLON2PW.js';
76
75
  export { FollowBanner } from './chunk-FW7HN6AP.js';
77
76
  export { DEFAULT_FRAME_THEME, EXTERNAL_URL_MAX, FRAME_BRIDGE, FRAME_MESSAGE, FRAME_ORIGIN_MODES, FRAME_SANDBOX_TOKENS, applyFrameTheme, checkFrameSandbox, externalUrl, frameFragment, frameOriginMatches, frameThemeMessage, httpOrigin, isFocusExit, isFrameNonce, negotiateBridge, parseFrameFragment, portTargetOrigin, readFrameHello, readFramePortMessage, readFrameTheme, readOpenLink } from './chunk-F6V2PTN6.js';
78
77
  export { DENSITY_PREFERENCES, PALETTE_ID, THEME_PREFERENCES, applyDensity, applyPalette, applyTheme, isDensityPreference, isPaletteId, isThemePreference } from './chunk-ZXXDZJQN.js';
79
78
  export { useFullscreen } from './chunk-XDTYBF2F.js';
79
+ export { FactList } from './chunk-JI5AVQLA.js';
80
80
  export { DIFF_SUMMARY_LABELS, DIFF_VIEW_LABELS, DiffSummary, DiffView, MAX_DIFF_LINES, collapseDiff, diffLines, diffStat, firstChangedLines, splitLines } from './chunk-BVWSLXTY.js';
81
81
  export { Disclosure } from './chunk-S4RCG44T.js';
82
82
  export { Divider } from './chunk-6KWNXIDE.js';
@@ -93,8 +93,8 @@ export { DATASET_SOURCE_KINDS, DatasetSource, DatasetSourceList } from './chunk-
93
93
  export { Tag } from './chunk-GFV4LJHH.js';
94
94
  export { StatusDot } from './chunk-WIATRXEJ.js';
95
95
  export { DEFAULT_DATE_TIME_PICKER_LABELS, DateTimePicker } from './chunk-WG5WUFBX.js';
96
- export { DescriptionList, DescriptionListItem } from './chunk-F2XSYBKH.js';
97
96
  export { DIFF_LIST_LABELS, DiffList } from './chunk-LFHCXZO5.js';
97
+ export { DescriptionList, DescriptionListItem } from './chunk-F2XSYBKH.js';
98
98
  export { Combobox } from './chunk-QS4ZGTEU.js';
99
99
  export { CommandPalette } from './chunk-GTLJXJ3U.js';
100
100
  export { ConfirmModal, Modal } from './chunk-F4DPAJCN.js';
@@ -140,9 +140,8 @@ export { ARTIFACT_KINDS, ArtifactCard, ArtifactKindGlyph } from './chunk-6J35F33
140
140
  export { PRINCIPAL_KINDS, PrincipalAvatar } from './chunk-4KP4RC3O.js';
141
141
  export { RelativeTime, currentNow, formatElapsed, formatExact, formatRelative, formatUntil, toISO, toInstant, useNow } from './chunk-3CZ7XAVY.js';
142
142
  export { EMPTY_VALUE, EmptyValue } from './chunk-EUCC37WY.js';
143
- export { AuthLayout } from './chunk-WHZFDS62.js';
144
- export { BrandLockup } from './chunk-7KBNFFM3.js';
145
143
  export { AvatarStack, avatarStackLabel } from './chunk-UAN5NE7M.js';
144
+ export { AuthLayout } from './chunk-WHZFDS62.js';
146
145
  export { AvatarPicker } from './chunk-PRNX5AFE.js';
147
146
  export { HuePicker } from './chunk-SGIQCI6Y.js';
148
147
  export { SegmentedControl } from './chunk-RCQXUT5K.js';
@@ -152,6 +151,7 @@ export { NODE_HUES, NODE_HUE_NAMES, isNodeHue } from './chunk-AYKXMIOR.js';
152
151
  export { CHARACTER_PICKER_COLUMNS, CharacterPicker } from './chunk-HVIX5ECM.js';
153
152
  import './chunk-RKKO7QHH.js';
154
153
  export { AVATAR_CHARACTER_FULL_DETAIL, AVATAR_CORNER_RATIO, AVATAR_SIZES, AVATAR_STATUSES, AVATAR_STATUS_LABELS, Avatar, avatarCorner, avatarInitialsName, avatarPixels, avatarTint, getInitials } from './chunk-5OM447RW.js';
154
+ export { BrandLockup } from './chunk-7KBNFFM3.js';
155
155
  export { ACCESS_DENIED_REASONS, AccessDeniedCard } from './chunk-G3EEUNZQ.js';
156
156
  export { EmptyState } from './chunk-RA2ULG6H.js';
157
157
  export { Card } from './chunk-YZCJ63JF.js';
@@ -167,9 +167,9 @@ export { Menu } from './chunk-UFKUWVMV.js';
167
167
  export { Button, ButtonLink } from './chunk-OG6CL3EB.js';
168
168
  export { LAYER_GAP, LAYER_REPOSITION_EVENT, LayerHost, outsideBounds, placePopup, useLayerContainer, viewportBounds } from './chunk-HMPFGIWM.js';
169
169
  export { focusables, isComposing, isModalLayerOpen, layerCount, useBodyScrollLock, useModalLayer, usePopupLayer } from './chunk-R25RGPUB.js';
170
- export { ArrangeBoard } from './chunk-QO7QEQKV.js';
171
170
  export { ArrangeFrame, useGridResize } from './chunk-DEJHAOC5.js';
172
171
  export { Announcer, announce, useAnnouncer } from './chunk-RSAQOKH3.js';
173
172
  export { IconButton } from './chunk-4FQT6ZAY.js';
174
173
  export { VisuallyHidden } from './chunk-BZFWDIV6.js';
174
+ export { ArrangeBoard } from './chunk-QO7QEQKV.js';
175
175
  export { cx } from './chunk-ODEQTPFM.js';
package/dist/styles.css CHANGED
@@ -20848,7 +20848,7 @@ svg.crewlet-select__chevron {
20848
20848
  }
20849
20849
 
20850
20850
 
20851
- /* SlideStage-XIOTMMRU.css */
20851
+ /* SlideStage-KGRRALXR.css */
20852
20852
  /*
20853
20853
  * SlideStage: a slide laid out at its authored size and scaled to its box.
20854
20854
  *
@@ -20867,6 +20867,22 @@ svg.crewlet-select__chevron {
20867
20867
  height: 100%;
20868
20868
  }
20869
20869
 
20870
+ /* Until it is measured, and wherever it is not (no layout), a view stage is
20871
+ its slide's shape at its width. In full screen it fills the box, sharing a
20872
+ flex column with the show's controls. */
20873
+ .crewlet-slide-stage--view {
20874
+ flex: none;
20875
+ aspect-ratio: var(--crewlet-slide-stage-ratio, 16 / 9);
20876
+ }
20877
+
20878
+ :fullscreen .crewlet-slide-stage--view,
20879
+ .crewlet-slide-stage--view:fullscreen {
20880
+ flex: 1 1 0;
20881
+ min-height: 0;
20882
+ height: 100%;
20883
+ aspect-ratio: auto;
20884
+ }
20885
+
20870
20886
  .crewlet-slide-stage__frame {
20871
20887
  position: absolute;
20872
20888
  top: 0;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crewlethq/ui",
3
- "version": "0.26.0",
3
+ "version": "0.27.1",
4
4
  "description": "Crewlet shared React components built on @crewlethq/tokens and @crewlethq/icons.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -42,8 +42,8 @@
42
42
  "clean": "rm -rf dist src/generated"
43
43
  },
44
44
  "dependencies": {
45
- "@crewlethq/icons": "0.26.0",
46
- "@crewlethq/tokens": "0.26.0",
45
+ "@crewlethq/icons": "0.27.1",
46
+ "@crewlethq/tokens": "0.27.1",
47
47
  "uqr": "0.1.3"
48
48
  },
49
49
  "peerDependencies": {
@@ -1,101 +0,0 @@
1
- import { isComposing } from './chunk-R25RGPUB.js';
2
- import { cx } from './chunk-ODEQTPFM.js';
3
- import './SlideStage-XIOTMMRU.css';
4
- import { useRef, useState, useLayoutEffect, useEffect } from 'react';
5
- import { jsx } from 'react/jsx-runtime';
6
-
7
- var SLIDE_WIDTH = 1920;
8
- var SLIDE_HEIGHT = 1080;
9
- function SlideStage({
10
- children,
11
- label,
12
- fit = "width",
13
- scale,
14
- width = SLIDE_WIDTH,
15
- height = SLIDE_HEIGHT,
16
- className
17
- }) {
18
- const box = useRef(null);
19
- const [measured, setMeasured] = useState({
20
- scale: 0,
21
- left: 0,
22
- top: 0
23
- });
24
- useLayoutEffect(() => {
25
- const el = box.current;
26
- if (!el || scale !== void 0) return void 0;
27
- const read = () => {
28
- const w = el.clientWidth;
29
- const h = el.clientHeight;
30
- if (fit === "contain") {
31
- const s2 = Math.min(w / width, h / height);
32
- setMeasured({ scale: s2, left: (w - width * s2) / 2, top: (h - height * s2) / 2 });
33
- } else {
34
- setMeasured({ scale: w / width, left: 0, top: 0 });
35
- }
36
- };
37
- read();
38
- if (typeof ResizeObserver === "undefined") return void 0;
39
- const observer = new ResizeObserver(read);
40
- observer.observe(el);
41
- return () => observer.disconnect();
42
- }, [fit, scale, width, height]);
43
- const s = scale ?? measured.scale;
44
- const boxStyle = fit === "width" || scale !== void 0 ? { aspectRatio: `${width} / ${height}`, ...scale !== void 0 ? { width: width * scale } : {} } : {};
45
- const frameStyle = {
46
- width,
47
- height,
48
- transform: `translate(${scale === void 0 ? measured.left : 0}px, ${scale === void 0 ? measured.top : 0}px) scale(${s})`,
49
- // Hidden until measured, so a slide is never painted at full size for
50
- // one frame inside a thumbnail.
51
- visibility: s > 0 ? "visible" : "hidden"
52
- };
53
- return /* @__PURE__ */ jsx(
54
- "div",
55
- {
56
- ref: box,
57
- className: cx("crewlet-slide-stage", `crewlet-slide-stage--${fit}`, className),
58
- style: boxStyle,
59
- role: "group",
60
- "aria-roledescription": "slide",
61
- "aria-label": label,
62
- children: /* @__PURE__ */ jsx("div", { className: "crewlet-slide-stage__frame", style: frameStyle, children })
63
- }
64
- );
65
- }
66
- function typing(target) {
67
- if (!(target instanceof HTMLElement)) return false;
68
- return target.isContentEditable || ["INPUT", "TEXTAREA", "SELECT"].includes(target.tagName);
69
- }
70
- function useSlideKeys({ onNext, onPrevious, onFirst, onLast, onExit, enabled = true }) {
71
- useEffect(() => {
72
- if (!enabled) return void 0;
73
- const onKeyDown = (event) => {
74
- if (event.defaultPrevented || isComposing(event) || typing(event.target)) return;
75
- if (event.altKey || event.ctrlKey || event.metaKey) return;
76
- const act = {
77
- ArrowRight: onNext,
78
- ArrowDown: onNext,
79
- PageDown: onNext,
80
- " ": onNext,
81
- Enter: onNext,
82
- ArrowLeft: onPrevious,
83
- ArrowUp: onPrevious,
84
- PageUp: onPrevious,
85
- Backspace: onPrevious,
86
- Home: onFirst,
87
- End: onLast,
88
- Escape: onExit
89
- };
90
- const fn = act[event.key];
91
- if (!fn) return;
92
- if ((event.key === "Enter" || event.key === " ") && event.target instanceof HTMLButtonElement) return;
93
- event.preventDefault();
94
- fn();
95
- };
96
- document.addEventListener("keydown", onKeyDown);
97
- return () => document.removeEventListener("keydown", onKeyDown);
98
- }, [enabled, onNext, onPrevious, onFirst, onLast, onExit]);
99
- }
100
-
101
- export { SLIDE_HEIGHT, SLIDE_WIDTH, SlideStage, useSlideKeys };