@draftably/editor 0.3.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.
Files changed (43) hide show
  1. package/README.md +5 -3
  2. package/dist/assets/engine.worker-BDrPGHQt.js +7634 -0
  3. package/dist/element.js +182 -17
  4. package/dist/index.js +8827 -7969
  5. package/dist/types/src/components/canvas/Canvas.d.ts +4 -0
  6. package/dist/types/src/components/scene/NodeView.d.ts +7 -0
  7. package/dist/types/src/components/scene/parts.d.ts +7 -11
  8. package/dist/types/src/components/session-context.d.ts +7 -1
  9. package/dist/types/src/dsl/cells.d.ts +1 -0
  10. package/dist/types/src/dsl/compile.d.ts +2 -1
  11. package/dist/types/src/dsl/legend-notes.d.ts +14 -0
  12. package/dist/types/src/dsl/syntax.d.ts +3 -1
  13. package/dist/types/src/dsl/translate.d.ts +1 -1
  14. package/dist/types/src/editor/css.d.ts +3 -0
  15. package/dist/types/src/editor/element.d.ts +8 -6
  16. package/dist/types/src/editor/internal.d.ts +486 -0
  17. package/dist/types/src/editor/mount.d.ts +77 -5
  18. package/dist/types/src/graph-api/core.d.ts +125 -0
  19. package/dist/types/src/model/appearance.d.ts +27 -1
  20. package/dist/types/src/model/colors.d.ts +10 -2
  21. package/dist/types/src/model/labels.d.ts +22 -6
  22. package/dist/types/src/runtime/anchors.d.ts +46 -0
  23. package/dist/types/src/runtime/camera.d.ts +41 -0
  24. package/dist/types/src/runtime/color-scheme.d.ts +15 -0
  25. package/dist/types/src/runtime/element-base.d.ts +40 -0
  26. package/dist/types/src/runtime/geometry.d.ts +72 -0
  27. package/dist/types/src/runtime/host.d.ts +78 -0
  28. package/dist/types/src/runtime/page-shared.d.ts +24 -0
  29. package/dist/types/src/runtime/policy.d.ts +7 -0
  30. package/dist/types/src/runtime/render.d.ts +10 -0
  31. package/dist/types/src/runtime/schemes.d.ts +2 -0
  32. package/dist/types/src/runtime/svg-renderer.d.ts +12 -0
  33. package/dist/types/src/runtime/types.d.ts +122 -0
  34. package/dist/types/src/runtime/version.d.ts +2 -0
  35. package/dist/types/src/runtime/viewer.d.ts +123 -0
  36. package/dist/types/src/state/active-session.d.ts +10 -1
  37. package/dist/types/src/state/dom-root.d.ts +8 -0
  38. package/dist/types/src/state/session/document.d.ts +3 -1
  39. package/dist/types/src/state/session/editor.d.ts +3 -2
  40. package/dist/types/src/state/session/emphasis.d.ts +3 -0
  41. package/dist/types/src/state/session/index.d.ts +13 -1
  42. package/package.json +1 -1
  43. package/dist/assets/engine.worker-BY9GKt7x.js +0 -7505
