foss-design 0.9.9 → 0.9.11

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.
@@ -42,6 +42,15 @@
42
42
  --tw-drop-shadow-color: initial;
43
43
  --tw-drop-shadow-alpha: 100%;
44
44
  --tw-drop-shadow-size: initial;
45
+ --tw-backdrop-blur: initial;
46
+ --tw-backdrop-brightness: initial;
47
+ --tw-backdrop-contrast: initial;
48
+ --tw-backdrop-grayscale: initial;
49
+ --tw-backdrop-hue-rotate: initial;
50
+ --tw-backdrop-invert: initial;
51
+ --tw-backdrop-opacity: initial;
52
+ --tw-backdrop-saturate: initial;
53
+ --tw-backdrop-sepia: initial;
45
54
  --tw-duration: initial;
46
55
  --tw-ease: initial;
47
56
  }
@@ -58,11 +67,13 @@
58
67
  --font-weight-semibold: 600;
59
68
  --tracking-wide: .025em;
60
69
  --leading-tight: 1.25;
70
+ --leading-snug: 1.375;
61
71
  --ease-in: cubic-bezier(.4, 0, 1, 1);
62
72
  --ease-out: cubic-bezier(0, 0, .2, 1);
63
73
  --ease-in-out: cubic-bezier(.4, 0, .2, 1);
64
74
  --animate-spin: spin 1s linear infinite;
65
75
  --animate-pulse: pulse 2s cubic-bezier(.4, 0, .6, 1) infinite;
76
+ --blur-sm: 8px;
66
77
  --default-transition-duration: .15s;
67
78
  --default-transition-timing-function: cubic-bezier(.4, 0, .2, 1);
68
79
  --default-font-family: "IBM Plex Sans", system-ui, sans-serif;
@@ -442,6 +453,10 @@
442
453
  position: sticky;
443
454
  }
444
455
 
456
+ .-inset-px {
457
+ inset: -1px;
458
+ }
459
+
445
460
  .inset-0 {
446
461
  inset: 0;
447
462
  }
@@ -470,6 +485,10 @@
470
485
  top: 50%;
471
486
  }
472
487
 
488
+ .top-3 {
489
+ top: calc(var(--spacing) * 3);
490
+ }
491
+
473
492
  .top-4 {
474
493
  top: calc(var(--spacing) * 4);
475
494
  }
@@ -482,6 +501,10 @@
482
501
  top: 52px;
483
502
  }
484
503
 
504
+ .right-3 {
505
+ right: calc(var(--spacing) * 3);
506
+ }
507
+
485
508
  .right-4 {
486
509
  right: calc(var(--spacing) * 4);
487
510
  }
@@ -1033,6 +1056,10 @@
1033
1056
  max-width: 1440px;
1034
1057
  }
1035
1058
 
1059
+ .max-w-\[calc\(100\%-24px\)\] {
1060
+ max-width: calc(100% - 24px);
1061
+ }
1062
+
1036
1063
  .max-w-\[calc\(100vw-24px\)\] {
1037
1064
  max-width: calc(100vw - 24px);
1038
1065
  }
@@ -1364,6 +1391,11 @@
1364
1391
  border-width: 0;
1365
1392
  }
1366
1393
 
1394
+ .border-2 {
1395
+ border-style: var(--tw-border-style);
1396
+ border-width: 2px;
1397
+ }
1398
+
1367
1399
  .border-t {
1368
1400
  border-top-style: var(--tw-border-style);
1369
1401
  border-top-width: 1px;
@@ -1389,6 +1421,10 @@
1389
1421
  border-style: dashed;
1390
1422
  }
1391
1423
 
1424
+ .border-action {
1425
+ border-color: var(--action);
1426
+ }
1427
+
1392
1428
  .border-action-line {
1393
1429
  border-color: var(--action-line);
1394
1430
  }
@@ -1522,6 +1558,16 @@
1522
1558
  }
1523
1559
  }
1524
1560
 
1561
+ .bg-surface\/90 {
1562
+ background-color: var(--surface);
1563
+ }
1564
+
1565
+ @supports (color: color-mix(in lab, red, red)) {
1566
+ .bg-surface\/90 {
1567
+ background-color: color-mix(in oklab, var(--surface) 90%, transparent);
1568
+ }
1569
+ }
1570
+
1525
1571
  .bg-track {
1526
1572
  background-color: var(--track);
1527
1573
  }
