anniedrawing 0.3.2 → 0.4.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 (57) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/README.md +5 -1
  3. package/dist/agent/index.js +1 -1
  4. package/dist/agent/index.js.map +1 -1
  5. package/dist/agent/toolDefs.d.ts +1 -0
  6. package/dist/board.d.ts +7 -1
  7. package/dist/core/catalog.d.ts +1 -1
  8. package/dist/core/index.js +1 -1
  9. package/dist/core/textFit.d.ts +13 -0
  10. package/dist/core/types.d.ts +12 -0
  11. package/dist/docs/agents-repository.md +2 -2
  12. package/dist/docs/agents.md +6 -2
  13. package/dist/docs/api.md +7 -3
  14. package/dist/docs/board-js.md +20 -16
  15. package/dist/docs/decisions.md +21 -1
  16. package/dist/docs/format.md +2 -2
  17. package/dist/docs/index.html +15 -7
  18. package/dist/docs/llms-full.txt +20 -16
  19. package/dist/docs/llms.txt +14 -10
  20. package/dist/docs/mcp.md +1 -1
  21. package/dist/fellow.d.ts +2 -2
  22. package/dist/fellow.js +1 -1
  23. package/dist/fellow.js.map +1 -1
  24. package/dist/index.js +1 -1
  25. package/dist/shared/board-OPwsZ2_V.js +2 -0
  26. package/dist/shared/board-OPwsZ2_V.js.map +1 -0
  27. package/dist/shared/{cards-DWgSVE54.js → cards-D_9Lly1d.js} +2 -2
  28. package/dist/shared/{cards-DWgSVE54.js.map → cards-D_9Lly1d.js.map} +1 -1
  29. package/dist/shared/defaults-DZEoAeRz.js +2 -0
  30. package/dist/shared/defaults-DZEoAeRz.js.map +1 -0
  31. package/dist/shared/describe-o3vER0cL.js +3 -0
  32. package/dist/shared/{describe-DaWyf3qV.js.map → describe-o3vER0cL.js.map} +1 -1
  33. package/dist/shared/{paste-C22i8o-g.js → paste-B4b0C9Jh.js} +2 -2
  34. package/dist/shared/{paste-C22i8o-g.js.map → paste-B4b0C9Jh.js.map} +1 -1
  35. package/dist/shared/picker-ciuPQvRn.js +2 -0
  36. package/dist/shared/picker-ciuPQvRn.js.map +1 -0
  37. package/dist/shared/textFit-BrGz6lhQ.js +2 -0
  38. package/dist/shared/textFit-BrGz6lhQ.js.map +1 -0
  39. package/dist/shared/ui-c98N8xEV.js +2 -0
  40. package/dist/shared/ui-c98N8xEV.js.map +1 -0
  41. package/dist/shared/{urlPaste-DN4JtgeB.js → urlPaste-BqcpeQ-c.js} +2 -2
  42. package/dist/shared/{urlPaste-DN4JtgeB.js.map → urlPaste-BqcpeQ-c.js.map} +1 -1
  43. package/dist/style.css +1 -1
  44. package/dist/ui/index.js +1 -1
  45. package/dist/ui/version.d.ts +1 -1
  46. package/llms-full.txt +20 -16
  47. package/llms.txt +14 -10
  48. package/package.json +1 -1
  49. package/dist/shared/board-DV5lzxNR.js +0 -2
  50. package/dist/shared/board-DV5lzxNR.js.map +0 -1
  51. package/dist/shared/defaults-C-aC_B4z.js +0 -2
  52. package/dist/shared/defaults-C-aC_B4z.js.map +0 -1
  53. package/dist/shared/describe-DaWyf3qV.js +0 -3
  54. package/dist/shared/picker-Dv_i4iNP.js +0 -2
  55. package/dist/shared/picker-Dv_i4iNP.js.map +0 -1
  56. package/dist/shared/ui-DEBI1jv_.js +0 -2
  57. package/dist/shared/ui-DEBI1jv_.js.map +0 -1
package/dist/ui/index.js CHANGED
@@ -1 +1 @@
1
- import{t as r}from"../shared/ui-DEBI1jv_.js";export{r as mountUI};
1
+ import{t as r}from"../shared/ui-c98N8xEV.js";export{r as mountUI};
@@ -1,4 +1,4 @@
1
1
  /** npm package version shown in the AnnieDrawing menu. Keep in sync with package.json. */
2
- export declare const PACKAGE_VERSION = "0.3.2";
2
+ export declare const PACKAGE_VERSION = "0.4.0";
3
3
  export declare const SITE_URL = "https://anniedrawing.com";
4
4
  export declare const GITHUB_REPO_URL = "https://github.com/Frontierz-AI/AnnieDrawing";
package/llms-full.txt CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Operate a live or headless board through JavaScript. This is the full AI reference for creating items and reading what is on the board. It does not cover installing, running, or changing the library.
4
4
 
5
- Kind catalog: 1
5
+ Kind catalog: 2
6
6
 
7
7
  `kindsSince(since?)` lists built-in kinds added or last changed after that catalog version. Omit `since`, or pass `0`, to list every built-in kind. Remember the returned `version` and pass it next time you want only what is new.
8
8
 
@@ -32,12 +32,12 @@ const board = createDoc();
32
32
 
33
33
  ```js
34
34
  board.kindsSince(); // every built-in kind; same as board.kindsSince(0)
35
- board.kindsSince(1); // kinds added or changed after catalog 1 (empty today)
35
+ board.kindsSince(1); // kinds added or changed after catalog 1
36
36
  ```
37
37
 
38
38
  Also exported as `kindsSince` and `CATALOG_VERSION` from `anniedrawing`, `anniedrawing/core`, and `anniedrawing/agent`.
39
39
 
40
- Each entry is `{ kind, since, w, h, note }`. `w` and `h` are the default size when those fields are omitted on `add`. Custom host kinds do not appear here.
40
+ Each entry is `{ kind, since, w, h, note }`. `w` and `h` are the default size when those fields are omitted on `add`. An `agent:` create can store a larger box so `text` fits. An `agent:` connector that omits `route` stores `elbow`. Custom host kinds do not appear here.
41
41
 
42
42
  The catalog version is independent of the `.annie` document format version (`2`) and the package version.
43
43
 
@@ -68,6 +68,8 @@ board.toJSON(); // portable document
68
68
 
69
69
  DOM nodes may show `[data-ad-id]` and `[data-ad-kind]`. Do not treat DOM edits as a write API.
70
70
 
71
+ `board.getPointer()` returns a copy of the last human pointer: `{ x, y, pageId, inside, pointerType, ageMs, itemId }`, or `null` before a pointer is observed, after a page switch, or after destruction. Coordinates are page-space. While `inside` is true they follow pan and zoom; `itemId` is the topmost hittable item or `null`. Editor controls are excluded. Leaving, blur, hidden tabs, cancel, or touch release sets `inside: false` and preserves the last point. `ageMs` measures time since the last pointer event, not camera changes. Treat an outside point as historical; ask the user to point again when ambiguous. Pointer state is never serialized.
72
+
71
73
  ## Write
72
74
 
73
75
  ```js
@@ -81,6 +83,8 @@ const result = board.apply(ops, {
81
83
  // { ok, created, errors, warnings, skipped? }
82
84
  ```
83
85
 
86
+ Pass `expectedRevision` from the read that informed an edit to `apply` or `board_apply`. A mismatch returns `STALE_REVISION` without applying any operation, including in lenient or dry-run mode. Read again before retrying. This guards one session only: `load()` and `clear()` reset revisions.
87
+
84
88
  A failed batch changes nothing. `dryRun: true` validates and does not write. It does not reserve IDs. Do not call `load()` to patch a few items. Do not set `merge: true` unless you intend to fold this commit into the previous history entry with the same origin and label. `lenient: true` is available on `apply` only.
85
89
 
86
90
  Use stable IDs when later operations in the same batch need to reference new items. Generated prefixes are `i_`, `p_`, and `m_`.
@@ -89,7 +93,7 @@ Operations: `add`, `set`, `remove`, `order`, `reparent`, `page.add`, `page.set`,
89
93
 
90
94
  `set` merges `style`, `text`, and `data` one level deep. Other fields are replaced. Do not change `id` with `set`. `order.to` is `front`, `back`, `forward`, `backward`, or a numeric index.
91
95
 
92
- `add` accepts `page`, `parent`, `index`, and `place`. `place` needs exactly one of `rightOf`, `leftOf`, `above`, `below`, `inside`, or `near`. Default `gap` is 32. Default `align` is `middle`. `inside` requires a `group`. Kind aliases: `rectangle` stores `rect`; `arrow` stores `connector` with an end arrow. `from` / `to` accept `{ item, side }`, `{ x, y }`, or a string item id.
96
+ `add` accepts `page`, `parent`, `index`, and `place`. `place` needs exactly one of `rightOf`, `leftOf`, `above`, `below`, `inside`, or `near`. Default `gap` is 32. Default `align` is `middle`. `inside` requires a `group`. `rightOf` / `leftOf` / `above` / `below` slide further along that axis when the first slot is occupied. Kind aliases: `rectangle` stores `rect`; `arrow` stores `connector` with an end arrow. `from` / `to` accept `{ item, side }`, `{ x, y }`, or a string item id. An `agent:` connector that omits `route` stores `elbow`. Elbows go around intervening boxes.
93
97
 
94
98
  `OVERLAPS_EXISTING` and `ID_REMAPPED` are warnings. The batch still committed. An `agent:` create that reuses an id is stored as `id_1`, then `_2`. Same-batch `place`, parent, and connector refs follow the stored id. `get` with the id you sent returns the older item. User and API origins still reject duplicates.
95
99
 
@@ -175,7 +179,7 @@ Named colors: `ink`, `slate`, `coral`, `amber`, `moss`, `teal`, `sky`, `violet`,
175
179
 
176
180
  ## Built-in kinds
177
181
 
178
- Omit `w` / `h` to use the default size in the catalog.
182
+ Omit `w` / `h` to use the default size in the catalog. An `agent:` create or text patch on `rect`, `ellipse`, `diamond`, `note`, or `text` grows the stored size so the label fits. Standalone `text` defaults to 600 wide. A larger explicit size is kept.
179
183
 
180
184
  ### `rect`
181
185
 
@@ -209,7 +213,7 @@ Omit `w` / `h` to use the default size in the catalog.
209
213
 
210
214
  ### `connector`
211
215
 
212
- `from` / `to` are `{ item, side?, anchor? }`, `{ x, y }`, or a string item id stored as `{ item, side: 'auto' }`. `side` is `auto` / `top` / `right` / `bottom` / `left`. `route` is `straight` / `elbow` / `curve`. Heads: `none` / `arrow` / `dot`. Optional `waypoints` are page-space `[x, y]`. Bound ends detach to their last point when the target disappears. `kind: 'arrow'` stores `connector` with an end arrow.
216
+ `from` / `to` are `{ item, side?, anchor? }`, `{ x, y }`, or a string item id stored as `{ item, side: 'auto' }`. `side` is `auto` / `top` / `right` / `bottom` / `left`. `route` is `straight` / `elbow` / `curve`. Heads: `none` / `arrow` / `dot`. Optional `waypoints` are page-space `[x, y]`. An `agent:` create that omits `route` stores `elbow`. Elbows pick a channel that misses intervening boxes. Bound ends detach to their last point when the target disappears. `kind: 'arrow'` stores `connector` with an end arrow.
213
217
 
214
218
  ```js
215
219
  { op: 'add', item: { id: 'i_flow', kind: 'connector',
@@ -229,11 +233,11 @@ Freehand points may include pressure: `[x, y, pressure]`. `closed: true` closes
229
233
  ### `text`
230
234
 
231
235
  ```js