@@ -0,0 +1,122 @@
1
+ import type { Geometry } from './geometry';
2
+ export type Severity = 'error' | 'warning' | 'info';
3
+ export interface SourceLocation {
4
+ sourceId?: string;
5
+ line: number;
6
+ column?: number;
7
+ }
8
+ export interface Diagnostic {
9
+ code: string;
10
+ severity: Severity;
11
+ message: string;
12
+ location?: SourceLocation;
13
+ itemIds: readonly string[];
14
+ related?: readonly {
15
+ message: string;
16
+ location: SourceLocation;
17
+ }[];
18
+ nativeCode?: string;
19
+ }
20
+ export interface CompileLimits {
21
+ maxSourceChars: number;
22
+ maxSourceBytes: number;
23
+ maxObjects: number;
24
+ maxEdges: number;
25
+ maxDepth: number;
26
+ }
27
+ export interface RenderLimits extends CompileLimits {
28
+ maxOutputBytes: number;
29
+ }
30
+ export type LinkPolicy = {
31
+ mode: 'none';
32
+ } | {
33
+ mode: 'safe';
34
+ baseUrl?: string;
35
+ target?: '_self' | '_blank';
36
+ resolve?: (request: {
37
+ itemId: string;
38
+ href: string;
39
+ }) => string | null;
40
+ cacheKey?: string;
41
+ };
42
+ export interface CommonRenderOptions {
43
+ title?: string;
44
+ description?: string;
45
+ includeSource?: boolean;
46
+ links?: LinkPolicy;
47
+ styleNonce?: string;
48
+ state?: string | null;
49
+ sourceId?: string;
50
+ signal?: AbortSignal;
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';
59
+ }
60
+ export type RenderOptions = CommonRenderOptions & ({
61
+ target?: 'image';
62
+ idPrefix?: never;
63
+ fonts?: 'embed';
64
+ } | {
65
+ target: 'inline';
66
+ idPrefix: string;
67
+ fonts?: 'embed' | 'host';
68
+ });
69
+ export interface ValidateOptions {
70
+ sourceId?: string;
71
+ signal?: AbortSignal;
72
+ limits?: Partial<CompileLimits>;
73
+ }
74
+ export interface ItemSummary {
75
+ id: string;
76
+ kind: 'node' | 'group' | 'edge';
77
+ label: string;
78
+ line: number;
79
+ from?: string;
80
+ to?: string;
81
+ }
82
+ export interface DiagramSummary {
83
+ title: string;
84
+ description?: string;
85
+ width: number;
86
+ height: number;
87
+ viewBox: readonly [number, number, number, number];
88
+ items: readonly ItemSummary[];
89
+ states: readonly {
90
+ id: string;
91
+ label: string;
92
+ }[];
93
+ activeState: string | null;
94
+ }
95
+ export interface RenderedDiagram extends DiagramSummary {
96
+ svg: string;
97
+ /**
98
+ * Where each node, group and edge is drawn, in the SVG's own units (its `viewBox`), in the graph
99
+ * API's shapes. `null` for `compare` and `states` drawings, which repeat items across panels.
100
+ */
101
+ geometry: Geometry | null;
102
+ provenance: {
103
+ runtimeVersion: string;
104
+ dslVersion: 1;
105
+ fontMetricsVersion: string;
106
+ renderContextVersion: string;
107
+ };
108
+ }
109
+ export type RenderFailure = {
110
+ ok: false;
111
+ reason: 'input' | 'limit' | 'aborted' | 'environment' | 'internal';
112
+ diagnostics: readonly Diagnostic[];
113
+ };
114
+ export type RenderResult = {
115
+ ok: true;
116
+ value: RenderedDiagram;
117
+ diagnostics: readonly Diagnostic[];
118
+ } | RenderFailure;
119
+ export type ValidationResult = {
120
+ ok: true;
121
+ diagnostics: readonly Diagnostic[];
122
+ } | RenderFailure;
@@ -0,0 +1,2 @@
1
+ export declare const runtimeVersion: string;
2
+ export { fontMetricsVersion } from '../model/font-faces';
@@ -0,0 +1,123 @@
1
+ import { type Camera, type CameraReason, type FrameOptions, type MoveResult } from './camera';
2
+ import { type Anchor, type DraftSlot } from './anchors';
3
+ import { type Geometry } from './geometry';
4
+ import { fontMetricsVersion, runtimeVersion } from './version';
5
+ import type { CommonRenderOptions, Diagnostic, LinkPolicy, RenderFailure, RenderResult } from './types';
6
+ export { fontMetricsVersion, runtimeVersion };
7
+ export type { Camera, CameraReason, FrameOptions, MoveResult } from './camera';
8
+ export type { Box, EdgeOut, Geometry, PlacedBox } from './geometry';
9
+ export type { Anchor, DraftSlot } from './anchors';
10
+ export { ZOOM_MAX, ZOOM_MIN } from './camera';
11
+ export type ViewerExecution = {
12
+ mode: 'worker';
13
+ createWorker?: () => Worker;
14
+ timeoutMs?: number;
15
+ } | {
16
+ mode: 'main';
17
+ };
18
+ export type ViewerRenderOptions = Omit<CommonRenderOptions, 'signal' | 'state'> & {
19
+ fonts?: 'host' | 'embed';
20
+ };
21
+ export interface ViewerOptions {
22
+ label?: string;
23
+ toolbar?: boolean;
24
+ /**
25
+ * The keyboard and screen-reader list of items. `'hidden'` (default) keeps it for assistive tech
26
+ * and shows it while it holds focus; `'visible'` always shows it under the drawing.
27
+ */
28
+ outline?: 'visible' | 'hidden';
29
+ execution?: ViewerExecution;
30
+ /** `auto` (default) hides slot bodies and shows titles again below a zoom of 0.4. */
31
+ detail?: 'auto' | 'full';
32
+ render?: ViewerRenderOptions;
33
+ }
34
+ export interface UpdateOptions {
35
+ camera?: 'preserve' | 'fit';
36
+ state?: string | null;
37
+ signal?: AbortSignal;
38
+ }
39
+ export type UpdateResult = {
40
+ status: 'committed';
41
+ revision: number;
42
+ value: Extract<RenderResult, {
43
+ ok: true;
44
+ }>['value'];
45
+ diagnostics: readonly Diagnostic[];
46
+ } | {
47
+ status: 'error';
48
+ revision: number;
49
+ error: RenderFailure;
50
+ } | {
51
+ status: 'superseded' | 'destroyed' | 'aborted';
52
+ revision: number;
53
+ };
54
+ export interface ViewerEvents {
55
+ /** After each commit, after `anchor()`, and with `[]` before `destroy` detaches the targets. */
56
+ anchors: {
57
+ anchors: readonly Anchor[];
58
+ };
59
+ /** After each commit: the drawing, and where each item is (`null` for compare and states). */
60
+ render: {
61
+ revision: number;
62
+ value: Extract<RenderResult, {
63
+ ok: true;
64
+ }>['value'];
65
+ geometry: Geometry | null;
66
+ };
67
+ diagnostics: {
68
+ revision: number;
69
+ diagnostics: readonly Diagnostic[];
70
+ stale: boolean;
71
+ };
72
+ /** At most once per animation frame, with the latest reason. */
73
+ camera: {
74
+ camera: Camera;
75
+ reason: CameraReason;
76
+ };
77
+ itemactivate: {
78
+ id: string;
79
+ kind: 'node' | 'group' | 'edge';
80
+ input: 'pointer' | 'keyboard';
81
+ revision: number;
82
+ };
83
+ /** `preventDefault()` stops the viewer opening the link. */
84
+ link: {
85
+ itemId: string;
86
+ href: string;
87
+ target: '_self' | '_blank';
88
+ preventDefault(): void;
89
+ };
90
+ /** A right-click or the menu key; `id` is null on the background. `preventDefault()` stops the browser's menu. */
91
+ contextmenu: {
92
+ id: string | null;
93
+ kind?: ItemKind;
94
+ clientX: number;
95
+ clientY: number;
96
+ preventDefault(): void;
97
+ };
98
+ }
99
+ export type ItemKind = 'node' | 'group' | 'edge';
100
+ export interface ViewerHandle {
101
+ /** Resolves after the first commit or failure; then after each later one. */
102
+ readonly ready: Promise<UpdateResult>;
103
+ update(source: string, options?: UpdateOptions): Promise<UpdateResult>;
104
+ /** Where each item is drawn, in world units. `null` before the first commit, and for compare and states. The same object for one revision. */
105
+ geometry(): Geometry | null;
106
+ on<K extends keyof ViewerEvents>(type: K, listener: (event: ViewerEvents[K]) => void): () => void;
107
+ getCamera(): Camera;
108
+ /** Zoom is clamped to `ZOOM_MIN`–`ZOOM_MAX`. */
109
+ setCamera(camera: Camera): void;
110
+ /** Frame these items, or the whole drawing without ids. At most actual size by default. */
111
+ fit(ids?: readonly string[], options?: FrameOptions): MoveResult;
112
+ /** The least move that shows the item; zooms out only if it does not fit. */
113
+ reveal(id: string, options?: FrameOptions): MoveResult;
114
+ focusItem(id: string): boolean;
115
+ /**
116
+ * Plain-DOM hosts only: keep a target for each slot (`body:<id>`, `overlay:<id>`). Targets come
117
+ * in the `anchors` event; put content in them. The elements set this from their marked children.
118
+ */
119
+ anchor(slots: readonly DraftSlot[]): void;
120
+ destroy(): void;
121
+ }
122
+ export declare function mountViewer(host: HTMLElement, options?: ViewerOptions): ViewerHandle;
123
+ export type { LinkPolicy };
@@ -1,5 +1,6 @@
1
1
  import type { DiagramSession } from './session';
