@draftably/runtime 0.4.0 → 0.5.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.
@@ -9,7 +9,7 @@ import type { Footnote } from './footnote.js';
9
9
  import type { Note } from './note.js';
10
10
  import { type FontRole, type TypeProfile } from './fonts.js';
11
11
  import type { FileConfig } from './link.js';
12
- export type ThemeId = 'drafting' | 'fieldnotes' | 'signal' | 'ink' | 'blueprint';
12
+ export type ThemeId = 'drafting' | 'fieldnotes' | 'signal' | 'ink' | 'blueprint' | 'drafting-dark';
13
13
  export declare const THEME_IDS: ThemeId[];
14
14
  export declare const DEFAULT_THEME: ThemeId;
15
15
  /** Shade stops. Lower numbers are lighter and higher numbers darker, in every theme. */
@@ -154,6 +154,13 @@ interface Preset {
154
154
  hues?: Partial<Record<string, [number, number]>>;
155
155
  }
156
156
  export declare const PRESETS: Record<ThemeId, Preset>;
157
+ /**
158
+ * The appearance to draw on a page of this scheme. The default theme follows the page, with or
159
+ * without a `theme drafting` line and its size and font overrides: dark draws it as
160
+ * `drafting-dark`. Another named theme, a `theme-color` line or a color override on the `theme`
161
+ * line keeps the file's colors on every page.
162
+ */
163
+ export declare function forScheme(appearance: DiagramAppearance, dark: boolean): DiagramAppearance;
157
164
  /** `a` moved toward `b` by `t` (0–1), in sRGB. */
158
165
  export declare function mixColors(a: string, b: string, t: number): string;
159
166
  export declare function contrast(a: string, b: string): number;
@@ -0,0 +1,15 @@
1
+ /** Watches one host's scheme. `check` reads it again now; `stop` ends the watch. */
2
+ export interface SchemeWatch {
3
+ check(): void;
4
+ stop(): void;
5
+ }
6
+ /**
7
+ * Calls `onChange(dark)` now and whenever the scheme in `host` changes: an element, or a shadow
8
+ * root, whose children inherit the element's scheme. A hidden probe in `host` has a `light-dark()`
9
+ * color, so a scheme change anywhere above it (a class flip on the page, a style) starts a
10
+ * transition there; the media query covers a change of system setting under `light dark`. A
11
+ * transition cannot run while the host has no box (a hidden tab, a closed `<details>`, a detached
12
+ * mount), so a resize observer on the host reads the scheme again when it gets one. Callers also
13
+ * call `check` after each commit.
14
+ */
15
+ export declare function watchColorScheme(host: Element | ShadowRoot, onChange: (dark: boolean) => void): SchemeWatch;
@@ -3,6 +3,7 @@
3
3
  * packages loop over `HOST_EVENTS`, so a new event adds no lines to any of them.
4
4
  * This module has no side effects and no runtime imports.
5
5
  */
6
+ import type { RenderFailure } from './types.js';
6
7
  import type { UpdateResult, ViewerEvents } from './viewer.js';
7
8
  export type { Camera, CameraReason, FrameOptions, MoveResult } from './camera.js';
8
9
  export type { Box, EdgeOut, Geometry, PlacedBox } from './geometry.js';
@@ -10,8 +11,11 @@ export type { Anchor, DraftSlot } from './anchors.js';
10
11
  export interface HostEvents {
11
12
  /** After each commit, after the marked children change, and with `[]` before destroy. */
12
13
  anchors: ViewerEvents['anchors'];
13
- /** Each update's result: committed, error or a cancellation. */
14
- update: UpdateResult;
14
+ /**
15
+ * Each update's result, from the first source on: committed, error or a cancellation. The
16
+ * editor's commit has no `value` or `diagnostics` (see `EditorUpdate`).
17
+ */
18
+ update: UpdateResult | EditorUpdate;
15
19
  render: ViewerEvents['render'];
16
20
  diagnostics: ViewerEvents['diagnostics'];
17
21
  camera: ViewerEvents['camera'];
@@ -30,11 +34,39 @@ export interface HostEvents {
30
34
  source: string;
31
35
  };
32
36
  }
