@phin-tech/dottie 0.5.0 → 0.5.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.
@@ -0,0 +1,30 @@
1
+ import { type DottieFile, type Element, type Marker, type Page } from "./model.ts";
2
+ /** Jump to scene `scene` (an index into the page's markers) and play on to the next; open `url` in a new tab; or,
3
+ * in <dottie-player> only, show page `page` (an index into the file's pages), where the element's link points. */
4
+ export type Click = {
5
+ scene: number;
6
+ } | {
7
+ url: string;
8
+ } | {
9
+ page: number;
10
+ };
11
+ /** The marker called `name`: an exact match, else one that differs only in case. */
12
+ export declare function sceneNamed(name: string, markers: Marker[]): number;
13
+ /** The page's clickable elements and what each click does, by element id. A scene named by no marker, or a link
14
+ * that isn't allowed, makes nothing clickable. Given the whole file, an element whose `link` points at an element on
15
+ * another page shows that page (the HTML export holds one page, so it can't). */
16
+ export declare function clickTargets(page: Page, file?: DottieFile): Map<string, Click>;
17
+ /** `e` as it looks hovered (HoverLook.apply). */
18
+ export declare function hoveredElement(e: Element): Element;
19
+ /** `page` with `ids` drawn as they look hovered. */
20
+ export declare function hovered(page: Page, ids: Set<string>): Page;
21
+ export declare function hasHover(e: Element): boolean;
22
+ /** What a screen reader calls the element as a button: the first line of its text, else its anchor, else for a
23
+ * symbol's copy the symbol's name, else its kind. */
24
+ export declare function buttonLabel(e: Element, symbolName?: string): string;
25
+ /** For each of `instances`, the ids of every element it can expand to, mapped to it, in drawing order
26
+ * (DottieDocument.parts(of:)). */
27
+ export declare function partsOf(page: Page, instances: Set<string>): Map<string, string>;
28
+ /** How clickable elements look (Exporter.clickStyle): a pointer, their hover look under it or with keyboard focus (a
29
+ * soft glow when they have none), and a small nudge while pressed. */
30
+ export declare const CLICK_STYLE = "\n.dottie-a { cursor: pointer; outline: none; }\n.dottie-a .dottie-h { display: none; }\n.dottie-a:hover .dottie-h, .dottie-a.dottie-hover .dottie-h, .dottie-a:focus-visible .dottie-h { display: inline; }\n.dottie-a:hover .dottie-n, .dottie-a.dottie-hover .dottie-n, .dottie-a:focus-visible .dottie-n { display: none; }\n.dottie-a:focus-visible { filter: drop-shadow(0 0 3px var(--dottie-focus, #3b82f6)); }\n.dottie-a:not(.dottie-b):active, .dottie-a.dottie-press:not(.dottie-b) { transform: translate(1px, 1px); }\n.dottie-a .dottie-d { display: none; }\n.dottie-b:active .dottie-n, .dottie-b:active .dottie-h, .dottie-b.dottie-press .dottie-n, .dottie-b.dottie-press .dottie-h { display: none; }\n.dottie-b:active .dottie-d, .dottie-b.dottie-press .dottie-d { display: inline; }\n";
@@ -18,4 +18,4 @@ export interface RenderOptions {
18
18
  /** One page of a drawing as an SVG document, as Dottie's own SVG export draws it. */
19
19
  export declare function render(source: string | DottieFile | unknown, options?: RenderOptions): string;
20
20
  /** The library's version. */
21
- export declare const VERSION = "0.5.0";
21
+ export declare const VERSION = "0.5.1";
@@ -6,7 +6,8 @@ export interface RGBA {
6
6
  }
7
7
  export type FillStyle = "solid" | "hachure" | "crossHatch" | "grid";
8
8
  export type DashStyle = "solid" | "dashed" | "dotted";
9
- export type ElementKind = "rectangle" | "ellipse" | "diamond" | "text" | "connector" | "freehand" | "path" | "note" | "image";
9
+ export type ElementKind = "rectangle" | "ellipse" | "diamond" | "text" | "connector" | "freehand" | "path" | "note" | "image" | "symbol";
10
+ export type SymbolPlayback = "loop" | "once" | "still" | "click";
10
11
  export type Port = "top" | "right" | "bottom" | "left";
11
12
  export type Routing = "straight" | "curved" | "elbow";
12
13
  export type Arrowhead = "none" | "arrow" | "triangle" | "dot" | "bar";
@@ -50,6 +51,17 @@ export interface EmbeddedImage {
50
51
  data: string;
51
52
  format: string;
52
53
  }
54
+ /** What clicking an element does in a played drawing: a scene to jump to and play on from, or a link. */
55
+ export interface ClickAction {
56
+ scene: string | null;
57
+ url: string | null;
58
+ }
59
+ /** How a clickable element looks under the pointer or with keyboard focus; null keeps its own. */
60
+ export interface HoverLook {
61
+ stroke: RGBA | null;
62
+ fill: RGBA | null;
63
+ opacity: number | null;
64
+ }
53
65
  export interface Element {
54
66
  id: string;
55
67
  /** A kind dottie.js doesn't know is kept as written and drawn as a labelled placeholder. */
@@ -71,6 +83,12 @@ export interface Element {
71
83
  rotation: number | null;
72
84
  link: string | null;
73
85
  anchor: string | null;
86
+ click: ClickAction | null;
87
+ hover: HoverLook | null;
88
+ /** For a `symbol` element: the page's symbol it shows, how it plays it, and from how far in. */
89
+ symbol: string | null;
90
+ playback: SymbolPlayback | null;
91
+ offset: number | null;
74
92
  /** Base64 bytes; an empty `data` is a picture that couldn't be found (drawn crossed out). */
75
93
  image: EmbeddedImage | null;
76
94
  reveal: number | null;
@@ -148,6 +166,19 @@ export interface Page {
148
166
  elements: Element[];
149
167
  theme: string | null;
150
168
  timeline: Timeline | null;
169
+ symbols: Symbol[] | null;
170
+ }
171
+ /** A drawing defined once on a page and placed by `symbol` elements, with its own timeline (Symbol). */
172
+ export interface Symbol {
173
+ id: string;
174
+ name: string;
175
+ width: number;
176
+ height: number;
177
+ layers: Layer[];
178
+ elements: Element[];
179
+ timeline: Timeline | null;
180
+ /** A Flash-style button: copies show its up scene; on the web, over, down and hit (Symbol.button). */
181
+ button: boolean | null;
151
182
  }
152
183
  export interface DottieFile {
153
184
  version: number;
@@ -173,6 +204,9 @@ export declare class DottieFormatError extends Error {
173
204
  }
174
205
  export declare function clampTime(t: number): number;
175
206
  export declare function clampFPS(f: number): number;
207
+ /** `url` trimmed, if it is a link a page may open: http, https or mailto, as ClickAction.allowed. A drawing can
208
+ * play on someone else's site, so nothing else (javascript:, data:) is ever followed. */
209
+ export declare function allowedURL(url: string): string | null;
176
210
  export declare function repeatIsValid(r: Repeat): boolean;
177
211
  /** Sorts in place by `key`, keeping equal keys in their original order (as Swift's sort happens to for these). */
178
212
  export declare function stableSortBy<T>(a: T[], key: (v: T) => number): void;
@@ -1,3 +1,4 @@
1
+ import { type Click } from "./clicks.ts";
1
2
  import { type DottieFile, type Page, type RGBA } from "./model.ts";
2
3
  import { type Plan } from "./svg.ts";
3
4
  /** Finds a page by name (any case) or 1-based number; the first page when `spec` is empty or matches nothing. */
@@ -11,20 +12,48 @@ export declare class Playback {
11
12
  readonly sceneNames: string[];
12
13
  readonly background: RGBA;
13
14
  readonly ink: RGBA;
15
+ /** What clicking each clickable element does, by element id. */
16
+ readonly clicks: Map<string, Click>;
17
+ /** Copies of symbols that play through once when clicked (playback "click"), by id, with their clip's length. */
18
+ readonly replays: Map<string, number>;
19
+ /** When each replaying copy was clicked (performance.now() milliseconds). */
20
+ private replayStarts;
21
+ private hoverIDs;
22
+ private labels;
23
+ /** Each drawn part of a clickable copy, to that copy's id; and each copy's parts in drawing order. */
24
+ private owner;
25
+ private partsOfOwner;
26
+ /** The moments of the button copies' over, down and hit states. */
27
+ private overTimes;
28
+ private downTimes;
29
+ private hitTimes;
30
+ private last;
14
31
  private svg;
15
32
  private groups;
16
33
  private order;
17
34
  frame: number;
18
35
  onFrame: ((frame: number) => void) | null;
36
+ /** `file` is the drawing `page` belongs to, so links to its other pages are clickable. */
19
37
  constructor(page: Page, into: Element, options?: {
20
38
  clean?: boolean;
39
+ file?: DottieFile;
21
40
  });
22
41
  get frameCount(): number;
23
42
  get posterFrame(): number;
24
43
  /** Draws frame `i`, replacing only the pieces whose markup changed since the last frame. */
25
44
  show(i: number): void;
45
+ /** Starts copy `id` replaying from `at` (performance.now() milliseconds; earlier to start partway). */
46
+ replay(id: string, at: number): void;
47
+ /** Whether a copy is still playing through after a click. */
48
+ replaying(now?: number): boolean;
49
+ /** Draws the last moment drawn again, for copies replaying while the page stands still. */
50
+ redraw(): void;
26
51
  /** Draws the moment `t` (seconds) in the frame-`i` view. */
27
52
  drawAt(t: number, i?: number): void;
53
+ /** What a clickable owner draws as: its normal look, and its hover, over and down looks where they differ. A
54
+ * symbol's copy keeps its drawing out of the pointer's way and takes clicks on a layer above: its hit state drawn
55
+ * invisibly, or its frame. `button` is whether it has a down look (the stylesheet nudges the others). */
56
+ private buttonPart;
28
57
  /** The scene frame `i` is in, or -1 before the first. */
29
58
  sceneAt(i: number): number;
30
59
  }
@@ -47,6 +76,7 @@ export declare class DottiePlayer extends ElementBase {
47
76
  private last;
48
77
  private acc;
49
78
  private raf;
79
+ private replayRaf;
50
80
  private loadToken;
51
81
  private visible;
52
82
  private observer;
@@ -69,6 +99,11 @@ export declare class DottiePlayer extends ElementBase {
69
99
  nextScene(): void;
70
100
  /** Back to the start of this scene, or the one before if already there. */
71
101
  prevScene(): void;
102
+ /** Does what clicking element `id` does: jumps to its scene and plays on to the next (with reduced motion, or in a
103
+ * still, straight to where that stops), opens its link in a new tab, or shows its page. */
104
+ activate(id: string): void;
105
+ /** Redraws, while the page itself stands still, as long as a clicked copy is playing through. */
106
+ private scheduleReplay;
72
107
  private setPlaying;
73
108
  private schedule;
74
109
  /** Steps whole frames at the timeline's rate; with scenes, playing stops at each one and at the end. */
@@ -0,0 +1,20 @@
1
+ import { type Page, type Symbol, type SymbolPlayback } from "./model.ts";
2
+ /** The deepest instances nest, and the most elements expanding one page may make (Symbol.maxDepth, .maxElements). */
3
+ export declare const MAX_DEPTH = 8;
4
+ export declare const MAX_ELEMENTS = 20000;
5
+ export type ButtonState = "up" | "over" | "down" | "hit";
6
+ /** The moment of the symbol's scene named `state`, any case, within its timeline (Symbol.sceneTime). */
7
+ export declare function sceneTime(s: Symbol, state: ButtonState): number | null;
8
+ /** Where a button is in each state (Symbol.buttonTime): over falls back to up, down to over; hit to nothing. */
9
+ export declare function buttonTime(s: Symbol, state: ButtonState): number | null;
10
+ /** Where an instance is in its symbol's timeline at page time `t` (Symbol.localTime). */
11
+ export declare function symbolTime(s: Symbol, t: number, playback: SymbolPlayback | null, offset: number | null): number;
12
+ /** The symbol as a page of its own (Symbol.page). */
13
+ export declare function symbolPage(s: Symbol): Page;
14
+ export declare function hasInstances(page: Page): boolean;
15
+ /** The page with every instance replaced by what it shows at page time `t` (DottieDocument.expandingSymbols). `times`
16
+ * puts instances on the page at a moment of their symbol's own: a button's other states, or a clip replaying. */
17
+ export declare function expandingSymbols(page: Page, t: number, posing?: boolean, times?: Map<string, number>): Page;
18
+ export declare function symbolTable(page: Page): Map<string, Symbol>;
19
+ /** The id an element of a symbol has inside instance `instance` (DottieDocument.derivedID). */
20
+ export declare function derivedID(instance: string, inner: string): string;
@@ -18,8 +18,11 @@ export declare function following(track: Track, e: Element, t: number, page: Pag
18
18
  /** Where the dashes of a line marching at `speed` stand at `t`, within one pattern `period` (Timeline.marchOffset):
19
19
  * the speed is rounded to a whole number of patterns over the timeline, so a loop is seamless. */
20
20
  export declare function marchOffset(tl: Timeline, speed: number, period: number, t: number): number;
21
- /** The page as a still drawing at `t` seconds (DottieDocument.resolved(at:)). A page without a timeline is returned as is. */
21
+ /** The page as a still drawing at `t` seconds, symbol instances expanded (DottieDocument.resolved(at:)). A page with
22
+ * no timeline and no instances is returned as is. */
22
23
  export declare function resolved(page: Page, t: number): Page;
24
+ /** The page posed at `t` seconds, instances kept (DottieDocument.posed(at:)). */
25
+ export declare function posed(page: Page, t: number): Page;
23
26
  /** The moment a still picture of the page shows: its poster, else the end. */
24
27
  export declare function posterTime(page: Page): number;
25
28
  /** The page as a still picture (its poster frame when animated). */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@phin-tech/dottie",
3
- "version": "0.5.0",
3
+ "version": "0.5.1",
4
4
  "description": "Render, play and compile Dottie (.dottie) drawings and animations in the browser",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",