2
2
  export declare function activeSession(): DiagramSession;
3
+ export declare const hasActiveSession: () => boolean;
3
4
  export declare const setActiveSession: (session: DiagramSession) => {
4
5
  dispose: () => void;
5
6
  } & {
@@ -46,7 +47,8 @@ export declare const setActiveSession: (session: DiagramSession) => {
46
47
  redo: () => void;
47
48
  canUndo: () => boolean;
48
49
  canRedo: () => boolean;
49
- setCamera: (camera: import("../model/types").Camera) => void;
50
+ setCamera: (camera: import("../model/types").Camera, reason?: import("../runtime/camera").CameraReason) => void;
51
+ onCamera: (listener: (reason: import("../runtime/camera").CameraReason) => void) => () => boolean;
50
52
  disableBrowserStorage: () => boolean;
51
53
  setPersistenceBlocked: (blocked: boolean) => void;
52
54
  persist: () => void;
@@ -267,6 +269,9 @@ export declare const setActiveSession: (session: DiagramSession) => {
267
269
  showState: (id: string | null) => void;
268
270
  stepState: (by: 1 | -1) => boolean;
269
271
  drawnDoc: () => import("../model/types").Diagram;
272
+ dark: import("solid-js").Accessor<boolean>;
273
+ setDark: import("solid-js").Setter<boolean>;
274
+ drawnAppearance: () => import("../model/appearance").DiagramAppearance;
270
275
  } & {
271
276
  tool: import("solid-js").Accessor<import("./session/editor").Tool>;
272
277
  setToolSignal: import("solid-js").Setter<import("./session/editor").Tool>;
@@ -476,4 +481,8 @@ export declare const setActiveSession: (session: DiagramSession) => {
476
481
  onDoubleClick: (e: MouseEvent) => void;
477
482
  selectForContextMenu: (e: MouseEvent) => void;
478
483
  dragKind: () => string | undefined;
484
+ } & {
485
+ describeLink: (href: string) => string;
479
486
  };
487
+ /** A destroyed session stops being the target of shortcuts and commands. */
488
+ export declare const releaseActiveSession: (session: DiagramSession) => void;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Lookups that work when the editor renders inside a shadow root. A page-level listener sees an
3
+ * event retargeted to the shadow host, and `document` lookups cannot see inside a shadow root.
4
+ */
5
+ /** The document or shadow root that holds `node`. */
6
+ export declare const rootOf: (node: Node) => Document | ShadowRoot;
7
+ /** The element the event started on, inside any shadow root. */
8
+ export declare const eventTarget: (e: Event) => EventTarget | null;
@@ -1,4 +1,5 @@
1
1
  import type { Camera, Diagram } from '../../model/types';
2
+ import type { CameraReason } from '../../runtime/camera';
2
3
  import type { CanvasTextPart } from './canvas-text';
3
4
  import type { SessionOptions } from '.';
4
5
  export interface HistoryEntry {
@@ -69,7 +70,8 @@ export declare function createDocument(s: CanvasTextPart, options: SessionOption
69
70
  redo: () => void;
70
71
  canUndo: () => boolean;
71
72
  canRedo: () => boolean;
72
- setCamera: (camera: Camera) => void;
73
+ setCamera: (camera: Camera, reason?: CameraReason) => void;
74
+ onCamera: (listener: (reason: CameraReason) => void) => () => boolean;
73
75
  disableBrowserStorage: () => boolean;
74
76
  setPersistenceBlocked: (blocked: boolean) => void;
75
77
  persist: () => void;
@@ -25,8 +25,9 @@ export interface DragFeedback {
25
25
  near?: string;
26
26
  };
27
27
  }
28
- export declare const MIN_ZOOM = 0.08;
29
- export declare const MAX_ZOOM = 4;
28
+ /** The zoom range both handles share: `ZOOM_MIN`–`ZOOM_MAX` in `runtime/camera.ts`. */
29
+ export declare const MIN_ZOOM = 0.02;
30
+ export declare const MAX_ZOOM = 8;
30
31
  export { NodeGeometry };
31
32
  export declare function createEditor(s: DocumentPart & ScenePart): {
32
33
  tool: import("solid-js").Accessor<Tool>;
@@ -7,5 +7,8 @@ export declare function createEmphasis(s: DocumentPart): {
7
7
  showState: (id: string | null) => void;
8
8
  stepState: (by: 1 | -1) => boolean;
9
9
  drawnDoc: () => import("../../model/types").Diagram;
10
+ dark: import("solid-js").Accessor<boolean>;
11
+ setDark: import("solid-js").Setter<boolean>;
12
+ drawnAppearance: () => import("../../model/appearance").DiagramAppearance;
10
13
  };
11
14
  export type EmphasisPart = ReturnType<typeof createEmphasis>;
@@ -15,6 +15,11 @@ export interface SessionOptions {
15
15
  openLink?: (href: string) => void;
16
16
  /** The user started a gesture or a tool on the canvas; a host closes its menus here. */
17
17
  onInteract?: () => void;
18
+ /** A link was pressed, before it opens. Return true to stop it opening. */
19
+ onLink?: (link: {
20
+ href: string;
21
+ itemId: string | undefined;
22
+ }) => boolean;
18
23
  }
19
24
  export declare function createDiagramSession(options?: SessionOptions): {
20
25
  dispose: () => void;
@@ -62,7 +67,8 @@ export declare function createDiagramSession(options?: SessionOptions): {
62
67
  redo: () => void;
63
68
  canUndo: () => boolean;
64
69
  canRedo: () => boolean;
65
- setCamera: (camera: import("../../model/types").Camera) => void;
70
+ setCamera: (camera: import("../../model/types").Camera, reason?: import("../../runtime/camera").CameraReason) => void;
71
+ onCamera: (listener: (reason: import("../../runtime/camera").CameraReason) => void) => () => boolean;
66
72
  disableBrowserStorage: () => boolean;
67
73
  setPersistenceBlocked: (blocked: boolean) => void;
68
74
  persist: () => void;
@@ -283,6 +289,9 @@ export declare function createDiagramSession(options?: SessionOptions): {
283
289
  showState: (id: string | null) => void;
284
290
  stepState: (by: 1 | -1) => boolean;
285
291
  drawnDoc: () => import("../../model/types").Diagram;
292
+ dark: import("solid-js").Accessor<boolean>;
293
+ setDark: import("solid-js").Setter<boolean>;
294
+ drawnAppearance: () => import("../../model/appearance").DiagramAppearance;
286
295
  } & {
287
296
  tool: import("solid-js").Accessor<import("./editor").Tool>;
288
297
  setToolSignal: import("solid-js").Setter<import("./editor").Tool>;
@@ -492,5 +501,8 @@ export declare function createDiagramSession(options?: SessionOptions): {
492
501
  onDoubleClick: (e: MouseEvent) => void;
493
502
  selectForContextMenu: (e: MouseEvent) => void;
494
503
  dragKind: () => string | undefined;
504
+ } & {
505
+ /** What opening `href` does, for a link mark's label. */
506
+ describeLink: (href: string) => string;
495
507
  };
496
508
  export type DiagramSession = ReturnType<typeof createDiagramSession>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@draftably/editor",
3
- "version": "0.3.0",
3
+ "version": "0.5.0",
4
4
  "description": "The Draftably diagram editor: drag boxes and lines, and get the .draft source back.",
5
5
  "license": "MIT",
6
6
  "type": "module",