@@ -1924,6 +1970,11 @@
1924
1970
  line-height: 1;
1925
1971
  }
1926
1972
 
1973
+ .leading-snug {
1974
+ --tw-leading: var(--leading-snug);
1975
+ line-height: var(--leading-snug);
1976
+ }
1977
+
1927
1978
  .leading-tight {
1928
1979
  --tw-leading: var(--leading-tight);
1929
1980
  line-height: var(--leading-tight);
@@ -1979,6 +2030,10 @@
1979
2030
  white-space: pre-wrap;
1980
2031
  }
1981
2032
 
2033
+ .\!text-ok-text {
2034
+ color: var(--ok-text) !important;
2035
+ }
2036
+
1982
2037
  .text-action {
1983
2038
  color: var(--action);
1984
2039
  }
@@ -2066,6 +2121,11 @@
2066
2121
  box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
2067
2122
  }
2068
2123
 
2124
+ .shadow-\[0_1px_3px_rgb\(0_0_0\/0\.08\)\] {
2125
+ --tw-shadow: 0 1px 3px var(--tw-shadow-color, #00000014);
2126
+ box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
2127
+ }
2128
+
2069
2129
  .shadow-\[inset_0_0_0_1px_rgba\(0\,0\,0\,0\.1\)\] {
2070
2130
  --tw-shadow: inset 0 0 0 1px var(--tw-shadow-color, #0000001a);
2071
2131
  box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
@@ -2091,6 +2151,11 @@
2091
2151
  box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
2092
2152
  }
2093
2153
 
2154
+ .ring {
2155
+ --tw-ring-shadow: var(--tw-ring-inset, ) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor);
2156
+ box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
2157
+ }
2158
+
2094
2159
  .outline {
2095
2160
  outline-style: var(--tw-outline-style);
2096
2161
  outline-width: 1px;
@@ -2121,14 +2186,26 @@
2121
2186
  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, );
2122
2187
  }
2123
2188
 
2189
+ .backdrop-blur-sm {
2190
+ --tw-backdrop-blur: blur(var(--blur-sm));
2191
+ -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, );
2192
+ 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, );
2193
+ }
2194
+
2124
2195
  .transition {
2125
2196
  transition-property: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to, opacity, box-shadow, transform, translate, scale, rotate, filter, -webkit-backdrop-filter, backdrop-filter, display, content-visibility, overlay, pointer-events;
2126
2197
  transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));
2127
2198
  transition-duration: var(--tw-duration, var(--default-transition-duration));
2128
2199
  }
2129
2200
 
2130
- .transition-\[background-color\,opacity\] {
2131
- transition-property: background-color, opacity;
2201
+ .transition-\[background-color\,opacity\,scale\] {
2202
+ transition-property: background-color, opacity, scale;
2203
+ transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));
2204
+ transition-duration: var(--tw-duration, var(--default-transition-duration));
2205
+ }
2206
+
2207
+ .transition-\[color\,background-color\,scale\] {
2208
+ transition-property: color, background-color, scale;
2132
2209
  transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));
2133
2210
  transition-duration: var(--tw-duration, var(--default-transition-duration));
2134
2211
  }
@@ -2208,12 +2285,6 @@
2208
2285
  user-select: none;
2209
2286
  }
2210
2287
 
2211
- @media (hover: hover) {
2212
- .group-hover\:opacity-100:is(:where(.group):hover *) {
2213
- opacity: 1;
2214
- }
2215
- }
2216
-
2217
2288
  .placeholder\:text-muted::placeholder {
2218
2289
  color: var(--muted);
2219
2290
  }
@@ -2223,10 +2294,6 @@
2223
2294
  border-top-width: 0;
2224
2295
  }
2225
2296
 
2226
- .focus-within\:opacity-100:focus-within {
2227
- opacity: 1;
2228
- }
2229
-
2230
2297
  .focus-within\:outline-2:focus-within {
2231
2298
  outline-style: var(--tw-outline-style);
2232
2299
  outline-width: 2px;
@@ -2282,6 +2349,14 @@
2282
2349
  background-color: var(--soft2);
2283
2350
  }
2284
2351
 
