@hypen-space/web 0.5.2 → 0.5.3

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 (104) hide show
  1. package/dist/canvas/accessibility.d.ts +118 -11
  2. package/dist/canvas/accessibility.js +470 -108
  3. package/dist/canvas/accessibility.js.map +1 -1
  4. package/dist/canvas/dispatch.d.ts +24 -0
  5. package/dist/canvas/dispatch.js +62 -0
  6. package/dist/canvas/dispatch.js.map +1 -0
  7. package/dist/canvas/editing.d.ts +178 -0
  8. package/dist/canvas/editing.js +590 -0
  9. package/dist/canvas/editing.js.map +1 -0
  10. package/dist/canvas/events.d.ts +28 -23
  11. package/dist/canvas/events.js +76 -128
  12. package/dist/canvas/events.js.map +1 -1
  13. package/dist/canvas/focus.d.ts +78 -0
  14. package/dist/canvas/focus.js +182 -0
  15. package/dist/canvas/focus.js.map +1 -0
  16. package/dist/canvas/index.d.ts +3 -1
  17. package/dist/canvas/index.js +3 -1
  18. package/dist/canvas/index.js.map +1 -1
  19. package/dist/canvas/paint.d.ts +16 -3
  20. package/dist/canvas/paint.js +283 -41
  21. package/dist/canvas/paint.js.map +1 -1
  22. package/dist/canvas/renderer.d.ts +20 -1
  23. package/dist/canvas/renderer.js +181 -50
  24. package/dist/canvas/renderer.js.map +1 -1
  25. package/dist/canvas/selection.js +31 -177
  26. package/dist/canvas/selection.js.map +1 -1
  27. package/dist/canvas/text-geometry.d.ts +72 -0
  28. package/dist/canvas/text-geometry.js +244 -0
  29. package/dist/canvas/text-geometry.js.map +1 -0
  30. package/dist/canvas/text.js +42 -9
  31. package/dist/canvas/text.js.map +1 -1
  32. package/dist/canvas/types.d.ts +7 -1
  33. package/dist/canvas/variants.d.ts +4 -1
  34. package/dist/canvas/variants.js +22 -3
  35. package/dist/canvas/variants.js.map +1 -1
  36. package/dist/dom/a11y-styles.d.ts +20 -0
  37. package/dist/dom/a11y-styles.js +61 -0
  38. package/dist/dom/a11y-styles.js.map +1 -0
  39. package/dist/dom/applicators/aria.d.ts +19 -0
  40. package/dist/dom/applicators/aria.js +36 -0
  41. package/dist/dom/applicators/aria.js.map +1 -0
  42. package/dist/dom/applicators/events.d.ts +7 -0
  43. package/dist/dom/applicators/events.js +35 -8
  44. package/dist/dom/applicators/events.js.map +1 -1
  45. package/dist/dom/applicators/index.js +4 -0
  46. package/dist/dom/applicators/index.js.map +1 -1
  47. package/dist/dom/components/hypenapp.d.ts +25 -1
  48. package/dist/dom/components/hypenapp.js +213 -245
  49. package/dist/dom/components/hypenapp.js.map +1 -1
  50. package/dist/dom/components/index.js +7 -0
  51. package/dist/dom/components/index.js.map +1 -1
  52. package/dist/dom/components/spinner.js +24 -10
  53. package/dist/dom/components/spinner.js.map +1 -1
  54. package/dist/dom/components/tabs.d.ts +27 -0
  55. package/dist/dom/components/tabs.js +69 -0
  56. package/dist/dom/components/tabs.js.map +1 -0
  57. package/dist/dom/components/visuallyhidden.d.ts +9 -0
  58. package/dist/dom/components/visuallyhidden.js +26 -0
  59. package/dist/dom/components/visuallyhidden.js.map +1 -0
  60. package/dist/dom/operability.d.ts +100 -0
  61. package/dist/dom/operability.js +298 -0
  62. package/dist/dom/operability.js.map +1 -0
  63. package/dist/dom/renderer.d.ts +98 -5
  64. package/dist/dom/renderer.js +398 -63
  65. package/dist/dom/renderer.js.map +1 -1
  66. package/dist/dom/route-focus.d.ts +42 -0
  67. package/dist/dom/route-focus.js +88 -0
  68. package/dist/dom/route-focus.js.map +1 -0
  69. package/dist/dom/semantics.d.ts +35 -0
  70. package/dist/dom/semantics.js +184 -0
  71. package/dist/dom/semantics.js.map +1 -0
  72. package/package.json +2 -2
  73. package/src/canvas/QUICKSTART.md +4 -4
  74. package/src/canvas/README.md +55 -29
  75. package/src/canvas/accessibility.ts +507 -115
  76. package/src/canvas/dispatch.ts +78 -0
  77. package/src/canvas/editing.ts +697 -0
  78. package/src/canvas/events.ts +89 -142
  79. package/src/canvas/focus.ts +216 -0
  80. package/src/canvas/index.ts +8 -1
  81. package/src/canvas/paint.ts +339 -42
  82. package/src/canvas/renderer.ts +218 -70
  83. package/src/canvas/selection.ts +52 -210
  84. package/src/canvas/text-geometry.ts +311 -0
  85. package/src/canvas/text.ts +43 -9
  86. package/src/canvas/types.ts +14 -1
  87. package/src/canvas/variants.ts +24 -5
  88. package/src/dom/a11y-styles.ts +65 -0
  89. package/src/dom/applicators/aria.ts +41 -0
  90. package/src/dom/applicators/events.ts +38 -7
  91. package/src/dom/applicators/index.ts +5 -0
  92. package/src/dom/components/hypenapp.ts +244 -272
  93. package/src/dom/components/index.ts +7 -0
  94. package/src/dom/components/spinner.ts +31 -13
  95. package/src/dom/components/tabs.ts +76 -0
  96. package/src/dom/components/visuallyhidden.ts +30 -0
  97. package/src/dom/operability.ts +312 -0
  98. package/src/dom/renderer.ts +455 -63
  99. package/src/dom/route-focus.ts +98 -0
  100. package/src/dom/semantics.ts +199 -0
  101. package/dist/canvas/input.d.ts +0 -76
  102. package/dist/canvas/input.js +0 -207
  103. package/dist/canvas/input.js.map +0 -1
  104. package/src/canvas/input.ts +0 -251