232
- { op: 'add', item: { id: 'i_title', kind: 'text', x: 80, y: 40, w: 280, h: 48,
236
+ { op: 'add', item: { id: 'i_title', kind: 'text', x: 80, y: 40,
233
237
  text: { value: 'Architecture', size: 'l', align: 'start' } } }
234
238
  ```
235
239
 
236
- A browser `text` item with `autoWidth: true` stores measured width and height. Headless documents keep the stored size.
240
+ Omitted `w` is 600. A browser `text` item with `autoWidth: true` (set for `agent:` creates) stores measured width and height. Headless documents keep the stored or grown size.
237
241
 
238
242
  ### `note`
239
243
 
@@ -323,14 +327,14 @@ PNG `labels: true` draws item IDs for vision models and defaults to a 32-color i
323
327
 
324
328
  Optional wrapper around the same APIs. Import `toolDefs` and `runTool` from `anniedrawing/agent`. Map `name`, `description`, and `inputSchema` into the provider envelope. Do not change the operations schema.
325
329
 
326
- | Tool | Use |
327
- | ---------------- | -------------------------------------------------------------------------------------------------------------- |
328
- | `board_describe` | Text with IDs. Start here. |
329
- | `board_read` | Deep JSON copy. Headless accepts only `scope: 'doc'`. |
330
- | `board_query` | Same filters as `query`. |
331
- | `board_apply` | Atomic ops. `runTool` forces an `agent:` origin (`agent:tool` if omitted). Duplicate create ids become `id_1`. |
332
- | `board_snapshot` | Browser PNG. Defaults: viewport, scale 2, labels on, 32 colors, 240 KiB. |
333
- | `board_view_fit` | Browser camera. Optional `ids`. |
330
+ | Tool | Use |
331
+ | ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
332
+ | `board_describe` | Text with IDs. Start here. |
333
+ | `board_read` | Deep JSON copy. Headless accepts only `scope: 'doc'`. |
334
+ | `board_query` | Same filters as `query`. |
335
+ | `board_apply` | Atomic ops. Grows labels, slides directional place, omitted route → elbow. `runTool` forces an `agent:` origin (`agent:tool` if omitted). Duplicate create ids become `id_1`. |
336
+ | `board_snapshot` | Browser PNG. Defaults: viewport, scale 2, labels on, 32 colors, 240 KiB. |
337
+ | `board_view_fit` | Browser camera. Optional `ids`. |
334
338
 
335
339
  `board_snapshot` and `board_view_fit` need a live board.
336
340
 
package/llms.txt CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Operate a board through JavaScript. The JSON document is the source of truth. People and agents commit through `apply(ops, options)`. This file does not cover installing or changing the library. Full examples: [board JavaScript](docs/board-js.md) / [llms-full.txt](llms-full.txt).
4
4
 
5
- Kind catalog: 1
5
+ Kind catalog: 2
6
6
 
7
7
  ```js
8
8
  const board = window.__anniedrawing[0]; // demo; hosts pass exposeGlobal: true
@@ -20,32 +20,36 @@ board.query({ kind: 'arrow' }); // matches stored connector created as arrow
20
20
 
21
21
  Reads return copies. Mutating them does not edit the board.
22
22
 
23
+ `board.getPointer()` returns a copy of the last human pointer: `{ x, y, pageId, inside, pointerType, ageMs, itemId }`, or `null` before a pointer is observed, after a page switch, or after destruction. Coordinates are page-space. While `inside` is true they follow pan and zoom; `itemId` is the topmost hittable item or `null`. Editor controls are excluded. Leaving, blur, hidden tabs, cancel, or touch release sets `inside: false` and preserves the last point. `ageMs` measures time since the last pointer event, not camera changes. Treat an outside point as historical; ask the user to point again when ambiguous. Pointer state is never serialized.
24
+
23
25
  ## Write
24
26
 
25
27
  ```
26
28
  board.apply(ops, { origin: 'agent:name', label: 'What changed', dryRun?: false, agentName?: 'Name', reveal?: 'fit' })
27
29
  ```
28
30
 
31
+ Pass `expectedRevision` from the read that informed an edit to `apply` or `board_apply`. A mismatch returns `STALE_REVISION` without applying any operation, including in lenient or dry-run mode. Read again before retrying. This guards one session only: `load()` and `clear()` reset revisions.
32
+
29
33
  Operations: `add`, `set`, `remove`, `order`, `reparent`, `page.add`, `page.set`, `page.remove`, `meta.set`, `media.set`, `media.remove`. A failed batch changes nothing. `set` merges `style`, `text`, and `data` one level deep. Do not change `id` with `set`. `add` accepts `page`, `parent`, `index`, and `place`. `order.to` is `front`, `back`, `forward`, `backward`, or a numeric index. Kind aliases: `rectangle` → `rect`, `arrow` → `connector`. Connector `from`/`to` accept `{ item, side }`, `{ x, y }`, or a string id.
30
34
 
31
- `place` requires exactly one of `rightOf`, `leftOf`, `above`, `below`, `inside`, or `near`. Default `gap` is 32. Default `align` is `middle`. `inside` requires a `group`. Do not call `load()` to patch a few items.
35
+ `place` requires exactly one of `rightOf`, `leftOf`, `above`, `below`, `inside`, or `near`. Default `gap` is 32. Default `align` is `middle`. `inside` requires a `group`. Directional `place` slides further along that axis when the slot is taken. An `agent:` create or text patch on `rect`, `ellipse`, `diamond`, `note`, or `text` grows the stored size so the label fits. Standalone `text` defaults to 600 wide. An `agent:` connector that omits `route` stores `elbow`. Elbows go around intervening boxes. Do not call `load()` to patch a few items.
32
36
 
33
37
  Check `result.ok`, then read `result.created` for stored ids. `OVERLAPS_EXISTING` and `ID_REMAPPED` are warnings; the batch still committed. An `agent:` create that reuses an id is stored as `id_1` (then `_2`); same-batch `place` and connector refs follow that id. `get` with the id you sent returns the older item. User and API origins still reject duplicates.
34
38
 
35
39
  ## Kinds
36
40
 
37
- Built-in kinds, default size when `w`/`h` omitted, catalog `since` 1:
41
+ Built-in kinds, default size when `w`/`h` omitted. `rect`, `ellipse`, `diamond`, `connector`, `note`, and `text` are catalog 2: labeled boxes grow so the label fits; an omitted connector `route` stores `elbow`.
38
42
 
39
43
  | Kind | Size | Create |
40
44
  | ---- | ---- | ------ |
41
- | `rect` | 180×110 | Box or node. `text`, `style`. |
42
- | `ellipse` | 180×110 | Ellipse or circle. |
43
- | `diamond` | 160×140 | Decision or highlight. |
45
+ | `rect` | 180×110 | Box or node. `text`, `style`. Agent creates grow to fit text. |
46
+ | `ellipse` | 180×110 | Ellipse or circle. Agent creates grow to fit text. |
47
+ | `diamond` | 160×140 | Decision or highlight. Agent creates grow to fit text. |
44
48
  | `line` | 180×0 | Segment. Optional `points` relative to x/y. |
45
- | `connector` | 0×0 | `from`/`to` as `{ item, side? }`, `{ x, y }`, or a string item id. `route`: straight/elbow/curve. Compact JSON omits x/y/w/h. |
49
+ | `connector` | 0×0 | `from`/`to` as `{ item, side? }`, `{ x, y }`, or a string item id. `route`: straight/elbow/curve. Agent omit stores elbow. Compact JSON omits x/y/w/h. |
46
50
  | `path` | 0×0 | Freehand. `points` (`[x,y,pressure?]`), optional `closed`. |
47
- | `text` | 200×48 | Plain text. Browser `autoWidth` measures. |
48
- | `note` | 200×180 | Sticky. Default moss fill, 12px corner. |
51
+ | `text` | 600×48 | Plain text. Agent creates grow to fit a title. Browser `autoWidth` measures. |
52
+ | `note` | 200×180 | Sticky. Default moss fill, 12px corner. Agent creates grow to fit text. |
49
53
  | `image` | 240×180 | `media` key in the document media table. |
50
54
  | `video` | 480×270 | YouTube or Vimeo `href`. |
51
55
  | `link` | 220×200 | Website card. `href`, optional `description`. |
@@ -79,7 +83,7 @@ Optional. Import `toolDefs` and `runTool` from `anniedrawing/agent`. Same operat
79
83
  | `board_describe` | Text with IDs. Start here. |
80
84
  | `board_read` | Deep JSON. Headless: `scope: 'doc'` only. |
81
85
  | `board_query` | Filters combine with AND. |
82
- | `board_apply` | Atomic ops. `dryRun` validates without writing. Duplicate agent create ids become `id_1`. |
86
+ | `board_apply` | Atomic ops. Grows labels, slides directional place, omitted route → elbow. `dryRun` validates. Duplicate agent create ids become `id_1`. |
83
87
  | `board_snapshot` | Browser PNG. Defaults: viewport, scale 2, labels on, 32 colors, 240 KiB. |
84
88
  | `board_view_fit` | Browser camera. Optional `ids`. |
85
89
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "anniedrawing",
3
- "version": "0.3.2",
3
+ "version": "0.4.0",
4
4
  "description": "A small, joyful HTML and SVG drawing board for people and AI agents. By Frontierz.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -1,2 +0,0 @@
1
- import{a as t,c as e,d as i,i as s,m as n,r as o,t as a,u as r}from"./picker-Dv_i4iNP.js";import{a as h,b as d,h as l,m as c,t as p,u,y as m}from"./defaults-C-aC_B4z.js";import{L as g,M as f,O as y,S as x,T as v,_ as w,a as k,d as b,f as $,i as M,o as S,s as z,u as E,y as I}from"./describe-DaWyf3qV.js";import{a as C,c as L,d as T,f as A,i as P,l as D,m as R,n as q,o as O,p as U,r as N,s as G,t as j,u as F}from"./ui-DEBI1jv_.js";function K(t){const e=/* @__PURE__ */new Set,i=(t,s=!1)=>{const n=s||!!t.locked;let o=!1;for(const e of t.children??[])o=i(e,n)||o;return(n||o)&&e.add(t.id),n||o};return t.forEach(t=>i(t)),e}var B=/* @__PURE__ */new Map;for(const{kind:St}of m)B.set(St,{kind:St});function H(t){if(!/^[a-z][a-z0-9_-]*$/i.test(t.kind))throw new Error("Kind names must begin with a letter and contain only letters, digits, _ or -.");return t}function J(t){H(t);const e=B.get(t.kind);return B.set(t.kind,t),()=>{e?B.set(t.kind,e):B.delete(t.kind)}}function _(){return[...B.values()]}function W(t=[]){return new Map([..._(),...t.map(H)].map(t=>[t.kind,t]))}var Y=class{id;element=document.createElement("div");shape=document.createElementNS(P,"svg");text=document.createElement("div");auxiliary=document.createElement("div");previous=/* @__PURE__ */new Map;currentKind;currentDefinition;unmount;doc;item;bounds;constructor(t){this.id=t,this.element.className="ad-item",this.element.style.display="none",this.element.dataset.adId=t,this.element.tabIndex=0,this.element.setAttribute("role","img"),this.shape.classList.add("ad-shape"),this.shape.setAttribute("aria-hidden","true"),this.shape.setAttribute("overflow","visible"),this.text.className="ad-text",this.auxiliary.className="ad-auxiliary",this.element.append(this.shape,this.text,this.auxiliary)}changed(t,e){return this.previous.get(t)!==e&&(this.previous.set(t,e),!0)}paint(t,e,i,s,n,o,a){this.doc=e,this.item=t;const r=/* @__PURE__ */new Set,h=!(!n?.mount&&!n?.paint);let d=!1;if(this.currentKind!==t.kind||this.currentDefinition!==n){this.unmount?.(),this.unmount=void 0,this.currentKind=t.kind,this.currentDefinition=n,this.previous.clear();const e=this.element.style.display;this.element.removeAttribute("style"),this.element.style.display=e,this.element.className="ad-item",delete this.element.dataset.adInteractive,this.shape.removeAttribute("style"),this.text.removeAttribute("style"),this.auxiliary.removeAttribute("style"),this.element.replaceChildren(this.shape,this.text,this.auxiliary),this.shape.replaceChildren(),this.text.replaceChildren(),this.auxiliary.replaceChildren(),this.auxiliary.className="ad-auxiliary",this.shape.style.display="",this.element.dataset.adKind=t.kind,["image","video","link"].includes(t.kind)&&this.auxiliary.classList.add("ad-card"),d=!0}const l="connector"===t.kind?x(t,i,a):void 0,c=l?"":`translate3d(${t.x}px,${t.y}px,0) rotate(${t.rotation??0}deg)`;this.changed("transform",c)&&(this.element.style.transform=c,r.add("transform"));const p=`${t.w}|${t.h}`;this.changed("size",p)&&(this.element.style.width=`${l?1:t.w}px`,this.element.style.height=`${l?1:t.h}px`,this.shape.setAttribute("width",String(l?1:t.w)),this.shape.setAttribute("height",String(l?1:t.h)),r.add("geometry"));const u=JSON.stringify([t.style,s]);this.changed("style",u)&&(this.element.style.opacity=String(t.style?.opacity??1),this.element.style.color=C("ink",s),this.text.style.color=T(t,s),r.add("style"));const m=JSON.stringify([p,t.kind,t.points,t.closed,t.heads,l?.d,u]);if(this.changed("geometry",m)&&(r.add("geometry"),!h)){const e=["rect","ellipse","diamond","note","line","path","connector"];if(this.shape.style.display=e.includes(t.kind)?"":"none",e.includes(t.kind)){const e=l?.points??(t.points??[[0,0],[t.w,t.h]]).map(([t,e])=>({x:t,y:e}));this.shape.innerHTML=R(t,s,this.id,l?.d)+("line"===t.kind||l?F(e,t,s):"")}}const g=JSON.stringify([t.text,t.kind,l?.midpoint,s]);this.changed("text",g)&&(r.add("text"),h||(this.text.isContentEditable||(this.text.textContent=t.text?.value??""),this.text.style.fontSize=`${L(t.text)}px`,this.text.style.fontFamily=G(t.text?.font),this.text.style.textAlign=t.text?.align??("text"===t.kind?"start":"center"),this.text.style.justifyContent="top"===t.text?.valign?"flex-start":"bottom"===t.text?.valign?"flex-end":"center",this.text.style.alignItems="start"===t.text?.align||"text"===t.kind&&!t.text?.align?"flex-start":"end"===t.text?.align?"flex-end":"center",this.text.style.display=t.text||this.text.isContentEditable?"flex":"none",l?(this.text.style.left=`${l.midpoint.x}px`,this.text.style.top=`${l.midpoint.y}px`,this.text.style.backgroundColor=C("paper",s)):(this.text.style.left="",this.text.style.top="",this.text.style.backgroundColor="")));const f=JSON.stringify([t.kind,t.name,t.html,t.href,t.description,t.text?.value,t.media,t.media?e.media[t.media]?.src:void 0,s,!!n,t.crop]);if(this.changed("auxiliary",f)&&(r.add("content"),!h))if(this.auxiliary.replaceChildren(),"image"===t.kind){const i=t.media?e.media[t.media]:void 0;if(i){const e=document.createElement("img");e.draggable=!1,e.alt=t.name??t.text?.value??"Image",e.src=i.src,t.crop&&t.crop.w>0&&t.crop.h>0&&(e.style.width=i.w/t.crop.w*100+"%",e.style.height=i.h/t.crop.h*100+"%",e.style.left=-t.crop.x/t.crop.w*100+"%",e.style.top=-t.crop.y/t.crop.h*100+"%"),this.auxiliary.append(e)}else this.placeholder("Image unavailable")}else if("video"===t.kind||"link"===t.kind){const e=f;import("./cards-DWgSVE54.js").then(({paintCard:i})=>{this.previous.get("auxiliary")===e&&i(this.auxiliary,t,this.doc)})}else"html"===t.kind?(this.auxiliary.classList.add("ad-html-content"),o?this.auxiliary.innerHTML=o(t.html??""):this.auxiliary.textContent=t.html??"HTML content"):n||this.placeholder(`Unknown kind: ${t.kind}`);this.changed("access",`${t.locked}|${t.hidden}`)&&(this.element.classList.toggle("ad-locked",!!t.locked),this.element.tabIndex=t.hidden?-1:0);const y=n?.summarize?.(t)??`${"rect"===t.kind?"Rectangle":t.kind[0].toUpperCase()+t.kind.slice(1)}${t.text?.value||t.name||t.href?`: ${t.text?.value??t.name??t.href}`:""}`;if(this.changed("aria",y)&&this.element.setAttribute("aria-label",y),h&&this.changed("custom",JSON.stringify(Object.fromEntries(Object.entries(t).filter(([t])=>!["x","y","w","h","rotation","style","text","points","heads","closed"].includes(t)))))&&r.add("content"),d){const t=n?.mount?.(this);"function"==typeof t&&(this.unmount=t)}n?.paint?.(this,t,r)}placeholder(t){const e=document.createElement("div");e.className="ad-placeholder",e.innerHTML=`<span aria-hidden="true">◇</span><span>${O(t)}</span>`,this.auxiliary.append(e)}destroy(){this.unmount?.(),this.unmount=void 0,this.element.remove()}},V=class{host;value={x:0,y:0,zoom:1};listeners=/* @__PURE__ */new Set;observer;animation=0;width;height;constructor(t){this.host=t,this.width=t.clientWidth||800,this.height=t.clientHeight||600,"undefined"!=typeof ResizeObserver&&(this.observer=new ResizeObserver(t=>{const e=t[0]?.contentRect;!e||e.width===this.width&&e.height===this.height||(this.width=e.width,this.height=e.height,this.emit())}),this.observer.observe(t))}get state(){return{...this.value}}get zoom(){return this.value.zoom}get center(){return this.toPage({x:this.width/2,y:this.height/2})}set(t){this.stop();const e={...this.value,...t};[e.x,e.y,e.zoom].every(Number.isFinite)&&(e.zoom=Math.max(.05,Math.min(8,e.zoom)),e.x===this.value.x&&e.y===this.value.y&&e.zoom===this.value.zoom||(this.value=e,this.emit()))}emit(){for(const t of this.listeners)t(this.state)}toPage(t){return{x:(t.x-this.value.x)/this.value.zoom,y:(t.y-this.value.y)/this.value.zoom}}toScreen(t){return{x:t.x*this.value.zoom+this.value.x,y:t.y*this.value.zoom+this.value.y}}viewport(t=0){return{...this.toPage({x:-t,y:-t}),w:(this.width+2*t)/this.zoom,h:(this.height+2*t)/this.zoom}}fitState(t,e=96){const i=Math.max(120,this.width-Math.min(2*e,.3*this.width)),s=Math.max(120,this.height-Math.min(2*e,.35*this.height)),n=Math.max(.05,Math.min(1.5,i/Math.max(1,t.w),s/Math.max(1,t.h)));return{x:this.width/2-(t.x+t.w/2)*n,y:this.height/2-(t.y+t.h/2)*n,zoom:n}}fit(t,e=96){this.stop(),this.set(this.fitState(t,e))}flyTo(t){this.stop();const e=this.fitState(t);if("undefined"==typeof matchMedia||matchMedia("(prefers-reduced-motion: reduce)").matches)return void this.set(e);const i=this.state,s=performance.now(),n=t=>{const o=Math.min(1,(t-s)/280),a=1-(1-o)**3;this.set({x:i.x+(e.x-i.x)*a,y:i.y+(e.y-i.y)*a,zoom:i.zoom+(e.zoom-i.zoom)*a}),this.animation=o<1?requestAnimationFrame(n):0};this.animation=requestAnimationFrame(n)}stop(){this.animation&&cancelAnimationFrame(this.animation),this.animation=0}onChange(t){return this.listeners.add(t),()=>this.listeners.delete(t)}destroy(){this.stop(),this.observer?.disconnect(),this.listeners.clear()}};function X(t,e,i,s){return`url("data:image/svg+xml,${encodeURIComponent(`<svg xmlns="http://www.w3.org/2000/svg" width="${e}" height="${e}" viewBox="0 0 ${e} ${e}">${t}</svg>`)}") ${i.join(" ")}, ${s}`}var Q="M8.5 6.5c-1.3-.5-2.5.7-2 2l6.1 19.4c.5 1.6 2.7 1.7 3.3.1l3.1-8a1.5 1.5 0 0 1 .9-.9l8-3.1c1.6-.6 1.5-2.8-.1-3.3Z",Z=X(`<defs><radialGradient id="a"><stop stop-color="#c4b5fd" stop-opacity=".22"/><stop offset="1" stop-color="#c4b5fd" stop-opacity="0"/></radialGradient></defs><circle cx="17" cy="18" r="18" fill="url(#a)"/><path d="${Q}" fill="none" stroke="#b9a6e6" stroke-width="5" stroke-opacity=".14" stroke-linejoin="round"/><path d="${Q}" fill="#18252a" stroke="#fff" stroke-width="2" stroke-linejoin="round"/>`,36,[7,7],"default"),tt="M14 4v6m0 8v6M4 14h6m8 0h6",et=X(`<circle cx="14" cy="14" r="10" fill="#c4b5fd" fill-opacity=".06"/><path d="${tt}" stroke="#b9a6e6" stroke-opacity=".15" stroke-width="6" stroke-linecap="round"/><path d="${tt}" stroke="#fff" stroke-width="4" stroke-linecap="round"/><path d="${tt}" stroke="#18252a" stroke-width="1.7" stroke-linecap="round"/><circle cx="14" cy="14" r="1" fill="#18252a"/>`,28,[14,14],"crosshair");var it=class{root;lens;queue=[];pending=/* @__PURE__ */new Set;restore=/* @__PURE__ */new Map;cursor;name;frame=0;tick=0;generation=0;running=!1;motion=matchMedia("(prefers-reduced-motion: reduce)");quiet=()=>matchMedia("(prefers-reduced-motion: reduce)").matches||document.hidden;preference=()=>{this.quiet()&&this.clear()};maxStops;durationScale;idle=/* @__PURE__ */new Set;constructor(t,e,i={}){this.root=t,this.lens=e,this.maxStops=Math.max(1,i.maxStops??8),this.durationScale=Math.min(2,Math.max(.25,i.durationScale??1)),this.motion.addEventListener("change",this.preference),document.addEventListener("visibilitychange",this.preference)}holds(t){return this.pending.has(t)}busy(){return this.running||0!==this.frame||this.pending.size>0}whenIdle(t){this.busy()?this.idle.add(t):t()}enqueue(t,e){if(this.quiet())return;const i=e?.trim();i&&!this.name&&(this.name=i);for(const s of t)if(s.elements=s.elements.filter(t=>!this.pending.has(t)),s.elements.length){for(const t of s.elements)t.classList.add("ad-agent-pending"),t.tabIndex=-1,this.pending.add(t);this.queue.push(s)}this.running||this.frame||!this.queue.length||(this.frame=requestAnimationFrame(()=>{this.frame=0,this.run(this.generation).catch(()=>this.clear())}))}prune(){let t=!1;for(const e of[...this.pending])e.isConnected||(t=!0,this.restore.get(e)?.(),this.restore.delete(e),this.pending.delete(e));this.queue=this.queue.filter(t=>(t.elements=t.elements.filter(t=>this.pending.has(t)),t.elements.length>0)),this.pending.size||!t&&(this.running||this.frame)||this.clear()}clear(){this.generation++,cancelAnimationFrame(this.frame),cancelAnimationFrame(this.tick),this.frame=0,this.tick=0;for(const e of this.restore.values())e();this.restore.clear();for(const e of this.pending)e.classList.remove("ad-agent-pending"),e.tabIndex<0&&(e.tabIndex=0);this.pending.clear(),this.queue=[],this.cursor?.remove(),this.cursor=void 0,this.name=void 0,this.running=!1;const t=[...this.idle];this.idle.clear();for(const e of t)e()}destroy(){this.clear(),this.motion.removeEventListener("change",this.preference),document.removeEventListener("visibilitychange",this.preference)}async play(t,e,i){if(t!==this.generation)return;if(this.quiet()||e<=0)return void i(1);let s=0;await new Promise(n=>{const o=a=>{if(t!==this.generation)return this.tick=0,void n();s||(s=a);const r=Math.min(1,(a-s)/e);i(1-(1-r)**3),r<1?this.tick=requestAnimationFrame(o):(this.tick=0,n())};this.tick=requestAnimationFrame(o)})}edge(t){const{width:e,height:i}=this.lens;return[{x:-70,y:t.y+40},{x:e+70,y:t.y-40},{x:t.x-40,y:-70},{x:t.x+40,y:i+70}].sort((e,i)=>Math.hypot(e.x-t.x,e.y-t.y)-Math.hypot(i.x-t.x,i.y-t.y))[0]}transform(t){return`translate(${t.x-7}px,${t.y-7}px)`}put(t,e){t.style.transform=this.transform(e),t.dataset.adAt=`${e.x},${e.y}`}center(t){return{x:t.x+t.w/2,y:t.y+t.h/2}}async move(t,e,i,s){const n=this.lens.toScreen(i),o=this.lens.toScreen(s),a=Math.hypot(o.x-n.x,o.y-n.y);await this.play(t,Math.min(650,320+.35*a)*this.durationScale,t=>{const n=this.lens.toScreen(i),o=this.lens.toScreen(s),a=Math.min(36,Math.hypot(o.x-n.x,o.y-n.y)/8),r=1-t;this.put(e,{x:r*r*n.x+2*r*t*((n.x+o.x)/2+a)+t*t*o.x,y:r*r*n.y+2*r*t*((n.y+o.y)/2-a)+t*t*o.y})}),t===this.generation&&this.put(e,this.lens.toScreen(s))}connector(t){return t.elements.length>0&&t.elements.every(t=>"connector"===t.dataset.adKind)}onScreen(t){const e=this.lens.toScreen(t.box),i=e.x+t.box.w*this.lens.zoom,s=e.y+t.box.h*this.lens.zoom,{width:n,height:o}=this.lens;return i>=0&&s>=0&&e.x<=n&&e.y<=o}visitable(t){return t.elements.some(t=>t.isConnected)&&!this.connector(t)&&this.onScreen(t)}take(t){return t.splice(0).flatMap(t=>t.elements)}show(t,e){this.pending.has(e)&&(e.classList.remove("ad-agent-pending"),e.tabIndex=0,this.pending.delete(e),this.reveal(t,e))}reveal(t,e){const i=e.style.opacity||"1",s=e.style.transform,n=Number(i),o=()=>{e.style.opacity=i,e.style.transform=s};this.restore.set(e,o),this.play(t,220*this.durationScale,t=>{e.style.opacity=String(n*t),"connector"!==e.dataset.adKind&&(e.style.transform=`${s} scale(${.97+.03*t})`)}).then(()=>{t===this.generation&&(o(),this.restore.delete(e))})}async run(t){let e;this.running=!0;let i=0;const s=[];for(;this.queue.length&&t===this.generation;){if(this.quiet())return void this.clear();if(this.prune(),t!==this.generation)return;const n=this.queue.shift();if(!n)break;if(!this.visitable(n)){s.push(n);continue}(++i>=this.maxStops||!this.queue.some(t=>this.visitable(t)))&&n.elements.push(...this.take(s),...this.take(this.queue));const o=this.center(n.box);if(!this.cursor){this.cursor=document.createElement("div"),this.cursor.className="ad-agent-cursor",this.cursor.setAttribute("aria-hidden","true"),this.cursor.innerHTML=`<svg width="36" height="36" viewBox="0 0 36 36"><path d="${Q}"/></svg>${this.name?`<span>${O(this.name)}</span>`:""}`;const t=this.edge(this.lens.toScreen(o));e=this.lens.toPage(t),this.put(this.cursor,t),this.cursor.dataset.adFrom=`${t.x},${t.y}`,this.root.append(this.cursor)}const a=this.cursor;if(await this.move(t,a,e,o),t!==this.generation)return;const r=this.lens.toScreen(o);a.dataset.adLanded=`${r.x},${r.y}`,e=o;for(const e of n.elements)this.show(t,e);const h=a.querySelector("svg");h&&await this.play(t,260*this.durationScale,t=>{h.style.transform=`scale(${t<.35?1-t/.35*.1:.9+(t-.35)/.65*.1})`}),h&&t===this.generation&&(h.style.transform="")}if(t===this.generation){if(s.length)for(const e of this.take(s))this.show(t,e);if(t===this.generation){if(this.cursor&&e){const i=this.lens.toPage(this.edge(this.lens.toScreen(e)));await this.move(t,this.cursor,e,i)}if(t===this.generation){if(this.cursor?.remove(),this.cursor=void 0,this.queue.length)return this.run(t);this.clear()}}}}},st=class{host;options;root=document.createElement("div");world=document.createElement("div");overlay=document.createElementNS(P,"svg");lens;kinds;resolveOutline=t=>this.kinds.get(t.kind)?.outline?.(t);grid=document.createElement("div");records=/* @__PURE__ */new Map;lookup=/* @__PURE__ */new Map;originals=/* @__PURE__ */new Map;ancestors=/* @__PURE__ */new Map;locked=/* @__PURE__ */new Set;presence;dependencies=/* @__PURE__ */new Map;previousDrafts=/* @__PURE__ */new Set;paintedTheme;index=new o;visible=/* @__PURE__ */new Set;selected=[];marquee;overlayMarkup="";theme="light";mediaQuery;mediaListener;settleTimer;cameraFrame=0;disposed=!1;doc;pageId;drafts;constructor(t,e={}){this.host=t,this.options=e,this.kinds=W(e.kinds),this.root.className="ad-root",this.root.tabIndex=0,this.root.setAttribute("role","application"),this.root.setAttribute("aria-label","Drawing board"),this.grid.className="ad-grid",this.world.className="ad-world",this.overlay.classList.add("ad-overlay"),this.overlay.setAttribute("aria-label","Selection controls"),this.root.append(this.grid,this.world,this.overlay),t.append(this.root),this.lens=new V(this.root),this.lens.onChange(()=>{this.cameraFrame||(this.cameraFrame=requestAnimationFrame(()=>{this.cameraFrame=0,this.updateCamera()}))}),"undefined"!=typeof matchMedia&&(this.mediaQuery=matchMedia("(prefers-color-scheme: dark)"),this.mediaListener=()=>{e.theme&&"auto"!==e.theme||this.setTheme("auto")},this.mediaQuery.addEventListener("change",this.mediaListener)),this.setTheme(e.theme??"light"),this.updateCamera()}setTheme(t){this.options.theme=t,this.theme="auto"===t?this.mediaQuery?.matches?"dark":"light":t,this.root.dataset.theme=this.theme,this.doc&&this.pageId&&this.render(this.doc,this.pageId,this.drafts)}get resolvedTheme(){return this.theme}whenPresentationIdle(t){this.presence?this.presence.whenIdle(t):t()}present(t,e){if(!1===this.options.agentPresence)return;const i=new Set(t),s=t.filter(t=>!this.ancestors.get(t)?.some(t=>i.has(t))).flatMap(t=>{const e=this.records.get(t),i=this.lookup.get(t);return e&&i&&!e.hidden?[{box:e.view.bounds,elements:w([i]).flatMap(t=>{const e=this.records.get(t.id);return e&&!e.hidden?[e.view.element]:[]})}]:[]});s.length&&(this.presence??=new it(this.root,this.lens,"object"==typeof this.options.agentPresence?this.options.agentPresence:void 0),this.presence.enqueue(s,e))}finishPresentation(){this.presence?.clear()}prunePresentation(){this.presence?.prune()}isPending(t){const e=this.records.get(t)?.view.element;return!!e&&!!this.presence?.holds(e)}render(t,e,i){if(this.disposed)return;const s=this.doc===t&&this.pageId===e&&this.paintedTheme===this.theme;if(this.doc=t,this.pageId=e,this.drafts=i,s)return void this.renderDrafts(i);this.paintedTheme=this.theme;const n=t.pages.find(t=>t.id===e);this.root.style.backgroundColor=C(n?.background??("dark"===this.theme?"#122f32":"#fbfcfa"),this.theme);const o=[];this.lookup.clear(),this.originals.clear(),this.ancestors.clear(),this.dependencies.clear();const a=(t,e,s)=>{for(const n of t){const t=k(n,i?.get(n.id)),r=s||!!t.hidden;if(this.lookup.set(t.id,t),this.originals.set(t.id,n),this.ancestors.set(t.id,e.map(t=>t.id)),"connector"===t.kind)for(const e of[t.from,t.to]){if(!e||!("item"in e))continue;const i=this.dependencies.get(e.item)??/* @__PURE__ */new Set;i.add(t.id),this.dependencies.set(e.item,i)}o.push({item:t,hidden:r}),t.children&&a(t.children,[...e,t],r)}};a(n?.items??[],[],!1),this.locked=K(n?.items??[]);const r=/* @__PURE__ */new Set;for(let d=0;d<o.length;d++){const{item:e,hidden:i}=o[d];r.add(e.id);let s=this.records.get(e.id);const n=I(e,this.lookup,this.resolveOutline),a={minX:n.x,minY:n.y,maxX:n.x+n.w,maxY:n.y+n.h,id:e.id};s?s.entry.minX===a.minX&&s.entry.minY===a.minY&&s.entry.maxX===a.maxX&&s.entry.maxY===a.maxY||(this.index.remove(s.entry),s.entry=a,this.index.insert(a)):(s={view:new Y(e.id),entry:a,hidden:i},this.records.set(e.id,s),this.index.insert(a)),s.hidden=i,s.view.bounds=n,s.view.paint(e,t,this.lookup,this.theme,this.kinds.get(e.kind),this.options.sanitizeHTML,this.resolveOutline),s.view.element.style.zIndex!==String(d)&&(s.view.element.style.zIndex=String(d))}for(const[d,l]of this.records)r.has(d)||(this.index.remove(l.entry),l.view.destroy(),this.records.delete(d),this.visible.delete(d));const h=o.map(({item:t})=>this.records.get(t.id)).sort((t,e)=>t.view.bounds.y-e.view.bounds.y||t.view.bounds.x-e.view.bounds.x);for(let d=0;d<h.length;d++){const t=h[d].view.element;this.world.children[d]!==t&&this.world.insertBefore(t,this.world.children[d]??null)}this.previousDrafts=new Set(i?.keys()),this.updateCulling(),this.paintOverlay(),this.presence?.prune()}renderDrafts(t){const e=/* @__PURE__ */new Set([...this.previousDrafts,...t?.keys()??[]]);for(const i of e){const s=this.originals.get(i);if(!s)continue;const n=t?.get(i);this.lookup.set(i,k(s,n));for(const t of this.ancestors.get(i)??[])e.add(t);if(s.children)for(const t of w(s.children))e.add(t.id)}for(const i of[...e])for(const t of this.dependencies.get(i)??[])e.add(t);for(const i of e){const t=this.lookup.get(i),e=this.records.get(i);if(!t||!e)continue;const s=I(t,this.lookup,this.resolveOutline),n={minX:s.x,minY:s.y,maxX:s.x+s.w,maxY:s.y+s.h,id:i};JSON.stringify(n)!==JSON.stringify(e.entry)&&(this.index.remove(e.entry),this.index.insert(n),e.entry=n),e.view.bounds=s;const o=(this.ancestors.get(i)??[]).map(t=>this.lookup.get(t)).filter(Boolean);e.hidden=!!t.hidden||o.some(t=>t.hidden),e.view.paint(t,this.doc,this.lookup,this.theme,this.kinds.get(t.kind),this.options.sanitizeHTML,this.resolveOutline)}this.previousDrafts=new Set(t?.keys()),e.size&&(this.updateCulling(),this.paintOverlay()),this.presence?.prune()}setSelection(t){if(t.length===this.selected.length&&t.every((t,e)=>t===this.selected[e]))return;const e=new Set(this.selected);this.selected=[...t];for(const i of e)t.includes(i)||this.records.get(i)?.view.element.removeAttribute("data-ad-selected");for(const i of t)this.records.get(i)?.view.element.setAttribute("data-ad-selected","true");this.paintOverlay()}setMarquee(t){this.marquee=t,this.paintOverlay()}updateCamera(){const{x:t,y:e,zoom:i}=this.lens.state;this.world.style.transform=`translate3d(${t}px,${e}px,0) scale(${i})`,this.world.style.willChange="transform",clearTimeout(this.settleTimer),this.settleTimer=setTimeout(()=>{this.world.style.willChange=""},150);const s=24*i*(i<.3?4:i<.6?2:1);this.grid.style.backgroundSize=`${s}px ${s}px`,this.grid.style.backgroundPosition=`${t}px ${e}px`,this.updateCulling(),this.paintOverlay()}updateCulling(){const t=this.lens.viewport(200),e=this.index.search({minX:t.x,minY:t.y,maxX:t.x+t.w,maxY:t.y+t.h}),i=new Set(e.filter(t=>!this.records.get(t.id)?.hidden).map(t=>t.id));for(const s of this.visible)if(!i.has(s)){const t=this.records.get(s);t&&(t.view.element.style.display="none")}for(const s of i)if(!this.visible.has(s)){const t=this.records.get(s);t&&(t.view.element.style.display="")}this.visible=i}paintOverlay(){const t=[],e=this.selected.map(t=>this.lookup.get(t)).filter(t=>!!t&&!t.hidden);if(e.length){const i=1===e.length&&!["connector","line","path","group"].includes(e[0].kind),s=i?e[0]:b(e,this.lookup,this.resolveOutline),n=i?e[0].rotation??0:0,o=$(s,n).map(t=>this.lens.toScreen(t));t.push(`<path class="ad-selection-outline" d="${A(o,!0)}"/>`);const a=[["nw",o[0],"nwse-resize"],["n",{x:(o[0].x+o[1].x)/2,y:(o[0].y+o[1].y)/2},"ns-resize"],["ne",o[1],"nesw-resize"],["e",{x:(o[1].x+o[2].x)/2,y:(o[1].y+o[2].y)/2},"ew-resize"],["se",o[2],"nwse-resize"],["s",{x:(o[2].x+o[3].x)/2,y:(o[2].y+o[3].y)/2},"ns-resize"],["sw",o[3],"nesw-resize"],["w",{x:(o[3].x+o[0].x)/2,y:(o[3].y+o[0].y)/2},"ew-resize"]];if(!e.some(t=>this.locked.has(t.id))){for(const[e,i,s]of a)t.push(`<rect class="ad-selection-handle" data-ad-handle="${e}" x="${i.x-4}" y="${i.y-4}" width="8" height="8" rx="2" style="cursor:${s}" aria-label="Resize ${e}"/>`);{const e=a[1][1],i=n*Math.PI/180,s={x:e.x+26*Math.sin(i),y:e.y-26*Math.cos(i)};t.push(`<path class="ad-selection-outline" d="M${e.x},${e.y}L${s.x},${s.y}"/><circle class="ad-selection-handle" data-ad-handle="rotate" cx="${s.x}" cy="${s.y}" r="4.5" style="cursor:grab" aria-label="Rotate"/>`)}}}if(1===e.length&&!this.locked.has(e[0].id)){const i=e[0],s=this.kinds.get(i.kind)?.handles?.(i)??[],n=(i.rotation??0)*Math.PI/180;for(const e of s){const s=e.x-i.w/2,o=e.y-i.h/2,a=this.lens.toScreen({x:i.x+i.w/2+s*Math.cos(n)-o*Math.sin(n),y:i.y+i.h/2+s*Math.sin(n)+o*Math.cos(n)});t.push(`<circle class="ad-selection-handle ad-custom-handle" data-ad-custom-handle="${O(e.id)}" data-ad-handle="custom:${O(e.id)}" cx="${a.x}" cy="${a.y}" r="5" style="cursor:${O(e.cursor??"crosshair")}" aria-label="${O(e.label??e.id)}"/>`)}}if(this.marquee){const e=this.lens.toScreen(this.marquee);t.push(`<rect class="ad-marquee" x="${e.x}" y="${e.y}" width="${Math.max(0,this.marquee.w*this.lens.zoom)}" height="${Math.max(0,this.marquee.h*this.lens.zoom)}"/>`)}const i=t.join("");i!==this.overlayMarkup&&(this.overlayMarkup=i,this.overlay.innerHTML=i)}destroy(){this.disposed=!0,this.presence?.destroy(),clearTimeout(this.settleTimer),cancelAnimationFrame(this.cameraFrame),this.mediaQuery&&this.mediaListener&&this.mediaQuery.removeEventListener("change",this.mediaListener),this.lens.destroy();for(const t of this.records.values())t.view.destroy();this.records.clear(),this.index.clear(),this.root.remove()}};function nt(t,e,i){if(!t.text?.value)return"";const s=L(t.text),n="text"===t.kind?0:"note"===t.kind?20:12,o=i?220:t.w*("diamond"===t.kind?.6:"ellipse"===t.kind?.75:1)-2*n,a=function(t,e,i){const s=Math.max(1,Math.floor(e/(.53*i))),n=[];for(const o of t.split("\n")){if(!o){n.push("");continue}let t="";for(const e of o.split(/\s+/)){t&&t.length+e.length+1>s&&(n.push(t),t="");let i=e;for(;i.length>s;)t&&(n.push(t),t=""),n.push(i.slice(0,s)),i=i.slice(s);t+=`${t?" ":""}${i}`}n.push(t)}return n}(t.text.value,o,s),r=1.35*s,h=t.text.align??("text"===t.kind?"start":"center"),d="start"===h?"start":"end"===h?"end":"middle",l=i?.x??("start"===h?n:"end"===h?t.w-n:t.w/2),c=a.length*r,p=i?i.y-c/2+s:"top"===t.text.valign?n+s:"bottom"===t.text.valign?t.h-n-c+s:(t.h-c)/2+s,u=Math.max(...a.map(t=>t.length))*s*.53;return`${i?`<rect x="${l-u/2-7}" y="${i.y-c/2-2}" width="${u+14}" height="${c+4}" rx="4" fill="${C("paper",e)}"/>`:""}<text x="${l}" y="${p}" font-family="${O(G(t.text.font))}" font-size="${s}" text-anchor="${i?"middle":d}" fill="${O(T(t,e))}">${a.map((t,e)=>`<tspan x="${l}" dy="${e?r:0}">${O(t)||"&#160;"}</tspan>`).join("")}</text>`}function ot(t,e,i){const s=Math.max(1,Math.floor(e/(.52*i))),n=t.trim();return n.length<=s?n:`${n.slice(0,Math.max(1,s-1))}…`}function at(t,e){const i=r(t);return i?`<a href="${O(i)}" target="_blank" rel="noopener noreferrer" style="text-decoration:none">${e}</a>`:e}function rt(t,s,n,o){const a=Math.min(t.style?.corner??12,t.w/2,t.h/2),h=t.w,d=t.h,l=`adx${o}`,c=D.sans,p=t.href,u=function(t,i){const s=t.text?.value?.trim()||t.name?.trim();if(s&&s.toLowerCase()!==t.kind)return s;if(i){const t=e(i).split(".")[0]??"";if(t)return t[0].toUpperCase()+t.slice(1)}return"video"===t.kind?"Video":"Link"}(t,p),m=function(t){const i=r(t);if(!i)return"";try{const t=new URL(i),s=decodeURIComponent(t.pathname).replace(/\/$/,""),n=`${e(i)}${s}`;return t.search&&n.length<36?`${n}${t.search}`:n}catch{return i.replace(/^https?:\/\//,"").replace(/\/$/,"")}}(p),g=Math.max(10,Math.min(14,.04*h)),f=`<defs><clipPath id="${l}p"><rect width="${h}" height="${d}" rx="${a}"/></clipPath></defs>`;if("video"===t.kind){const t=i(p),e="vimeo"===t?.provider?"Vimeo":t?"YouTube":"",s=.11*Math.min(h,d),n=d>=96?.58*d:d,o=h/2+.06*s,a=d/2,r=ot(u,h-2*g,15),y=ot(m,h-2*g,12);return`${f}<defs>\n <linearGradient id="${l}g" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stop-color="#16494c"/><stop offset="1" stop-color="#103639"/></linearGradient>\n <radialGradient id="${l}s" cx="50%" cy="50%" r="58%"><stop offset="0" stop-color="#05D9AB" stop-opacity=".2"/><stop offset="1" stop-color="#103639" stop-opacity="0"/></radialGradient>\n <linearGradient id="${l}c" x1="0" y1="0" x2="0" y2="1"><stop offset="0" stop-color="#103639" stop-opacity="0"/><stop offset="1" stop-color="#103639" stop-opacity=".92"/></linearGradient>\n </defs>${at(p,`<g clip-path="url(#${l}p)">\n <rect width="${h}" height="${d}" fill="url(#${l}g)"/><rect width="${h}" height="${d}" fill="url(#${l}s)"/>\n <circle cx="${U(h/2)}" cy="${U(a)}" r="${U(1.7*s)}" fill="#fff" fill-opacity=".1"/>\n <path d="M${U(o-.36*s)} ${U(a-.7*s)}L${U(o+.7*s)} ${U(a)}L${U(o-.36*s)} ${U(a+.7*s)}Z" fill="#fff"/>\n ${d>=96?`<rect y="${U(n)}" width="${h}" height="${U(d-n)}" fill="url(#${l}c)"/>`:""}\n ${e&&d>=120?`<text x="${g}" y="${g+10}" fill="#05D9AB" font-family="${O(c)}" font-size="11" font-weight="700">${e}</text>`:""}\n <text x="${g}" y="${d-(y?28:16)}" fill="#fff" font-family="${O(c)}" font-size="15" font-weight="700">${O(r)}</text>\n ${y?`<text x="${g}" y="${d-12}" fill="#B6C5C1" font-family="${O(c)}" font-size="12">${O(y)}</text>`:""}\n </g>`)}`}const y=d>=118?Math.min(.48*d,d-62):0,x=t.media?n.media[t.media]:void 0,v=u.trim().slice(0,1).toUpperCase()||"•",w=y?x?`<image width="${h}" height="${y}" href="${O(x.src)}" preserveAspectRatio="xMidYMid slice"/>`:`<rect width="${h}" height="${y}" fill="#8F93F914"/><text x="${h/2}" y="${y/2+11}" text-anchor="middle" fill="#8F93F9" font-family="${O(c)}" font-size="${Math.min(34,.28*y)}" font-weight="700">${O(v)}</text>`:"",k=y?y+20:24,b=ot(u,h-2*g,15),$=ot(m,h-2*g,12),M=t.description&&d-y>78?ot(t.description,h-2*g,12):"",S="dark"===s?"#ffffff14":"#10363914";return`${f}${at(p,`<g clip-path="url(#${l}p)">\n <rect width="${h}" height="${d}" fill="${C("paper",s)}"/>${w}\n <text x="${g}" y="${k}" fill="${C("ink",s)}" font-family="${O(c)}" font-size="15" font-weight="700">${O(b)}</text>\n ${$?`<text x="${g}" y="${k+18}" fill="${C("slate",s)}" font-family="${O(c)}" font-size="12">${O($)}</text>`:""}\n ${M?`<text x="${g}" y="${k+36}" fill="${C("slate",s)}" font-family="${O(c)}" font-size="12">${O(M)}</text>`:""}\n </g><rect width="${h}" height="${d}" rx="${a}" fill="none" stroke="${S}"/>`)}`}var ht=/* @__PURE__ */new Uint32Array(256);for(let St=0;St<256;St++){let t=St;for(let e=0;e<8;e++)t=1&t?3988292384^t>>>1:t>>>1;ht[St]=t}function dt(t){return Uint8Array.of(t>>>24&255,t>>>16&255,t>>>8&255,255&t)}function lt(t,e){const i=Uint8Array.of(t.charCodeAt(0),t.charCodeAt(1),t.charCodeAt(2),t.charCodeAt(3)),s=new Uint8Array(12+e.length);return s.set(dt(e.length)),s.set(i,4),s.set(e,8),s.set(dt(function(t){let e=-1;for(const i of t)for(const t of i)e=ht[255&(e^t)]^e>>>8;return~e>>>0}([i,e])),8+e.length),s}function ct(t,e,i,s){return(t<<24|e<<16|i<<8|s)>>>0}function pt(t){const e=/* @__PURE__ */new Uint32Array(32768);let i=0;for(let n=0;n<t.length;n+=4)t[n+3]<128?i++:e[t[n]>>3<<10|t[n+1]>>3<<5|t[n+2]>>3]++;const s=[];i&&s.push({r:0,g:0,b:0,a:0,n:i});for(let n=0;n<32768;n++){const t=e[n];if(!t)continue;const i=n>>10<<3,o=(n>>5&31)<<3,a=(31&n)<<3;s.push({r:i|i>>5,g:o|o>>5,b:a|a>>5,a:255,n:t})}return s}function ut(t){let e=255,i=0,s=255,n=0,o=255,a=0,r=255,h=0;for(const u of t)u.r<e&&(e=u.r),u.r>i&&(i=u.r),u.g<s&&(s=u.g),u.g>n&&(n=u.g),u.b<o&&(o=u.b),u.b>a&&(a=u.b),u.a<r&&(r=u.a),u.a>h&&(h=u.a);const d=i-e,l=n-s,c=a-o,p=h-r;return d>=l&&d>=c&&d>=p?"r":l>=c&&l>=p?"g":c>=p?"b":"a"}function mt(t){let e=0,i=0,s=0,n=0,o=0;for(const a of t)e+=a.r*a.n,i+=a.g*a.n,s+=a.b*a.n,n+=a.a*a.n,o+=a.n;return{r:Math.round(e/o),g:Math.round(i/o),b:Math.round(s/o),a:Math.round(n/o)}}function gt(t,e,i,s,n){let o=0,a=1/0;for(let r=0;r<t.length;r++){const h=t[r],d=(e-h.r)**2+(i-h.g)**2+(s-h.b)**2+(n-h.a)**2;d<a&&(a=d,o=r)}return o}function ft(t,e){const i=Math.min(256,Math.max(1,Math.trunc(e))),{colors:s,exact:n}=function(t){const e=/* @__PURE__ */new Map;for(let i=0;i<t.length;i+=4){const s=ct(t[i],t[i+1],t[i+2],t[i+3]),n=e.get(s);if(n)n.n++;else{if(e.size>=4096)return{colors:pt(t),exact:!1};e.set(s,{r:t[i],g:t[i+1],b:t[i+2],a:t[i+3],n:1})}}return{colors:[...e.values()],exact:!0}}(t),o=n&&s.length<=i?s.map(({r:t,g:e,b:i,a:s})=>({r:t,g:e,b:i,a:s})):function(t,e){if(t.length<=e)return t.map(({r:t,g:e,b:i,a:s})=>({r:t,g:e,b:i,a:s}));const i=[t];for(;i.length<e;){let t=-1,e=-1;for(let h=0;h<i.length;h++){if(i[h].length<2)continue;const s=ut(i[h]);let n=255,o=0;for(const t of i[h]){const e=t[s];e<n&&(n=e),e>o&&(o=e)}const a=o-n;a>e&&(e=a,t=h)}if(t<0)break;const s=i[t],n=ut(s);s.sort((t,e)=>t[n]-e[n]);let o=0;for(const i of s)o+=i.n;let a=0,r=Math.max(1,s.length>>1);for(let i=0;i<s.length-1;i++)if(a+=s[i].n,a>=o/2){r=i+1;break}i[t]=s.slice(0,r),i.push(s.slice(r))}return i.map(mt)}(s,i),a=new Uint8Array(t.length/4);if(n&&s.length<=i){const e=/* @__PURE__ */new Map;for(let t=0;t<o.length;t++){const i=o[t];e.set(ct(i.r,i.g,i.b,i.a),t)}for(let i=0,s=0;i<a.length;i++,s+=4)a[i]=e.get(ct(t[s],t[s+1],t[s+2],t[s+3]))}else{const e=/* @__PURE__ */new Map;for(let i=0,s=0;i<a.length;i++,s+=4){const n=ct(t[s],t[s+1],t[s+2],t[s+3]);let r=e.get(n);void 0===r&&(r=gt(o,t[s],t[s+1],t[s+2],t[s+3]),e.set(n,r)),a[i]=r}}return{palette:o,indices:a}}async function yt(t,e,i,s){if(t<1||e<1||i.length<1||i.length>256)throw new Error("Indexed PNG dimensions or palette are invalid.");if(s.length!==t*e)throw new Error("Indexed PNG indices do not match size.");const n=/* @__PURE__ */new Uint8Array(13);n.set(dt(t)),n.set(dt(e),4),n[8]=8,n[9]=3;const o=new Uint8Array(3*i.length);let a=-1;for(let p=0;p<i.length;p++)o[3*p]=i[p].r,o[3*p+1]=i[p].g,o[3*p+2]=i[p].b,i[p].a<255&&(a=p);const r=new Uint8Array((t+1)*e);for(let p=0;p<e;p++){const e=p*(t+1);r[e]=0,r.set(s.subarray(p*t,(p+1)*t),e+1)}const h=[Uint8Array.of(137,80,78,71,13,10,26,10),lt("IHDR",n),lt("PLTE",o)];if(a>=0){const t=new Uint8Array(a+1);for(let e=0;e<=a;e++)t[e]=i[e].a;h.push(lt("tRNS",t))}h.push(lt("IDAT",await async function(t){if("function"!=typeof CompressionStream)throw new Error("CompressionStream is unavailable.");const e=new Response(t).body;if(!e)throw new Error("CompressionStream is unavailable.");return new Uint8Array(await new Response(e.pipeThrough(new CompressionStream("deflate"))).arrayBuffer())}(r)),lt("IEND",/* @__PURE__ */new Uint8Array));let d=0;for(const p of h)d+=p.length;const l=new Uint8Array(d);let c=0;for(const p of h)l.set(p,c),c+=p.length;return new Blob([l],{type:"image/png"})}var xt={png:"image/png",jpeg:"image/jpeg",webp:"image/webp"},vt=[.85,.7,.55,.4];var wt=/* @__PURE__ */new Map;function kt(t,e){const i=JSON.stringify(e),s=wt.get(i);if(s)return wt.delete(i),wt.set(i,s),s;const n=t.createElement("div");n.style.cssText="position:fixed;left:-100000px;top:0;visibility:hidden;pointer-events:none;white-space:pre;line-height:1.35;width:max-content;max-width:none;padding:0;border:0;",n.style.fontFamily=G(e.font),n.style.fontSize=`${L(e)}px`,n.textContent=e.value||" ",t.body.append(n);const o=n.getBoundingClientRect(),a={w:Math.max(24,Math.ceil(o.width+4)),h:Math.max(1.35*L(e),Math.ceil(o.height))};return n.remove(),wt.set(i,a),wt.size>256&&wt.delete(wt.keys().next().value),a}var bt={v:"select",h:"hand",r:"rect",o:"ellipse",d:"diamond",l:"line",a:"connector",p:"path",t:"text",n:"note",e:"eraser"},$t=class{host;stage;model;ready;readonly;agentName;selectionSignal=n([]);toolSignal=n("select");drafts=/* @__PURE__ */new Map;defaultStyle={stroke:"ink",strokeWidth:2,fill:"paper",corner:12};grid=!0;pageId;document;spatial=new a;geometryLookup=/* @__PURE__ */new Map;hiddenGeometry=/* @__PURE__ */new Set;lockedGeometry=/* @__PURE__ */new Set;listeners=/* @__PURE__ */new Map;cleanup=[];uiCleanup;frame=0;drag;rect;space=!1;clipboard=[];pointers=/* @__PURE__ */new Map;pinch;editor;finishEditor;longPressTimer;lastTouchTap;touchDoubleAt=0;enteredGroup;destroyed=!1;themeValue;drawPreview;previewDocument;previewBase;observer;unfurl;agentReveal;pendingReveal;constructor(e,i={}){this.host=e,this.readonly=i.readonly??!1,this.agentName=i.agentName?.trim()||void 0,this.agentReveal=i.agentReveal??"fit",this.model=t(i.doc,{readonly:this.readonly,allowedImageOrigins:i.allowedImageOrigins,kinds:[..._(),...i.kinds??[]],sanitizeHTML:i.sanitizeHTML,agentHistory:i.agentHistory,agentPlaceGap:i.agentPlaceGap}),this.document=this.model.toJSON({compact:!1}),this.pageId=this.document.pages[0].id,this.themeValue=i.theme??"light",this.unfurl=i.unfurl,this.stage=new st(e,{agentPresence:i.agentPresence,theme:this.themeValue,kinds:i.kinds,sanitizeHTML:i.sanitizeHTML}),this.updateCursor(),this.refreshGeometry(),this.rect=this.stage.root.getBoundingClientRect(),this.stage.root.dataset.adBoard="",this.cleanup.push(this.model.on("change",t=>{this.document=this.model.toJSON({compact:!1}),this.document.pages.some(t=>t.id===this.pageId)||(this.pageId=this.document.pages[0].id),this.refreshGeometry(),(this.drag&&["move","resize","rotate","erase"].includes(this.drag.kind)&&this.drag.ids.some(t=>this.isLocked(t))||this.editor&&this.isLocked(this.editor.closest("[data-ad-id]")?.dataset.adId??""))&&this.cancel(),this.select(this.selection.filter(t=>!!this.get(t))),this.schedule(),this.emit("change",t)})),this.cleanup.push(this.stage.lens.onChange(t=>{this.schedule(),this.emit("view",t)}));const s=(t,e,i)=>{this.stage.root.addEventListener(t,e,i),this.cleanup.push(()=>this.stage.root.removeEventListener(t,e,i))};s("pointerdown",this.pointerDown),s("pointermove",this.pointerMove),s("pointerup",this.pointerUp),s("pointercancel",this.pointerCancel),s("wheel",this.wheel,{passive:!1}),s("keydown",this.keyDown),s("keyup",t=>{"Space"===t.code&&(this.space=!1,this.updateCursor())}),s("dblclick",this.doubleClick),s("contextmenu",t=>{if(this.isUI(t.target))return;t.preventDefault();const e=t.target.closest("[data-ad-id]")?.dataset.adId;this.openContext(this.point(t),e)}),s("copy",this.copyEvent),s("cut",this.cutEvent),s("paste",this.pasteEvent),s("dragover",t=>{this.readonly||(t.preventDefault(),t.dataTransfer&&(t.dataTransfer.dropEffect="copy"))}),s("drop",this.drop),s("focusin",t=>{const e=t.target.closest("[data-ad-id]");e&&t.target===e&&!this.drag&&this.select([e.dataset.adId])});const n=()=>{this.space=!1,this.finishEditor?.(!0),this.cancel(),this.updateCursor()};window.addEventListener("blur",n),this.cleanup.push(()=>window.removeEventListener("blur",n)),this.observer=new ResizeObserver(()=>{this.rect=this.stage.root.getBoundingClientRect(),this.schedule()}),this.observer.observe(this.stage.root);const o=()=>{this.rect=this.stage.root.getBoundingClientRect()};window.addEventListener("scroll",o,!0),this.cleanup.push(()=>window.removeEventListener("scroll",o,!0)),!1!==i.ui&&(this.uiCleanup=j(this,"object"==typeof i.ui?i.ui:{})),this.render(),this.view.fit(),i.exposeGlobal&&(window.__anniedrawing??=[],window.__anniedrawing.push(this)),this.ready=i.autosaveKey&&!this.readonly?async function(t,e){let i,s,n=!1,o=()=>{};const a=JSON.stringify(t.read()),r=(e,i)=>{n||t.emit("save",{status:e,message:i})},h=()=>{if(!n&&i)try{r("saving");const s=i.transaction("boards","readwrite");s.objectStore("boards").put(t.read(),e),s.oncomplete=()=>r("saved"),s.onerror=()=>r("error","Could not save locally. Export your drawing to keep it.")}catch{r("error","Could not save locally. Export your drawing to keep it.")}},d=()=>{s&&(clearTimeout(s),s=void 0,h())};t.addCleanup(()=>{d(),n=!0,o(),window.removeEventListener("pagehide",d),i?.close()});try{if(i=await new Promise((t,e)=>{const i=indexedDB.open("anniedrawing",1);i.onupgradeneeded=()=>i.result.createObjectStore("boards"),i.onsuccess=()=>t(i.result),i.onerror=()=>e(i.error)}),n)return void i.close();const s=await new Promise((t,s)=>{const n=i.transaction("boards","readonly").objectStore("boards").get(e);n.onsuccess=()=>t(n.result),n.onerror=()=>s(n.error)});if(n)return void i.close();s&&JSON.stringify(t.read())===a&&t.load(s),r("saved")}catch{return void r("error","Browser storage is unavailable. Export your drawing to keep it.")}o=t.on("change",()=>{r("saving"),s&&clearTimeout(s),s=setTimeout(()=>{s=void 0,h()},300)}),window.addEventListener("pagehide",d)}(this,i.autosaveKey):Promise.resolve()}get selection(){return[...this.selectionSignal.value]}get tool(){return this.toolSignal.value}get theme(){return this.themeValue}get canUndo(){return this.model.canUndo}get canRedo(){return this.model.canRedo}get revision(){return this.model.revision}changesSince(t,e){return this.model.changesSince(t,e)}get items(){return w(this.pageItems())}get view(){const t=this;return{fit(e){t.stage.lens.fit(t.boundsOf(e))},flyTo(e){t.stage.lens.flyTo(e)},get zoom(){return t.stage.lens.state.zoom},set zoom(e){t.zoomAt(e,{x:t.rect.width/2,y:t.rect.height/2})},get center(){return t.stage.lens.toPage({x:t.rect.width/2,y:t.rect.height/2})},set center(e){const i=t.view.zoom;t.stage.lens.set({x:t.rect.width/2-e.x*i,y:t.rect.height/2-e.y*i})}}}read(t="doc"){const e="string"==typeof t?{scope:t}:t,i=this.model.toJSON();if(e.includeDrafts&&this.drawPreview&&i.pages.find(t=>t.id===this.pageId)?.items.push(h(this.drawPreview)),e.scope&&"doc"!==e.scope&&(i.pages=i.pages.filter(t=>t.id===this.pageId)),"selection"===e.scope||"viewport"===e.scope){const t="selection"===e.scope?new Set(this.selection):new Set(this.items.filter(t=>!t.hidden&&this.visible(t)).map(t=>t.id)),s=e=>e.flatMap(e=>t.has(e.id)?[e]:s(e.children??[]));for(const e of i.pages)e.items=s(e.items)}if(e.includeDrafts)for(const s of i.pages.flatMap(t=>w(t.items))){const t=k(s,this.drafts.get(s.id));Object.assign(s,t)}if(e.scope&&"doc"!==e.scope){const t=new Set(i.pages.flatMap(t=>w(t.items)).map(t=>t.media));i.media=Object.fromEntries(Object.entries(i.media).filter(([e])=>t.has(e)))}return i}get(t){return this.model.get(t)}isLocked(t){return this.lockedGeometry.has(t)}lockedResult(t=0){return{ok:!1,created:[],errors:[{index:t,code:"LOCKED",message:"Unlock the selection before editing it."}],warnings:[]}}query(t={}){return this.model.query(t)}describe(t={}){return this.model.describe({...t,page:t.page??("doc"!==t.scope&&t.scope?this.pageId:void 0),selection:t.selection??this.selection,..."viewport"===t.scope?{ids:this.items.filter(t=>!t.hidden&&this.visible(t)).map(t=>t.id)}:{}})}kindsSince(t=0){return d(t)}boundsOf(t){const e=t?new Set(t):void 0,i=this.spatial.search({x:-1e7,y:-1e7,w:2e7,h:2e7}),s=e?i.filter(t=>e.has(t.id)):i;return b(s,this.geometryLookup,this.outline)}apply(t,e={}){const i=t=>!(!t||"object"!=typeof t)&&(("set"!==t.op||!1!==t.patch?.locked||1!==Object.keys(t.patch).length)&&(["set","remove","order","reparent"].includes(t.op)&&"id"in t&&this.isLocked(t.id)||("add"===t.op||"reparent"===t.op)&&!!t.parent&&this.isLocked(t.parent))),s=e.origin??"api";let n=(Array.isArray(t),t);const o=[];if("user"===s&&Array.isArray(t)){const s=t.flatMap((t,e)=>i(t)?[e]:[]);if(s.length&&!e.lenient)return this.lockedResult(s[0]);if(s.length&&e.lenient&&(o.push(...s.map(t=>({index:t,code:"LOCKED",message:"Unlock the selection before editing it."}))),n=t.filter((t,e)=>!s.includes(e)),!n.length))return{ok:!1,created:[],errors:[],warnings:[],skipped:o}}const a=Array.isArray(n)?n.map(t=>{if(!t||"object"!=typeof t)return t;if("add"===t.op&&t.item){let e=t.item;return"text"===e.kind&&e.autoWidth&&"string"==typeof e.text?.value&&e.text.value.length<=f.maxTextLength&&(e={...e,...kt(this.host.ownerDocument,e.text)}),{...t,item:e,...t.page||t.parent?{}:{page:this.pageId}}}if("set"===t.op&&t.patch){const e=this.get(t.id);if("text"===e?.kind&&(t.patch.autoWidth??e.autoWidth)&&(t.patch.text||t.patch.autoWidth)){const i={...e.text,...t.patch.text};if("string"==typeof i.value&&i.value.length<=f.maxTextLength)return{...t,patch:{...t.patch,...kt(this.host.ownerDocument,i)}}}}return t}):n,r=this.model.apply(a,{origin:"api",...e});if(o.length&&Array.isArray(t)){const e=new Set(o.map(t=>t.index)),i=t.map((t,e)=>e).filter(t=>!e.has(t)),s=t=>t?.map(t=>({...t,index:i[t.index]??t.index}));r.errors=s(r.errors)??r.errors,r.warnings=s(r.warnings)??r.warnings,r.skipped=[...o,...s(r.skipped)??[]].sort((t,e)=>t.index-e.index)}if(r.ok&&!e.dryRun&&r.created.length){if(s.startsWith("agent:")){this.render();const t=(e.agentName??this.agentName)?.trim()||void 0;this.stage.present(r.created,t)}"fit"===(e.reveal??(s.startsWith("agent:")?this.agentReveal:"none"))&&this.queueReveal(r.created)}return r}queueReveal(t){this.pendingReveal=[.../* @__PURE__ */new Set([...this.pendingReveal??[],...t])],this.stage.whenPresentationIdle(()=>this.flushReveal())}flushReveal(){const t=this.pendingReveal;this.pendingReveal=void 0,t?.length&&!this.destroyed&&this.revealCreated(t)}revealCreated(t){const e=t.filter(t=>w(this.pageItems()).some(e=>e.id===t));e.length&&(e.every(t=>{const e=this.get(t);return!!e&&this.visible(e)})||this.view.fit(e))}undo(t){return this.cancel(),this.model.undo(t)}redo(){return this.cancel(),this.model.redo()}load(t){this.cancel(),this.pendingReveal=void 0,this.model.load(t),this.document=this.model.toJSON({compact:!1}),this.pageId=this.document.pages[0].id,this.refreshGeometry(),this.select([]),this.render(),this.view.fit()}clear(){this.cancel(),this.pendingReveal=void 0,this.model.clear(),this.document=this.model.toJSON({compact:!1}),this.pageId=this.document.pages[0].id,this.refreshGeometry(),this.select([]),this.render(),this.view.fit()}select(t){const e=[...new Set(t)].filter(t=>!!this.get(t));e.join(",")!==this.selectionSignal.value.join(",")&&(this.selectionSignal.value=e,this.stage.setSelection(e),this.emit("select",e))}setTool(t){this.cancel(),this.toolSignal.value=t,this.updateCursor(),this.emit("tool",t)}setTheme(t){this.themeValue=t,this.stage.setTheme(t)}setPage(t){this.document.pages.some(e=>e.id===t)&&(this.cancel(),this.pendingReveal=void 0,this.pageId=t,this.refreshGeometry(),this.enteredGroup=void 0,this.select([]),this.render(),this.view.fit(),this.emit("page",t))}setGrid(t){this.grid=t,this.stage.root.classList.toggle("ad-no-grid",!t)}on(t,e){const i=this.listeners.get(t)??/* @__PURE__ */new Set;return i.add(e),this.listeners.set(t,i),()=>i.delete(e)}emit(t,e){this.listeners.get(t)?.forEach(t=>t(e))}async export(t,e={}){const i=this.read(e.scope??"page");if("json"===t)return z(i.pages.flatMap(t=>t.items),this.geometryLookup,this.outline),N(i);const s=i.pages.flatMap(t=>t.items).map(t=>this.get(t.id)??t),n=function(t,e,i={}){const s=i.theme??"light",n=M(t),o=new Map(n.map(t=>[t.id,t])),a=W(i.kinds),r=t=>a.get(t.kind)?.outline?.(t),h=/* @__PURE__ */new Set,d=(t,e)=>{for(const i of t)(e||i.hidden)&&h.add(i.id),i.children&&d(i.children,e||!!i.hidden)};for(const x of t.pages)d(x.items,!1);const l=/* @__PURE__ */new Set,c=w(e).filter(t=>!(l.has(t.id)||h.has(t.id)||t.hidden||(l.add(t.id),0))),p=i.bounds??(c.length?b(c,o,r):{x:0,y:0,w:800,h:600}),u=Math.max(0,i.padding??32),m=p.x-u,g=p.y-u-(i.labels?18:0),f=Math.max(1,p.w+2*u),y=Math.max(1,p.h+2*u+(i.labels?18:0)),v=[];for(const[w,b]of c.entries()){let e="";const n=a.get(b.kind),h="connector"===b.kind?x(b,o,r):void 0;if(n?.toSVG){const i=n.toSVG(b,{doc:t,theme:s,color:t=>C(t,s),escape:O});e="string"==typeof i?i:(new XMLSerializer).serializeToString(i)}else if(["rect","ellipse","diamond","note","line","path","connector"].includes(b.kind))e=R(b,s,`export_${w}`,h?.d),(h||"line"===b.kind)&&(e+=F(h?.points??(b.points??[[0,0],[b.w,b.h]]).map(([t,e])=>({x:t,y:e})),b,s));else if("image"===b.kind){const i=b.media?t.media[b.media]:void 0,s=Math.min(b.style?.corner??12,b.w/2,b.h/2),n=`export_clip_${w}`;if(i){const t=b.crop&&b.crop.w>0&&b.crop.h>0?`<svg width="${b.w}" height="${b.h}" viewBox="${b.crop.x} ${b.crop.y} ${b.crop.w} ${b.crop.h}" preserveAspectRatio="none" overflow="hidden"><image width="${i.w}" height="${i.h}" href="${O(i.src)}" preserveAspectRatio="none"/></svg>`:`<image width="${b.w}" height="${b.h}" href="${O(i.src)}" preserveAspectRatio="none"/>`;e=`<defs><clipPath id="${n}"><rect width="${b.w}" height="${b.h}" rx="${s}"/></clipPath></defs><g clip-path="url(#${n})">${t}</g>`}}else"video"===b.kind||"link"===b.kind?e=rt(b,s,t,w):["text","group"].includes(b.kind)||(e=`<rect width="${b.w}" height="${b.h}" rx="8" fill="${C("paper",s)}" stroke="#8F93F9" stroke-dasharray="5 4"/><text x="12" y="24" fill="${C("ink",s)}" font-family="${O(D.sans)}" font-size="14">${O("html"===b.kind?"HTML content":`Unknown kind: ${b.kind}`)}</text>`);if("video"!==b.kind&&"link"!==b.kind&&(e+=nt(b,s,h?.midpoint)),i.labels){const t=h?h.bounds.x:0,i=h?h.bounds.y-22:-22;e+=`<rect x="${t}" y="${i}" width="${6.6*b.id.length+12}" height="17" rx="4" fill="#103639"/><text x="${t+6}" y="${i+12}" fill="#FFFFFF" font-family="monospace" font-size="10">${O(b.id)}</text>`}const d=h?"":`translate(${b.x} ${b.y}) rotate(${b.rotation??0} ${b.w/2} ${b.h/2})`,l=`<g data-ad-id="${O(b.id)}" data-ad-kind="${O(b.kind)}"${d?` transform="${d}"`:""}${void 0!==b.style?.opacity?` opacity="${b.style.opacity}"`:""}><title>${O(b.name??b.text?.value??b.kind)}</title>${e}</g>`;v.push(l)}const k=!1===i.background?"":C("string"==typeof i.background?i.background:"paper",s);return`<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="${f}" height="${y}" viewBox="${m} ${g} ${f} ${y}" role="img" aria-label="${O(t.meta.title)}"><title>${O(t.meta.title)}</title>${k?`<rect x="${m}" y="${g}" width="${f}" height="${y}" fill="${O(k)}"/>`:""}${v.join("")}</svg>`}(this.document,s,{...e,theme:this.stage.resolvedTheme,kinds:[...this.stage.kinds.values()],..."viewport"===e.scope?{bounds:this.stage.lens.viewport(),padding:0}:{}});if("svg"===t)return n;const o="png"===t&&!0===e.labels;return async function(t,e){const i=e.format;if("undefined"==typeof document)throw new Error(`${i.toUpperCase()} export requires a browser. Use SVG export in headless environments.`);let s=e.scale??2;if(!Number.isFinite(s)||s<=0||s>8)throw new Error(`${i.toUpperCase()} scale must be greater than zero and no greater than 8.`);const n="png"===i&&void 0!==e.colors?e.colors:void 0;if(void 0!==n&&(!Number.isInteger(n)||n<2||n>256))throw new Error("PNG colors must be an integer from 2 to 256.");const o=URL.createObjectURL(new Blob([t],{type:"image/svg+xml;charset=utf-8"}));try{const t=new Image;t.decoding="async",await new Promise((e,i)=>{t.onload=()=>e(),t.onerror=()=>i(/* @__PURE__ */new Error("This drawing could not be rasterised. Export SVG instead, or embed external images as data URLs.")),t.src=o});const a=Math.max(1,t.naturalWidth),r=Math.max(1,t.naturalHeight);if(e.maxSide&&Number.isFinite(e.maxSide)&&e.maxSide>0){const t=Math.max(a*s,r*s);t>e.maxSide&&(s*=e.maxSide/t)}const h="png"===i?[1]:[Math.min(1,Math.max(.1,e.quality??.85)),...vt.filter(t=>t<(e.quality??.85))],d=async(e,s,n)=>{const o=Math.max(1,Math.ceil(a*e)),h=Math.max(1,Math.ceil(r*e));if(o>16384||h>16384||o*h>64e6)throw new Error(`${i.toUpperCase()} is too large. Export a smaller selection or reduce the scale.`);const d=document.createElement("canvas");d.width=o,d.height=h;const l=d.getContext("2d",n?{willReadFrequently:!0}:void 0);if(!l)throw new Error(`This browser does not support ${i.toUpperCase()} export.`);if(l.drawImage(t,0,0,o,h),"png"===i&&n){const t=l.getImageData(0,0,o,h),e=ft(t.data,n);try{return await yt(o,h,e.palette,e.indices)}catch{!function(t,e,i){for(let s=0,n=0;s<i.length;s++,n+=4){const o=e[i[s]];t[n]=o.r,t[n+1]=o.g,t[n+2]=o.b,t[n+3]=o.a}}(t.data,e.palette,e.indices),l.putImageData(t,0,0)}}return await new Promise((t,e)=>{try{d.toBlob(s=>s?t(s):e(/* @__PURE__ */new Error(`The browser could not encode this ${i.toUpperCase()}.`)),xt[i],"png"===i?void 0:s)}catch{e(/* @__PURE__ */new Error(`An external image prevents ${i.toUpperCase()} export. Embed images as data URLs or export SVG.`))}})};if(!e.maxBytes)return d(s,h[0],n);let l,c=s;const p=t=>((!l||t.size<l.size)&&(l=t),t.size<=e.maxBytes);for(;c>=.25-1e-9;){if("png"===i){if(void 0===n&&await p(await d(c,1)))return l;if(await p(await d(c,1,n??g.colors)))return l}else for(const e of h)if(await p(await d(c,e)))return l;const t=c/2;if(t<.25-1e-9)break;c=t}return l??d(s,h[0],n)}finally{URL.revokeObjectURL(o)}}(n,{format:t,scale:e.scale??2,maxSide:e.maxSide,maxBytes:e.maxBytes??(o?g.maxBytes:void 0),quality:e.quality,colors:e.colors??(o?g.colors:void 0)})}destroy(){this.destroyed||(this.destroyed=!0,this.pendingReveal=void 0,this.cancel(),cancelAnimationFrame(this.frame),this.observer.disconnect(),this.cleanup.forEach(t=>t()),this.uiCleanup?.(),this.stage.destroy(),this.listeners.clear(),window.__anniedrawing&&(window.__anniedrawing=window.__anniedrawing.filter(t=>t!==this)))}addCleanup(t){this.cleanup.push(t)}focus(){this.stage.root.focus({preventScroll:!0})}add(t,e){const i=e??this.view.center,[s,n]=u(t),o=this.apply([{op:"add",page:this.pageId,item:{kind:t,x:i.x-s/2,y:i.y-n/2,w:s,h:n,style:h(this.defaultStyle),..."note"===t?{style:{...this.defaultStyle,fill:"moss",stroke:"none",corner:12},text:{value:"A little idea",size:"l"}}:{},..."text"===t?{autoWidth:!0,text:{value:"Type something…",size:"l"},style:{fill:"none",stroke:"ink"}}:{}}}],{origin:"user",label:`Add ${t}`});return o.ok&&(this.select(o.created),"text"!==t&&"note"!==t||this.editText(o.created[0])),o}updateSelection(t){if(!1===t.locked&&1===Object.keys(t).length){const e=new Set(this.selection),i=[],s=(t,n=!1)=>{n||=e.has(t.id);let o=!1;for(const e of t.children??[])o=s(e,n)||o;return t.locked&&(n||o)&&i.push(t.id),n||o};return this.document.pages.forEach(t=>t.items.forEach(t=>s(t))),this.apply(i.map(e=>({op:"set",id:e,patch:t})),{origin:"user",label:"Unlock selection"})}return this.apply(this.selection.map(e=>({op:"set",id:e,patch:t})),{origin:"user",label:"Change style"})}deleteSelection(){if(this.selection.some(t=>this.isLocked(t)))return;const t=this.topSelection();this.apply(t.map(t=>({op:"remove",id:t})),{origin:"user",label:"Delete"}),this.select([]),this.focus()}duplicate(t=24){if(this.selection.some(t=>this.isLocked(t)))return this.lockedResult();const e=this.topSelection().map(t=>this.get(t)).filter(Boolean),i=S(e,t),s=this.apply(i.map(t=>({op:"add",item:t,page:this.pageId})),{origin:"user",label:"Duplicate"});return s.ok&&this.select(i.map(t=>t.id)),s}group(){if(this.selection.length<2||this.selection.some(t=>this.isLocked(t)))return;const t=this.topSelection(),e=this.boundsOf(t),i=c();this.apply([{op:"add",page:this.pageId,item:{kind:"group",id:i,...e,children:[]}},...t.map(t=>({op:"reparent",id:t,parent:i}))],{origin:"user",label:"Group"}),this.select([i])}ungroup(){if(this.selection.some(t=>this.isLocked(t)))return;const t=[];for(const e of this.selection){const i=this.get(e);if("group"===i?.kind){for(const e of i.children??[])t.push({op:"reparent",id:e.id,parent:null});t.push({op:"remove",id:e})}}this.apply(t,{origin:"user",label:"Ungroup"}),this.select([])}align(t){if(this.selection.some(t=>this.isLocked(t)))return;const e=this.topSelection().map(t=>this.get(t)).filter(t=>t&&!t.locked&&"connector"!==t.kind),i=t=>I(t,this.geometryLookup,this.outline),s=b(e,this.geometryLookup,this.outline),n=[...e].sort((e,s)=>"horizontal"===t?i(e).x-i(s).x:i(e).y-i(s).y);let o="horizontal"===t?s.x:s.y;const a=e.length>1?(("horizontal"===t?s.w:s.h)-e.reduce((e,s)=>e+("horizontal"===t?i(s).w:i(s).h),0))/(e.length-1):0,r=n.flatMap(e=>{const n=i(e);let r=0,h=0;return"left"===t&&(r=s.x-n.x),"center"===t&&(r=s.x+(s.w-n.w)/2-n.x),"right"===t&&(r=s.x+s.w-n.w-n.x),"top"===t&&(h=s.y-n.y),"middle"===t&&(h=s.y+(s.h-n.h)/2-n.y),"bottom"===t&&(h=s.y+s.h-n.h-n.y),"horizontal"===t&&(r=o-n.x,o+=n.w+a),"vertical"===t&&(h=o-n.y,o+=n.h+a),this.movable([e.id]).map(t=>({op:"set",id:t.id,patch:E(t,r,h)}))});this.apply(r,{origin:"user",label:"Align selection"})}async addImage(t,e){if(this.readonly)return;if(!/^image\/(png|jpeg|gif|webp|avif)$/.test(t.type))throw new Error("Choose a PNG, JPEG, GIF, WebP or AVIF image.");if(t.size>10485760)throw new Error("Images must be under 10 MB.");const i=await new Promise((e,i)=>{const s=new FileReader;s.onload=()=>e(s.result),s.onerror=i,s.readAsDataURL(t)}),s=new Image;s.src=i,await s.decode();const n=Math.min(1,480/s.width,360/s.height),o=s.width*n,a=s.height*n,r=e??this.view.center,h=l(),d=this.apply([{op:"media.set",id:h,media:{src:i,mime:t.type,w:s.width,h:s.height}},{op:"add",page:this.pageId,item:{kind:"image",x:r.x-o/2,y:r.y-a/2,w:o,h:a,media:h,name:t.name}}],{origin:"user",label:"Add image"});d.ok&&this.select(d.created)}setHref(t,e){return import("./urlPaste-DN4JtgeB.js").then(({updateHref:i})=>i(this.pasteHost(),t,e))}pasteHost(){return{pageId:this.pageId,items:this.items,destroyed:this.destroyed,unfurl:this.unfurl,view:this.view,host:this.host,apply:(t,e)=>this.apply(t,e),select:t=>this.select(t),get:t=>this.get(t)}}editText(t){if(this.readonly||this.editor)return;this.render();const e=this.get(t);if(!e||this.isLocked(t))return;const i=this.stage.world.querySelector(`[data-ad-id="${CSS.escape(t)}"]`);if(!i)return;let s=i.querySelector(".ad-text");s||(s=document.createElement("div"),s.className="ad-text",i.append(s)),s.contentEditable="plaintext-only",s.setAttribute("role","textbox"),s.setAttribute("aria-label","Edit text"),s.style.pointerEvents="auto",s.style.display="flex",s.classList.add("ad-editing"),this.editor=s;const n=e.text?.value??"";s.textContent=n,s.focus();const o=document.createRange();o.selectNodeContents(s);const a=window.getSelection();a?.removeAllRanges(),a?.addRange(o);const r=(i=!0)=>{if(this.editor!==s)return;this.editor=void 0,this.finishEditor=void 0;const o=s.innerText;if(s.contentEditable="false",s.classList.remove("ad-editing"),s.removeAttribute("role"),s.removeAttribute("aria-label"),s.removeEventListener("blur",h),s.removeEventListener("keydown",d),i&&o!==n){const i={...this.get(t)?.text,value:o},s="text"===e.kind&&e.autoWidth?kt(this.host.ownerDocument,i):{};this.apply([{op:"set",id:t,patch:{...s,text:{value:o}}}],{origin:"user",label:"Edit text"})}const a=this.get(t);s.textContent=a?.text?.value??n,s.style.display=a?.text?"flex":"none",this.render(),this.focus()};this.finishEditor=r;const h=()=>r(),d=t=>{t.stopPropagation(),"Escape"===t.key&&(t.preventDefault(),r(!1)),"Enter"===t.key&&(t.metaKey||t.ctrlKey)&&(t.preventDefault(),r())};s.addEventListener("blur",h),s.addEventListener("keydown",d)}cancel(){this.clearInteractive(),clearTimeout(this.longPressTimer),this.lastTouchTap=void 0,this.finishEditor?.(!1),this.drag&&(this.drag=void 0,this.drafts.clear(),this.drawPreview=void 0,this.stage.setMarquee(void 0),this.render()),this.pointers.clear(),this.pinch=void 0,this.updateCursor()}schedule(){this.frame||this.destroyed||(this.frame=requestAnimationFrame(()=>{this.frame=0,this.render()}))}render(){if(this.destroyed)return;let t=this.document;this.drawPreview?(this.previewDocument&&this.previewBase===t||(this.previewBase=t,this.previewDocument={...t,pages:t.pages.map(t=>t.id===this.pageId?{...t,items:[...t.items,this.drawPreview]}:t)}),t=this.previewDocument,this.drafts.set(this.drawPreview.id,{...this.drawPreview})):(this.previewDocument=void 0,this.previewBase=void 0),this.stage.render(t,this.pageId,this.drafts),this.stage.setSelection(this.selection)}visible(t){if(this.hiddenGeometry.has(t.id))return!1;const e=this.stage.lens.viewport(),i=I(t,this.geometryLookup,this.outline);return i.x+i.w>=e.x&&i.y+i.h>=e.y&&i.x<=e.x+e.w&&i.y<=e.y+e.h}isUI(t){return t instanceof Element&&!!t.closest('.ad-ui, .ad-dialog, input, textarea, select, button, [contenteditable="plaintext-only"], [data-ad-interactive="true"], a')}point(t){return{x:t.clientX-this.rect.left,y:t.clientY-this.rect.top}}updateCursor(){this.stage.root.style.cursor=function(t,e={}){return e.panning?"grabbing":e.space||e.readonly||"hand"===t?"grab":"text"===t?"text":"select"===t?Z:et}(this.tool,{space:this.space,readonly:this.readonly,panning:"pan"===this.drag?.kind})}topSelection(){const t=new Set(this.selection),e=[],i=(s,n=!1)=>{for(const o of s){const s=t.has(o.id);s&&!n&&e.push(o.id),o.children&&i(o.children,n||s)}};return i(this.pageItems()),e}pageItems(){return this.document.pages.find(t=>t.id===this.pageId)?.items??[]}movable(t){if(t.some(t=>this.isLocked(t)))return[];const e=/* @__PURE__ */new Map;for(const i of t){const t=this.get(i);if(t&&!t.locked)for(const i of[t,...w(t.children??[])])e.set(i.id,i)}return[...e.values()]}outline=t=>this.stage.kinds.get(t.kind)?.outline?.(t);refreshGeometry(){const t=this.pageItems();this.geometryLookup=new Map(w(t).map(t=>[t.id,t])),this.lockedGeometry=K(this.document.pages.flatMap(t=>t.items)),this.hiddenGeometry.clear();const e=(t,i=!1)=>{for(const s of t){const t=i||!!s.hidden;t&&this.hiddenGeometry.add(s.id),s.children&&e(s.children,t)}};e(t),this.spatial.set(t,this.outline)}hit(t,e=!1){const i=this.spatial.pick(t,{includeLocked:!0,tolerance:6/this.view.zoom,enteredGroup:this.enteredGroup,outline:this.outline,ignore:t=>this.stage.isPending(t.id)});if(i&&i.id!==this.enteredGroup&&(e||!this.isLocked(i.id)))return i}zoomAt(t,e){t=Math.max(.05,Math.min(8,t));const i=this.stage.lens.toPage(e);this.stage.lens.set({zoom:t,x:e.x-i.x*t,y:e.y-i.y*t})}pointerDown=t=>{if(this.isUI(t.target)||t.button>1)return;this.clearInteractive(t.target),clearTimeout(this.longPressTimer),"touch"!==t.pointerType&&(this.lastTouchTap=void 0);const e=this.point(t);if(this.pointers.set(t.pointerId,e),2===this.pointers.size){this.lastTouchTap=void 0,this.drag=void 0,this.updateCursor(),this.drafts.clear(),this.drawPreview=void 0;const[t,e]=[...this.pointers.values()],i={x:(t.x+e.x)/2,y:(t.y+e.y)/2};return void(this.pinch={distance:Math.hypot(t.x-e.x,t.y-e.y),zoom:this.view.zoom,center:i,anchor:this.stage.lens.toPage(i)})}t.preventDefault();try{this.stage.root.setPointerCapture(t.pointerId)}catch{}this.focus();const i=this.stage.lens.toPage(e),s={...this.stage.lens.state},n=t.target.closest("[data-ad-handle]")?.dataset.adHandle;if(this.space||"hand"===this.tool||1===t.button||this.readonly)return this.drag={kind:"pan",pointer:t.pointerId,start:i,screen:e,last:e,original:[],ids:[],camera:s,moved:!1},void this.updateCursor();if(n&&this.selection.length){if(this.selection.some(t=>this.isLocked(t)))return;return void(this.drag={kind:"rotate"===n?"rotate":"resize",pointer:t.pointerId,start:i,screen:e,last:i,original:this.movable(this.topSelection()),ids:this.topSelection(),camera:s,handle:n,moved:!1})}if("select"===this.tool){const n=t.target.closest("[data-ad-id]")?.dataset.adId,o=n&&!this.stage.isPending(n)?this.get(n):void 0,a=this.hit(i,!0)??(o&&!this.outline(o)?o:void 0);if(a){t.shiftKey?this.select(this.selection.includes(a.id)?this.selection.filter(t=>t!==a.id):[...this.selection,a.id]):this.selection.includes(a.id)||this.select([a.id]);const n=this.topSelection();this.drag={kind:"move",pointer:t.pointerId,start:i,screen:e,last:i,original:this.movable(n),ids:n,camera:s,moved:!1,alt:t.altKey}}else t.shiftKey||this.select([]),this.drag={kind:"marquee",pointer:t.pointerId,start:i,screen:e,last:i,original:[],ids:this.selection,camera:s,moved:!1};if("touch"===t.pointerType){const i=this.drag;this.longPressTimer=setTimeout(()=>{if(this.drag!==i||i.moved||1!==this.pointers.size)return;this.cancel();const s=t.target.closest("[data-ad-id]")?.dataset.adId;this.openContext(e,s)},500)}return}if("eraser"===this.tool){const n=this.hit(i);return this.drag={kind:"erase",pointer:t.pointerId,start:i,screen:e,last:i,original:[],ids:n?[n.id]:[],camera:s,moved:!1},n&&this.drafts.set(n.id,{hidden:!0}),void this.schedule()}const o=this.tool,a=this.hit(i),r={id:c(),kind:o,x:i.x,y:i.y,w:0,h:0,style:h(this.defaultStyle),..."path"===o?{points:[[0,0,t.pressure||.5]]}:{},..."connector"===o?{from:a?{item:a.id,side:"auto"}:i,to:i,route:"elbow",heads:{end:"arrow"}}:{},..."note"===o?{style:{...this.defaultStyle,fill:"moss",stroke:"none",corner:12},text:{value:"",size:"l"}}:{},..."text"===o?{autoWidth:!0,text:{value:"",size:"l"}}:{}};this.drag={kind:"draw",pointer:t.pointerId,start:i,screen:e,last:i,original:[],ids:[],camera:s,item:r,points:"path"===o?[[0,0,t.pressure||.5]]:void 0,moved:!1},this.drawPreview=r,this.select([]),this.schedule()};pointerMove=t=>{const e=this.point(t);if(this.pointers.has(t.pointerId)&&this.pointers.set(t.pointerId,e),this.pinch&&this.pointers.size>=2){t.preventDefault();const[e,i]=[...this.pointers.values()],s={x:(e.x+i.x)/2,y:(e.y+i.y)/2},n=Math.max(.05,Math.min(8,this.pinch.zoom*Math.hypot(e.x-i.x,e.y-i.y)/Math.max(1,this.pinch.distance)));return void this.stage.lens.set({zoom:n,x:s.x-this.pinch.anchor.x*n,y:s.y-this.pinch.anchor.y*n})}const i=this.drag;if(!i||i.pointer!==t.pointerId)return;const s=this.stage.lens.toPage(e),n=Math.hypot(e.x-i.screen.x,e.y-i.screen.y);if(i.moved||!(n<("touch"===t.pointerType?8:4)))if(clearTimeout(this.longPressTimer),this.lastTouchTap=void 0,i.moved=!0,i.last=s,"pan"!==i.kind){if("move"===i.kind){let e=s.x-i.start.x,n=s.y-i.start.y;t.shiftKey&&(Math.abs(e)>Math.abs(n)?n=0:e=0);for(const t of i.original)this.drafts.set(t.id,E(t,e,n));return void this.schedule()}if("resize"===i.kind){if(i.handle?.startsWith("custom:")){const e=1===i.ids.length?i.original.find(t=>t.id===i.ids[0]):void 0,n=e?this.stage.kinds.get(e.kind)?.dragHandle:void 0;if(e&&n){const a=v(s,{x:e.x+e.w/2,y:e.y+e.h/2},-(e.rotation??0));try{this.drafts.set(e.id,n(h(e),i.handle.slice(7),{x:a.x-e.x,y:a.y-e.y},{shift:t.shiftKey,alt:t.altKey})),this.schedule()}catch(o){this.cancel(),this.host.dispatchEvent(new CustomEvent("ad-error",{detail:o instanceof Error?o.message:String(o)}))}}return}const e=i.original.filter(t=>i.ids.includes(t.id)),n=1===e.length&&!["connector","line","path","group"].includes(e[0].kind),a=n?e[0]:b(e,this.geometryLookup,this.outline),r=i.handle??"se",d=n?e[0].rotation??0:0,l={x:a.x+a.w/2,y:a.y+a.h/2},c=v(i.start,l,-d),p=v(s,l,-d),u=p.x-c.x,m=p.y-c.y,g=r.includes("e")?1:r.includes("w")?-1:0,f=r.includes("s")?1:r.includes("n")?-1:0;let y=a.w+g*u*(t.altKey?2:1),x=a.h+f*m*(t.altKey?2:1);if(t.shiftKey){const t=y/Math.max(1,a.w),e=x/Math.max(1,a.h),i=Math.max(12/Math.max(1,a.w),12/Math.max(1,a.h),g?f?Math.abs(t-1)>=Math.abs(e-1)?t:e:t:e);y=a.w*i,x=a.h*i}else y=Math.max(12,y),x=Math.max(12,x);const w={x:l.x+(t.altKey?0:g*(y-a.w)/2),y:l.y+(t.altKey?0:f*(x-a.h)/2)},k=w.x-y/2,$=w.y-x/2,M=y/Math.max(1,a.w),S=x/Math.max(1,a.h),z=t=>{const e=v(t,l,-d);return v({x:k+(e.x-a.x)*M,y:$+(e.y-a.y)*S},l,d)};for(const t of i.original){const e=z({x:t.x+t.w/2,y:t.y+t.h/2}),i=Math.max(1,t.w*M),s=Math.max(1,t.h*S),n={x:e.x-i/2,y:e.y-s/2,w:i,h:s};if(t.points&&(n.points=t.points.map(t=>t.length>2?[t[0]*M,t[1]*S,t[2]]:[t[0]*M,t[1]*S])),"connector"===t.kind){for(const e of["from","to"]){const i=t[e];i&&!("item"in i)&&(n[e]=z(i))}t.waypoints&&(n.waypoints=t.waypoints.map(([t,e])=>{const i=z({x:t,y:e});return[i.x,i.y]}))}this.drafts.set(t.id,n)}return void this.schedule()}if("rotate"===i.kind){const t=i.original.filter(t=>i.ids.includes(t.id)),e=b(t,this.geometryLookup,this.outline),n={x:e.x+e.w/2,y:e.y+e.h/2},o=180*(Math.atan2(s.y-n.y,s.x-n.x)-Math.atan2(i.start.y-n.y,i.start.x-n.x))/Math.PI;for(const s of i.original){const t=v({x:s.x+s.w/2,y:s.y+s.h/2},n,o),e={x:t.x-s.w/2,y:t.y-s.h/2,rotation:(s.rotation??0)+o};if("connector"===s.kind){e.rotation=0;for(const t of["from","to"]){const i=s[t];i&&!("item"in i)&&(e[t]=v(i,n,o))}s.waypoints&&(e.waypoints=s.waypoints.map(([t,e])=>{const i=v({x:t,y:e},n,o);return[i.x,i.y]}))}this.drafts.set(s.id,e)}return void this.schedule()}if("marquee"!==i.kind){if("erase"===i.kind){const t=this.hit(s);return void(t&&!i.ids.includes(t.id)&&(i.ids.push(t.id),this.drafts.set(t.id,{hidden:!0}),this.schedule()))}if(i.item){const e=i.item;if("path"===e.kind){const s=t.getCoalescedEvents?.(),n=s?.length?s:[t];for(const t of n){const e=this.stage.lens.toPage(this.point(t));i.points.push([e.x-i.start.x,e.y-i.start.y,t.pressure||.5])}e.points=i.points,e.w=Math.max(1,...i.points.map(t=>t[0])),e.h=Math.max(1,...i.points.map(t=>t[1]))}else if("connector"===e.kind){const t=this.hit(s);e.to=t?{item:t.id,side:"auto"}:s}else{let n=Math.abs(s.x-i.start.x),o=Math.abs(s.y-i.start.y);t.shiftKey&&(n=o=Math.max(n,o)),e.x=s.x<i.start.x?i.start.x-n:i.start.x,e.y=s.y<i.start.y?i.start.y-o:i.start.y,e.w=n,e.h=o,"line"===e.kind&&(e.points=[[i.start.x-e.x,i.start.y-e.y],[s.x-e.x,s.y-e.y]])}this.drawPreview=e,this.schedule()}}else this.stage.setMarquee({x:Math.min(s.x,i.start.x),y:Math.min(s.y,i.start.y),w:Math.abs(s.x-i.start.x),h:Math.abs(s.y-i.start.y)})}else this.stage.lens.set({x:i.camera.x+e.x-i.screen.x,y:i.camera.y+e.y-i.screen.y})};pointerUp=t=>{if(clearTimeout(this.longPressTimer),this.pointers.delete(t.pointerId),this.pinch)return void(this.pointers.size<2&&(this.pinch=void 0));const e=this.drag;if(!e||e.pointer!==t.pointerId)return;this.drag=void 0,this.updateCursor();const i="touch"===t.pointerType&&!e.moved&&["move","marquee"].includes(e.kind),s=[];if(("move"===e.kind||"resize"===e.kind||"rotate"===e.kind)&&e.moved&&e.original.length)if("move"===e.kind&&e.alt){const t=e.ids.map(t=>e.original.find(e=>e.id===t)).filter(Boolean).map(t=>this.withDrafts(t)),i=S(t,0);s.push(...i.map(t=>({op:"add",item:t,page:this.pageId}))),this.selectionSignal.value=i.map(t=>t.id)}else for(const[n,o]of this.drafts)s.push({op:"set",id:n,patch:o});if("marquee"===e.kind&&e.moved){const t=e.last,i={x:Math.min(t.x,e.start.x),y:Math.min(t.y,e.start.y),w:Math.abs(t.x-e.start.x),h:Math.abs(t.y-e.start.y)};this.select([...e.ids,...this.spatial.enclosed(i,{enteredGroup:this.enteredGroup,ignore:t=>this.stage.isPending(t.id)}).map(t=>t.id)])}if("erase"===e.kind&&s.push(...e.ids.map(t=>({op:"remove",id:t}))),"draw"===e.kind&&e.item){const t=e.item;if(!e.moved){const[e,i]=u(t.kind);t.w="path"===t.kind?1:e,t.h="path"===t.kind?1:i,"connector"===t.kind&&(t.to={x:t.x+160,y:t.y}),"line"===t.kind&&(t.points=[[0,0],[e,0]]),"path"===t.kind&&(t.points=[[0,0,.5],[.1,.1,.5]])}if("path"===t.kind&&t.points?.length){const e=Math.min(...t.points.map(t=>t[0])),i=Math.min(...t.points.map(t=>t[1])),s=Math.max(...t.points.map(t=>t[0])),n=Math.max(...t.points.map(t=>t[1]));t.x+=e,t.y+=i,t.w=Math.max(1,s-e),t.h=Math.max(1,n-i),t.points=y(t.points.map(t=>[t[0]-e,t[1]-i,t[2]]),.5/this.view.zoom)}"note"!==t.kind||t.text?.value||(t.text={value:"A little idea",size:"l"}),"text"!==t.kind||t.text?.value||(t.text={value:"Type something…",size:"l"}),s.push({op:"add",item:t,page:this.pageId})}if(this.drafts.clear(),this.drawPreview=void 0,this.stage.setMarquee(void 0),s.length){const t=this.apply(s,{origin:"user",label:"draw"===e.kind?`Draw ${e.item.kind}`:"move"===e.kind?"Move":"resize"===e.kind?"Resize":"rotate"===e.kind?"Rotate":"Erase"});t.ok&&t.created.length&&this.select(e.alt?t.created.filter(t=>!this.items.some(e=>w(e.children??[]).some(e=>e.id===t))):[t.created[0]]),t.ok||this.host.dispatchEvent(new CustomEvent("ad-error",{detail:t.errors[0]?.message}))}if(this.render(),"draw"===e.kind&&e.item){const t=e.item.kind;"path"!==t&&this.setTool("select"),"text"!==t&&"note"!==t||this.editText(e.item.id)}if(this.emit("select",this.selection),i){const e=this.point(t),i=Date.now(),s=this.lastTouchTap;this.lastTouchTap={at:i,screen:e},s&&i-s.at<350&&Math.hypot(e.x-s.screen.x,e.y-s.screen.y)<24&&(this.lastTouchTap=void 0,this.touchDoubleAt=i,this.activateAt(e))}};pointerCancel=()=>this.cancel();wheel=t=>{this.isUI(t.target)||(t.preventDefault(),t.ctrlKey||t.metaKey?this.zoomAt(this.view.zoom*Math.exp(.008*-t.deltaY),this.point(t)):this.stage.lens.set({x:this.stage.lens.state.x-t.deltaX,y:this.stage.lens.state.y-t.deltaY}))};doubleClick=t=>{if(this.isUI(t.target)||Date.now()-this.touchDoubleAt<500)return;const e=(t.target instanceof Element?t.target:void 0)?.closest("[data-ad-id]")?.dataset.adId;this.activateAt(this.point(t),e)};openContext(t,e){const i=this.spatial.pick(this.stage.lens.toPage(t),{tolerance:6/this.view.zoom,includeLocked:!0,enteredGroup:this.enteredGroup,outline:this.outline,ignore:t=>this.stage.isPending(t.id)})??(e&&!this.stage.isPending(e)?this.get(e):void 0);i&&(this.setTool("select"),this.select([i.id])),this.host.dispatchEvent(new CustomEvent("ad-context",{detail:{...t,id:i?.id}}))}activateAt(t,e){const i=e?this.get(e):void 0,s=(!i||"html"!==i.kind&&"video"!==i.kind?void 0:i)??this.hit(this.stage.lens.toPage(t),!0)??i;if(!s||!this.isLocked(s.id))return"group"===s?.kind?(this.enteredGroup=s.id,void this.select([])):void("html"!==s?.kind&&"video"!==s?.kind?s&&!["image","path","line","link"].includes(s.kind)?this.editText(s.id):s||this.readonly||this.add("text",this.stage.lens.toPage(t)):this.activateEmbedded(s));this.select([s.id])}activateEmbedded(t){const e=this.stage.world.querySelector(`[data-ad-id="${CSS.escape(t.id)}"]`);if(!e)return;if(this.clearInteractive(),e.dataset.adInteractive="true","html"!==t.kind)return;const i=e.querySelector(".ad-html-content");if(!i)return;i.tabIndex=0,i.focus();const s=t=>{t.relatedTarget instanceof Node&&i.contains(t.relatedTarget)||(delete e.dataset.adInteractive,i.tabIndex=-1,i.removeEventListener("focusout",s))};i.addEventListener("focusout",s)}clearInteractive(t){for(const e of this.stage.world.querySelectorAll("[data-ad-interactive]"))t instanceof Node&&e.contains(t)||delete e.dataset.adInteractive}keyDown=t=>{if(this.isUI(t.target))return;const e=t.metaKey||t.ctrlKey,i=t.key.toLowerCase();if("contextmenu"===i||"f10"===i&&t.shiftKey){t.preventDefault();const e=1===this.selection.length?this.get(this.selection[0]):void 0;if(e){const t=I(e,this.geometryLookup,this.outline),i=this.stage.lens.toScreen({x:t.x+t.w/2,y:t.y+t.h/2});this.host.dispatchEvent(new CustomEvent("ad-context",{detail:{...i,id:e.id}}))}return}if("Space"===t.code)return t.preventDefault(),this.space=!0,void this.updateCursor();if("escape"===i)return this.cancel(),this.enteredGroup=void 0,this.select([]),void this.setTool("select");if(e&&"a"===i)return t.preventDefault(),void this.select(this.items.filter(t=>!t.hidden&&!t.locked&&!this.stage.isPending(t.id)).map(t=>t.id));if("1"!==i||e)if("2"!==i||e)if("+"!==i&&"="!==i)if("-"!==i){if(!this.readonly){if(e&&"z"===i)return t.preventDefault(),void(t.shiftKey?this.redo():this.undo());if(e&&"y"===i)return t.preventDefault(),void this.redo();if(e&&"d"===i)return t.preventDefault(),void this.duplicate();if(e&&"g"===i)return t.preventDefault(),void(t.shiftKey?this.ungroup():this.group());if("delete"===i||"backspace"===i)return t.preventDefault(),void this.deleteSelection();if("enter"===i&&1===this.selection.length){t.preventDefault();const e=this.get(this.selection[0]);return void("html"===e?.kind||"video"===e?.kind?this.activateEmbedded(e):e&&!["image","path","line","link"].includes(e.kind)&&this.editText(e.id))}if("["===i||"]"===i)return t.preventDefault(),void this.apply(this.selection.map(e=>({op:"order",id:e,to:"]"===i?t.shiftKey?"front":"forward":t.shiftKey?"back":"backward"})),{origin:"user",label:"Reorder"});if(i.startsWith("arrow")){t.preventDefault();const e=t.shiftKey?10:1,s="arrowleft"===i?-e:"arrowright"===i?e:0,n="arrowup"===i?-e:"arrowdown"===i?e:0;return void this.apply(this.movable(this.topSelection()).map(t=>({op:"set",id:t.id,patch:E(t,s,n)})),{origin:"user",label:"Nudge"})}!e&&bt[i]&&(t.preventDefault(),this.setTool(bt[i]))}}else this.view.zoom/=1.2;else this.view.zoom*=1.2;else this.view.fit();else this.view.zoom=1};withDrafts(t){const e=k(t,this.drafts.get(t.id));return e.children?{...e,children:e.children.map(t=>this.withDrafts(t))}:e}copyEvent=t=>{if(this.isUI(t.target)||!this.selection.length)return;t.preventDefault(),this.clipboard=this.topSelection().map(t=>this.get(t)).filter(Boolean);const e={};for(const s of w(this.clipboard))s.media&&this.document.media[s.media]&&(e[s.media]=h(this.document.media[s.media]));z(this.clipboard,this.geometryLookup,this.outline);const i=JSON.stringify({format:"anniedrawing-clipboard",items:this.clipboard,media:e});t.clipboardData?.setData(q,i),t.clipboardData?.setData("text/plain",i)};cutEvent=t=>{this.readonly||this.isUI(t.target)||(this.copyEvent(t),this.deleteSelection())};pasteEvent=t=>{if(this.readonly||this.isUI(t.target))return;const e=[...t.clipboardData?.files??[]];if(e.length)return t.preventDefault(),void e.forEach(t=>{this.addImage(t).catch(t=>this.host.dispatchEvent(new CustomEvent("ad-error",{detail:String(t)})))});t.clipboardData&&(t.preventDefault(),this.pasteFrom(t.clipboardData))};pasteFrom(t,e){const i=t?.getData("application/vnd.anniedrawing+json")||s(t)||t?.getData("text/html")||"";if(i)try{const t=JSON.parse(i);if(!t||"object"!=typeof t||!Array.isArray(t.items))throw new Error("not clipboard json");const e=S(t.items,24),s=new Map(Object.keys(t.media??{}).map(t=>[t,l()])),n=Object.entries(t.media??{}).map(([t,e])=>({op:"media.set",id:s.get(t),media:e}));for(const i of w(e))i.media&&s.has(i.media)&&(i.media=s.get(i.media));n.push(...e.map(t=>({op:"add",item:t,page:this.pageId})));const o=this.apply(n,{origin:"user",label:"Paste"});o.ok?this.select(e.map(t=>t.id)):this.host.dispatchEvent(new CustomEvent("ad-error",{detail:o.errors[0]?.message}))}catch{import("./urlPaste-DN4JtgeB.js").then(({pastePlain:t})=>t(this.pasteHost(),i,e))}}drop=t=>{if(this.readonly)return;t.preventDefault();const e=this.stage.lens.toPage(this.point(t)),i=[...t.dataTransfer?.files??[]];if(i.length)for(const s of i)(async()=>{try{s.name.endsWith(".annie")||"application/json"===s.type?this.load(JSON.parse(await s.text())):await this.addImage(s,e)}catch(t){this.host.dispatchEvent(new CustomEvent("ad-error",{detail:String(t)}))}})();else t.dataTransfer&&this.pasteFrom(t.dataTransfer,e)}};function Mt(t,e){return new $t(t,e)}export{J as i,Mt as n,H as r,$t as t};
2
- //# sourceMappingURL=board-DV5lzxNR.js.map