37
+ /**
38
+ * `<draft-editor>`'s update. The editor draws in its own session, not as one SVG, so a commit
39
+ * has no `value` and no `diagnostics`: the `diagnostics` event has them. A source that does not
40
+ * parse is an `error` with a `DRAFT_PARSE` diagnostic; the editor keeps the text and shows it.
41
+ */
42
+ export type EditorUpdate = {
43
+ status: 'committed';
44
+ revision: number;
45
+ value?: never;
46
+ diagnostics?: never;
47
+ } | {
48
+ status: 'error';
49
+ revision: number;
50
+ error: RenderFailure;
51
+ } | {
52
+ status: 'destroyed';
53
+ revision: number;
54
+ };
33
55
  export type HostEventName = keyof HostEvents;
34
56
  /** Every event, in one list. Each element dispatches these as bubbling `draft-<name>` events. */
35
57
  export declare const HOST_EVENTS: readonly ["anchors", "update", "render", "diagnostics", "camera", "itemactivate", "link", "contextmenu", "select", "change"];
36
58
  /** Events a host can cancel with `preventDefault()`. */
59
+ export type CancelableEventName = 'link' | 'contextmenu';
37
60
  export declare const CANCELABLE_EVENTS: readonly HostEventName[];
61
+ /**
62
+ * What a framework event prop receives: the event's `detail`, and on a cancelable event a
63
+ * `preventDefault()` that cancels the DOM event, so `onLink={e => e.preventDefault()}` works.
64
+ */
65
+ export type HostEventDetail<K extends HostEventName> = K extends CancelableEventName ? HostEvents[K] & {
66
+ preventDefault(): void;
67
+ } : HostEvents[K];
68
+ /** The value a framework event prop receives for a `draft-<name>` event. */
69
+ export declare function hostDetail(event: Event): unknown;
38
70
  export type DraftEventMap = {
39
71
  [K in HostEventName as `draft-${K}`]: CustomEvent<HostEvents[K]>;
40
72
  };
@@ -4,7 +4,7 @@
4
4
  */
5
5
  import type { RenderOptions, RenderResult } from './types.js';
6
6
  /** Names the worker and the usual fix, so "worker failed" is not a dead end. */
7
- export declare const WORKER_HELP = "The worker is the module next to @draftably/runtime's viewer. With Vite, add optimizeDeps: { exclude: ['@draftably/runtime', '@draftably/editor'] } to vite.config.";
7
+ export declare const WORKER_HELP = "The worker is the module next to @draftably/runtime's viewer. With Vite 5\u20137, add optimizeDeps: { exclude: ['@draftably/runtime', '@draftably/editor'] } to vite.config.";
8
8
  /**
9
9
  * Render in the page's worker pool. Jobs queue on the main thread; an aborted job leaves the
10
10
  * queue before a worker sees it. A job that runs past `timeoutMs` stops its worker only.
@@ -0,0 +1,2 @@
1
+ /** Both drawings as one, or null when they differ in more than color. */
2
+ export declare function mergeSchemes(light: string, dark: string): string | null;
@@ -26,10 +26,15 @@ export interface SvgOptions {
26
26
  rects: Map<string, Rect>;
27
27
  routes: Route[];
28
28
  }) => void;
29
+ /**
30
+ * The routes `onDrawn` gave for this document, so drawing it again in other colors routes
31
+ * nothing again (not for compare or states).
32
+ */
33
+ routes?: Route[];
29
34
  }
30
35
  export declare class SvgLimitError extends Error {
31
36
  }