@@ -3,27 +3,130 @@
3
3
  *
4
4
  * Maintain shadow DOM for screen readers
5
5
  */
6
+ import type { Semantics } from "@hypen-space/core/types";
6
7
  import type { VirtualNode } from "./types.js";
7
8
  /**
8
- * Accessibility Manager
9
+ * Apply engine-derived accessibility semantics to a shadow-tree element.
10
+ *
11
+ * Unlike the DOM renderer, the canvas paints pixels — the accessible name is
12
+ * *not* otherwise exposed — so the derived name is applied directly as
13
+ * `aria-label` (whether derived or explicit). Roles are set only on generic
14
+ * hosts that don't convey them natively. `hidden` is handled by the caller
15
+ * (the node is omitted from the shadow tree entirely).
16
+ *
17
+ * Called at shadow-node create and again on every reactive `setSemantics`
18
+ * re-apply. Idempotent and clearing: attributes set on a previous pass that
19
+ * the new block no longer produces are removed.
20
+ */
21
+ export declare function applyShadowSemantics(element: HTMLElement, semantics?: Semantics): void;
22
+ /**
23
+ * Accessibility Mirror — positioned transparent semantics overlay
24
+ *
25
+ * A live DOM mirror of the virtual tree, rendered INVISIBLY over the canvas
26
+ * with every element absolutely positioned at its painted bounds (the
27
+ * Flutter-web / Google-Docs approach). Canvas *fallback content* was tried
28
+ * first and rejected on evidence: Chromium exposes fallback elements to the
29
+ * accessibility tree (names, roles, focus all work) but gives them ZERO
30
+ * geometry — and screen-reader browse modes (VoiceOver cursor, rotor, touch
31
+ * exploration) are geometry-driven, so they skip boundless elements. A
32
+ * rendered-but-transparent overlay gets real boxes, which makes browse mode
33
+ * work and puts native focus rings exactly over the painted controls.
34
+ *
35
+ * Real DOM focus on mirror elements is the single source of truth for
36
+ * `node.focused`; the overlay is `pointer-events: none` throughout so the
37
+ * canvas keeps all pointer interaction.
38
+ *
39
+ * The mirror is synced **incrementally** from the same patch stream that
40
+ * drives the canvas (`create/insert/move/remove/detach/attach/...`), so
41
+ * mirror elements keep their identity across re-renders — a screen reader's
42
+ * virtual cursor or a keyboard user's focus survives reactive updates
43
+ * instead of being destroyed by a rebuild. Element positions are refreshed
44
+ * after each canvas render via {@link syncPositions}.
9
45
  */