2352
+ .active\:not-disabled\:scale-\[0\.94\]:active:not(:disabled) {
2353
+ scale: .94;
2354
+ }
2355
+
2356
+ .active\:not-disabled\:scale-\[0\.97\]:active:not(:disabled) {
2357
+ scale: .97;
2358
+ }
2359
+
2285
2360
  .disabled\:cursor-not-allowed:disabled {
2286
2361
  cursor: not-allowed;
2287
2362
  }
@@ -3270,6 +3345,51 @@
3270
3345
  inherits: false
3271
3346
  }
3272
3347
 
3348
+ @property --tw-backdrop-blur {
3349
+ syntax: "*";
3350
+ inherits: false
3351
+ }
3352
+
3353
+ @property --tw-backdrop-brightness {
3354
+ syntax: "*";
3355
+ inherits: false
3356
+ }
3357
+
3358
+ @property --tw-backdrop-contrast {
3359
+ syntax: "*";
3360
+ inherits: false
3361
+ }
3362
+
3363
+ @property --tw-backdrop-grayscale {
3364
+ syntax: "*";
3365
+ inherits: false
3366
+ }
3367
+
3368
+ @property --tw-backdrop-hue-rotate {
3369
+ syntax: "*";
3370
+ inherits: false
3371
+ }
3372
+
3373
+ @property --tw-backdrop-invert {
3374
+ syntax: "*";
3375
+ inherits: false
3376
+ }
3377
+
3378
+ @property --tw-backdrop-opacity {
3379
+ syntax: "*";
3380
+ inherits: false
3381
+ }
3382
+
3383
+ @property --tw-backdrop-saturate {
3384
+ syntax: "*";
3385
+ inherits: false
3386
+ }
3387
+
3388
+ @property --tw-backdrop-sepia {
3389
+ syntax: "*";
3390
+ inherits: false
3391
+ }
3392
+
3273
3393
  @property --tw-duration {
3274
3394
  syntax: "*";
3275
3395
  inherits: false
@@ -326,6 +326,18 @@ export type RuntimeMessage = {
326
326
  type: 'keydown';
327
327
  code: string;
328
328
  }
329
+ /**
330
+ * Where the pointer is in the frame, once the viewer asked with `pointer` (0.9.11+): on moves (at
331
+ * most once a frame), `down` on a press (a tap on a touch screen), -1, -1 when it leaves.
332
+ */
333
+ | {
334
+ source: 'design-runtime';
335
+ key: string;
336
+ type: 'pointer';
337
+ x: number;
338
+ y: number;
339
+ down: boolean;
340
+ }
329
341
  /** ⌘/Ctrl pressed or released in the frame, or a key pressed while one is down. */
330
342
  | {
331
343
  source: 'design-runtime';
@@ -365,6 +377,11 @@ export type ViewerMessage = {
365
377
  source: 'design-viewer';
366
378
  type: 'canvas';
367
379
  }
380
+ /** Report the pointer: the viewer shows its controls when the pointer nears them over the frame. */
381
+ | {
382
+ source: 'design-viewer';
383
+ type: 'pointer';
384
+ }
368
385
  /** Inspect mode on or off; `tokens` let the frame name the tokens behind computed styles. */
369
386
  | {
370
387
  source: 'design-viewer';
@@ -11,10 +11,17 @@ export interface DesignViewerProps {
11
11
  base?: string;
12
12
  /** The `sandbox` attribute for every frame; none when unset. */
13
13
  frameSandbox?: string;
14
+ /**
15
+ * The `allow` attribute (permissions policy) for every frame; `clipboard-read; clipboard-write;
16
+ * fullscreen` when unset, as the local viewer has it. A permission the user grants is the
17
+ * embedding page's and then holds for every frame, so a host that shows screens from others
18
+ * should grant less, such as `clipboard-write` alone.
19
+ */
20
+ frameAllow?: string;
14
21
  slots?: ViewerSlots;
15
22
  scope?: ViewerScope;
16
23
  /** Shared with the embedding app; the viewer makes its own when unset. */
17
24
  queryClient?: QueryClient;
18
25
  }
19
26
  /** The whole viewer: home, canvases, screens and the design system of one project. */
20
- export declare function DesignViewer({ source, base, frameSandbox, slots, scope, queryClient }: DesignViewerProps): import("react").JSX.Element;
27
+ export declare function DesignViewer({ source, base, frameSandbox, frameAllow, slots, scope, queryClient, }: DesignViewerProps): import("react").JSX.Element;
@@ -0,0 +1,21 @@
1
+ import { type ReactNode } from 'react';
2
+ /**
3
+ * A plate in the top-right corner over a full-window frame. It shows while the screen loads and for a
4
+ * few seconds after, then fades out; a pointer in the window's top-right quarter brings it back and
5
+ * keeps it while it stays there, a tap there shows it for a while, and so does focus inside it.
6
+ *
7
+ * The page does not see the pointer over the frame, so the frame's runtime reports it (0.9.11+).
8
+ * Until a frame does (an older runtime, a URL item), the plate shows whenever the pointer is over the
9
+ * page, as before.
10
+ */
11
+ export declare function CornerPlate({ frame, note, badge, children, }: {
12
+ frame: HTMLIFrameElement | null;
13
+ /** A muted line under the plate's controls: whose content the screen is. */
14
+ note?: ReactNode;
15
+ /**
16
+ * Instead of fading out, the plate folds into this small badge, which a click opens again: for pages
17
+ * anyone can open, so a screen can never pass for the app around it.
18
+ */
19
+ badge?: ReactNode;
20
+ children?: ReactNode;
21
+ }): import("react").JSX.Element;
@@ -0,0 +1,5 @@
1
+ import { type ReactNode } from 'react';
2
+ /** One page that throws shows what went wrong in its place, instead of blanking the whole viewer. */
3
+ export declare function PageBoundary({ children }: {
4
+ children: ReactNode;
5
+ }): import("react").JSX.Element;
@@ -1,4 +1,7 @@
1
- /** http, https, mailto or relative. Browsers drop whitespace and control characters inside a scheme, so do we. */
1
+ /**
2
+ * http, https, mailto or relative, read as the browser reads a URL (it drops whitespace and
3
+ * control characters inside a scheme, and so does URL parsing).
4
+ */
2
5
  export declare function isSafeHref(href: string): boolean;
3
6
  export declare function renderMarkdown(text: string): string;
4
7
  /** Markdown from the project's own files (guidelines, notes, descriptions). */
@@ -23,13 +23,19 @@ export declare function reloadFrame(frame: HTMLIFrameElement | null): void;
23
23
  * process, so frames served from the viewer's twin host (localhost ↔ 127.0.0.1,
24
24
  * both reach the same server) run their scripts and animations off the viewer's
25
25
  * thread: a canvas full of live screens still pans smoothly. Any other host,
26
- * and static builds, keep frames on the viewer's origin.
26
+ * and static builds, keep frames on the viewer's origin. The dev server keeps
27
+ * its viewer on localhost and gives 127.0.0.1 to frames (server/hosts.ts).
27
28
  */
28
29
  export declare const FRAME_ORIGIN: string;
29
30
  /** A frame URL with the theme it should open in. */
30
31
  export declare function frameSrc(url: string, theme: Theme, extra?: Record<string, string>): string;
31
32
  /** Absolute URL for opening a frame in a new tab. */
32
33
  export declare function absoluteUrl(url: string): string;
34
+ /** A screen a link can lead to: its id and the app routes it shows. */
35
+ export interface LinkTarget {
36
+ id: string;
37
+ routes?: string[];
38
+ }
33
39
  /**
34
40
  * A link, form or history push the runtime kept from leaving its frame. The path goes to the
35
41
  * screen whose `route` matches it best (a relative `href` resolves against the route of the
@@ -39,5 +45,7 @@ export declare function absoluteUrl(url: string): string;
39
45
  */
40
46
  export declare function followLink(message: Extract<RuntimeMessage, {
41
47
  type: 'link';
42
- }>, canvas: CanvasDoc, go: (id: string) => void, from?: string): void;
48
+ }>, canvas: CanvasDoc | LinkTarget[], go: (id: string) => void, from?: string,
49
+ /** A link to a path no screen has; a toast says so by default. */
50
+ missing?: (path: string) => void): void;
43
51
  export {};