32
- type Route = ReturnType<typeof computeRoutes>['routes'][number];
37
+ export type Route = ReturnType<typeof computeRoutes>['routes'][number];
33
38
  /**
34
39
  * A sequence diagram's panel, a light surface with a border that bounds the exchange, and a row
35
40
  * band for each phase with its label in a tab at the left edge. Drawn under everything else.
@@ -43,4 +48,3 @@ export declare const PHASE_TAB = 8;
43
48
  /** A thin stripe across the top of a box, inside its rounded corners. */
44
49
  export declare function accentPath(r: Rect, radius: number): string;
45
50
  export declare function renderSvg(doc: Diagram, opts?: SvgOptions): string;
46
- export {};
@@ -49,6 +49,13 @@ export interface CommonRenderOptions {
49
49
  sourceId?: string;
50
50
  signal?: AbortSignal;
51
51
  limits?: Partial<RenderLimits>;
52
+ /**
53
+ * `light` (default) draws the file's own colors. `dark` draws a file without a `theme` line in
54
+ * the default theme's dark variant. `auto` writes both as `light-dark()` colors, so the page's
55
+ * `color-scheme` picks one; the viewer and `<draft-diagram>` use it. A file's own theme line
56
+ * always wins.
57
+ */
58
+ colorScheme?: 'light' | 'dark' | 'auto';
52
59
  }
53
60
  export type RenderOptions = CommonRenderOptions & ({
54
61
  target?: 'image';
@@ -0,0 +1,4 @@
1
+ const n = "0.5.0", o = n;
2
+ export {
3
+ o as r
4
+ };
package/dist/viewer.css CHANGED
@@ -3,13 +3,14 @@
3
3
  * They inherit through the shadow root; the defaults below apply only when unset.
4
4
  */
5
5
  .draft-viewer {
6
- --dv-border: var(--draft-border, #cbd5e1);
7
- --dv-ink: var(--draft-ink, #1e293b);
8
- --dv-bg: var(--draft-bg, #fff);
9
- --dv-focus: var(--draft-focus, #2563eb);
10
- --dv-shadow: var(--draft-shadow, rgb(15 23 42 / 0.12));
11
- --dv-warning-ink: var(--draft-warning-ink, #9a3412);
12
- --dv-warning-bg: var(--draft-warning-bg, #fff7ed);
6
+ /* The viewer sets color-scheme from the page; each default has a dark value. */
7
+ --dv-border: var(--draft-border, light-dark(#cbd5e1, #3d4450));
8
+ --dv-ink: var(--draft-ink, light-dark(#1e293b, #e7eaef));
9
+ --dv-bg: var(--draft-bg, light-dark(#fff, #16191e));
10
+ --dv-focus: var(--draft-focus, light-dark(#2563eb, #7fa4e6));
11
+ --dv-shadow: var(--draft-shadow, light-dark(rgb(15 23 42 / 0.12), rgb(0 0 0 / 0.4)));
12
+ --dv-warning-ink: var(--draft-warning-ink, light-dark(#9a3412, #fdba74));
13
+ --dv-warning-bg: var(--draft-warning-bg, light-dark(#fff7ed, #431407));
13
14
  position: relative;
14
15
  display: grid;
15
16
  grid-template-rows: auto minmax(8rem, 1fr) auto auto;
@@ -126,7 +127,7 @@
126
127
  }
127
128
 
128
129
  /* The anchor layer: slot targets above the drawing. Slot content takes no pointer input unless
129
- it is marked data-draft-input (host.css). */
130
+ it is marked data-draft-input. */
130
131
  .draft-anchors {
131
132
  position: absolute;
132
133
  inset: 0;
@@ -150,6 +151,11 @@
150
151
  box-sizing: border-box;
151
152
  pointer-events: none;
152
153
  }
154
+ /* Marked content in a mountViewer target, in the page's DOM. The element's slotted content gets the
155
+ same rule from host.css, because these selectors do not reach into slots. */
156
+ .draft-anchor [data-draft-input] {
157
+ pointer-events: auto;
158
+ }
153
159
  .draft-anchor--body {
154
160
  overflow: clip;
155
161
  }