10
46
  export declare class AccessibilityLayer {
11
- private shadowRoot;
47
+ private mirrorRoot;
12
48
  private nodeMap;
13
49
  private enabled;
14
- constructor(container: HTMLElement | null, enabled?: boolean);
50
+ /** Whether the environment can host a mirror at all. */
51
+ private supported;
52
+ private canvas;
53
+ /**
54
+ * Last box written to each mirror element, so the per-frame position sync
55
+ * only touches elements whose geometry actually changed — style writes on
56
+ * n absolutely-positioned elements per frame are what they cost.
57
+ */
58
+ private lastSyncedBounds;
59
+ private lastRootRect;
60
+ private boundReposition;
61
+ constructor(canvas: HTMLElement | null, enabled?: boolean);
62
+ private mount;
63
+ private unmount;
64
+ /** Pin the overlay root to the canvas's page rect. */
65
+ private repositionRoot;
66
+ /**
67
+ * Mirror a `create` patch: build the element (detached — a subsequent
68
+ * `insert` places it). Elements mirror the virtual tree 1:1; visibility
69
+ * and decorative hiding are expressed with `display:none` (which removes
70
+ * the subtree from the AT tree) instead of omission, so sibling order
71
+ * always matches the virtual tree and `beforeId` mapping stays exact.
72
+ *
73
+ * The mirror's accessibility metadata (role, name, busy, hidden) comes
74
+ * from the engine-derived {@link Semantics} block — the single source of
75
+ * truth shared with every other renderer — not from ad-hoc prop sniffing.
76
+ * Form *values* (input value/placeholder) still come from props, as those
77
+ * aren't semantics.
78
+ */
79
+ createNode(node: VirtualNode): void;
80
+ /**
81
+ * Mirror an `insert` or `attach` patch. Re-inserting an element that is
82
+ * already in the tree moves it (native `insertBefore` semantics), so
83
+ * `move` routes here too. An `attach` reinserts the exact element kept
84
+ * alive by {@link detachNode} — AT identity survives router navigation.
85
+ */
86
+ insertNode(parentId: string, id: string, beforeId?: string): void;
87
+ /**
88
+ * Mirror a `remove` patch: drop the element and purge the subtree's
89
+ * id mappings.
90
+ */
91
+ removeNode(node: VirtualNode): void;
92
+ private purge;
93
+ /**
94
+ * Mirror a `detach` patch: unlink the element but keep the subtree and
95
+ * all id mappings alive so a later `attach` reinserts the same elements
96
+ * (router subtree cache parity).
97
+ */
98
+ detachNode(id: string): void;
99
+ /**
100
+ * Full rebuild from a virtual tree. Only used when re-enabling the mirror
101
+ * (`setEnabled(true)`) and by `clear()` — steady-state sync is incremental.
102
+ */
103
+ rebuild(root: VirtualNode | null): void;
104
+ private mountSubtree;
105
+ /**
106
+ * `display:none` removes the subtree from the accessibility tree — used
107
+ * both for `visible: false` and for decorative (`semantics.hidden`) nodes.
108
+ */
109
+ private syncVisibility;
15
110
  /**
16
- * Sync shadow DOM with virtual tree
111
+ * Write each mirror element's box to its node's painted (scroll-aware)
112
+ * bounds — called by the renderer after every canvas render, so AT
113
+ * geometry follows layout changes and container scrolling. Positions are
114
+ * parent-relative (every mirror element is absolutely positioned).
17
115
  */
18
- syncTree(root: VirtualNode): void;
116
+ syncPositions(root: VirtualNode | null): void;
19
117
  /**
20
- * Create shadow DOM element for virtual node
118
+ * `scrollX`/`scrollY` accumulate the ancestors' scroll offsets down the
119
+ * recursion (the same subtraction `getScrollAwareBounds` derives by
120
+ * walking up), keeping the pass O(n) instead of O(n·depth). Writes are
121
+ * skipped when the element's box is unchanged since the last sync.
21
122
  */
22
- private createShadowNode;
123
+ private syncNodePosition;
23
124
  /**
24
- * Get text content from node tree
125
+ * Choose the semantic HTML tag for a node's shadow element and set its
126
+ * non-accessibility content (text, input value/placeholder). Roles/names are
127
+ * applied separately from the semantics block.
25
128
  */
26
- private getNodeText;
129
+ private createShadowElement;
27
130
  /**
28
131
  * Focus node in shadow DOM
29
132
  */
@@ -36,10 +139,14 @@ export declare class AccessibilityLayer {
36
139
  * Get shadow element by node ID
37
140
  */
38
141
  getElement(nodeId: string): HTMLElement | undefined;
142
+ /** The fallback-content root element (for focus delegation wiring). */
143
+ getRoot(): HTMLElement | null;
144
+ isEnabled(): boolean;
39
145
  /**
40
- * Enable or disable accessibility layer
146
+ * Enable or disable the mirror. Re-enabling rebuilds from the given
147
+ * virtual tree (incremental sync has no history to replay).
41
148
  */
42
- setEnabled(enabled: boolean): void;
149
+ setEnabled(enabled: boolean, root?: VirtualNode | null): void;
43
150
  /**
44
151
  * Cleanup
45
152
  */