@@ -0,0 +1,12 @@
1
+ import type { RuntimeMessage } from '../../../src/shared/types';
2
+ /**
3
+ * Frames run code anyone who can push wrote, and any of them may post the viewer anything: a
4
+ * message only reaches the viewer's handlers with the fields its type has, of their types.
5
+ * Strings are cut and sizes kept within reason, so a frame cannot swell the viewer's state.
6
+ */
7
+ export declare const MAX_FRAME_SIZE = 100000;
8
+ export declare const MAX_FRAME_ERRORS = 20;
9
+ /** `data` as a runtime message, with its sizes and texts bounded; null when it is none. */
10
+ export declare function readRuntimeMessage(data: unknown): RuntimeMessage | null;
11
+ /** A frame's error list with `message` added: once, and no more than `MAX_FRAME_ERRORS` of them. */
12
+ export declare function withError(list: string[], message: string): string[];
@@ -37,9 +37,15 @@ export declare class ApiError extends Error {
37
37
  export declare const localSource: ViewerSource;
38
38
  /** The JSON files of a `design build` site, relative to its root. */
39
39
  export declare const staticSource: ViewerSource;
40
- /** `url` against a unit's base; an empty base leaves it as the doc has it. */
40
+ /**
41
+ * `url` against a unit's base, or '' when it may not be loaded. Docs come from builds anyone who
42
+ * can push has written, so a URL is only kept when it is http(s) and, for a unit build, inside
43
+ * that unit's base: a `javascript:` frame source would run with the viewer's own origin.
44
+ */
41
45
  export declare function resolveUrl(url: string, base: string): string;
42
- /** A canvas with its frame, snapshot and image URLs resolved against its unit's base. */
46
+ /** An external page for a `url` item: http or https only. */
47
+ export declare function externalUrl(url: string): string;
48
+ /** A canvas with its frame, snapshot and image URLs resolved against its unit's base, unsafe ones dropped. */
43
49
  export declare function resolveCanvas(doc: CanvasDoc, base: string): CanvasDoc;
44
50
  /** A design system with its specimen and asset URLs resolved against the system unit's base. */
45
51
  export declare function resolveSystem(doc: SystemDoc, base: string): SystemDoc;
@@ -28,6 +28,16 @@ export interface ViewerSlots {
28
28
  canvasesAfter?: ReactNode;
29
29
  /** Below the panels of the home page, full width. */
30
30
  homeAfter?: ReactNode;
31
+ /**
32
+ * On a screen's full-window page, the corner plate with the way out: `note` is a muted line under it
33
+ * (whose content the screen is), `actions` sit next to the way out, and with `badge` the plate folds
34
+ * into that badge instead of fading out (pages anyone can open).
35
+ */
36
+ fullPlate?: {
37
+ note?: ReactNode;
38
+ actions?: ReactNode;
39
+ badge?: ReactNode;
40
+ };
31
41
  }
32
42
  /** Single-canvas mode: only this canvas is reachable, without the design system or other canvases. */
33
43
  export interface ViewerScope {
@@ -43,10 +53,14 @@ export declare function viewerKeys(id: string): {
43
53
  source: (unit: string, path: string) => readonly ['design', string, 'source', string, string];
44
54
  };
45
55
  export type ViewerKeys = ReturnType<typeof viewerKeys>;
56
+ /** What frames of the local viewer may use: the clipboard, both ways, and fullscreen. */
57
+ export declare const DEFAULT_FRAME_ALLOW = "clipboard-read; clipboard-write; fullscreen";
46
58
  export interface Viewer {
47
59
  source: ViewerSource;
48
60
  keys: ViewerKeys;
49
61
  frameSandbox?: string;
62
+ /** The `allow` attribute (permissions policy) of every frame. */
63
+ frameAllow: string;
50
64
  slots: ViewerSlots;
51
65
  scope: ViewerScope | null;
52
66
  }
@@ -1,11 +1,13 @@
1
- export type { AssetDoc, CanvasDoc, CanvasItem, CanvasPage, CanvasSection, CanvasSummary, ComponentDoc, FrameSize, GuidelineDoc, ImageItem, Issue, NoteItem, ProjectInfo, ScreenItem, SystemDoc, SystemSummary, Theme, Token, TokenKind, TokenValue, UrlItem, } from '../../src/shared/types';
1
+ export type { AssetDoc, CanvasDoc, CanvasItem, CanvasPage, CanvasSection, CanvasSummary, ComponentDoc, FrameSize, GuidelineDoc, ImageItem, Issue, NoteItem, ProjectInfo, RuntimeMessage, ScreenItem, SystemDoc, SystemSummary, Theme, Token, TokenKind, TokenValue, UrlItem, } from '../../src/shared/types';
2
2
  export { DesignViewer, type DesignViewerProps } from './app';
3
+ export { CornerPlate } from './components/corner-plate';
3
4
  export { SlidePanel } from './components/slide-panel';
4
5
  export { ThemeMenu } from './components/theme-menu';
5
6
  export { Bar, useBarCompact } from './components/topbar';
6
7
  export { Mark, Wordmark } from './components/wordmark';
7
8
  export { cn } from './lib/cn';
8
9
  export { copyText } from './lib/copy';
10
+ export { followLink, frameSrc, type LinkTarget, listenToFrame, sendTheme } from './lib/frames';
9
11
  export { useIsPhone } from './lib/phone';
10
12
  export { ApiError, localSource, resolveUrl, staticSource, type ViewerSource } from './lib/source';
11
13
  export { setThemePref, type ThemePref, useTheme, useThemePref } from './lib/theme';
@@ -14,6 +16,7 @@ export { Avatar, initials } from './ui/avatar';
14
16
  export { Badge, Count, type Tone } from './ui/badge';
15
17
  export { Button, ButtonAnchor, type ButtonKind, ButtonLink, type ButtonProps, buttonClass, IconButton, type IconButtonProps, iconButtonClass, } from './ui/button';
16
18
  export { Segmented, Switch } from './ui/choice';
19
+ export { CopyButton } from './ui/copy-button';
17
20
  export { Dialog } from './ui/dialog';
18
21
  export { Icon, type IconName } from './ui/icon';
19
22
  export { floatingSurface, Menu, MenuItem, MenuLabel, MenuSeparator, menuItemClass, menuSurface } from './ui/menu';
@@ -7,7 +7,7 @@ export declare const fullHref: (canvas: string, item: string, theme: Theme) => s
7
7
  * tab gets the full-window page of the viewer; otherwise the screen's own URL.
8
8
  */
9
9
  export declare function useOpenUrl(canvasId: string, item: Frame | undefined, theme: Theme): string | null;
10
- /** `/c/:canvas/full/:item`: one screen filling the window, a way out on hover and Esc. */
10
+ /** `/c/:canvas/full/:item`: one screen filling the window, a way out in the top-right corner and on Esc. */
11
11
  export declare function FullPage({ canvasId, itemId }: {
12
12
  canvasId: string;
13
13
  itemId: string;
@@ -0,0 +1,7 @@
1
+ /** A ghost "Copy" button that turns into "Copied" with a check for a moment after it copies. */
2
+ export declare function CopyButton({ text, label, done, className, }: {
3
+ text: string;
4
+ label?: string;
5
+ done?: string;
6
+ className?: string;
7
+ }): import("react").JSX.Element;
@@ -1,10 +1,10 @@
1
- import type { ReactNode } from 'react';
1
+ import { type ReactNode } from 'react';
2
2
  /**
3
3
  * A modal over a dimmed page: focus stays inside until it closes, Escape and a
4
4
  * click outside close it. Head and foot are a panel's; `actions` go to the foot.
5
5
  * On a phone it is a sheet from the bottom edge with a handle: swiping it down closes it too.
6
6
  */
7
- export declare function Dialog({ open, onOpenChange, title, description, children, actions, footNote, below, width, }: {
7
+ export declare function Dialog({ open, onOpenChange, title, description, children, actions, footNote, below, width, step, }: {
8
8
  open: boolean;
9
9
  onOpenChange: (open: boolean) => void;
10
10
  title: ReactNode;
@@ -18,4 +18,9 @@ export declare function Dialog({ open, onOpenChange, title, description, childre
18
18
  /** Full-width content under the body, scrolling on its own: lists with row borders. */
19
19
  below?: ReactNode;
20
20
  width?: number;
21
+ /**
22
+ * The dialog's current step, for a dialog that turns into another one in place (a confirmation
23
+ * that becomes its result): a new value cross-fades the content while the panel eases to its size.
24
+ */
25
+ step?: string;
21
26
  }): import("react").JSX.Element;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "foss-design",
3
- "version": "0.9.9",
3
+ "version": "0.9.11",
4
4
  "description": "Design canvases and design systems for coding agents: live, animated, clickable screens on an infinite canvas, served locally from a .design folder.",
5
5
  "type": "module",
6
6
  "license": "MIT",