@hypen-space/web 0.2.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.
- package/dist/chunk-2s02mkzs.js +32 -0
- package/dist/chunk-2s02mkzs.js.map +9 -0
- package/dist/src/canvas/accessibility.js +152 -0
- package/dist/src/canvas/accessibility.js.map +10 -0
- package/dist/src/canvas/events.js +198 -0
- package/dist/src/canvas/events.js.map +10 -0
- package/dist/src/canvas/index.js +28 -0
- package/dist/src/canvas/index.js.map +9 -0
- package/dist/src/canvas/input.js +132 -0
- package/dist/src/canvas/input.js.map +10 -0
- package/dist/src/canvas/layout.js +309 -0
- package/dist/src/canvas/layout.js.map +10 -0
- package/dist/src/canvas/paint.js +878 -0
- package/dist/src/canvas/paint.js.map +10 -0
- package/dist/src/canvas/renderer.js +276 -0
- package/dist/src/canvas/renderer.js.map +10 -0
- package/dist/src/canvas/text.js +118 -0
- package/dist/src/canvas/text.js.map +10 -0
- package/dist/src/canvas/types.js +2 -0
- package/dist/src/canvas/types.js.map +9 -0
- package/dist/src/canvas/utils.js +139 -0
- package/dist/src/canvas/utils.js.map +10 -0
- package/dist/src/dom/applicators/advanced-layout.js +111 -0
- package/dist/src/dom/applicators/advanced-layout.js.map +10 -0
- package/dist/src/dom/applicators/background.js +54 -0
- package/dist/src/dom/applicators/background.js.map +10 -0
- package/dist/src/dom/applicators/border.js +33 -0
- package/dist/src/dom/applicators/border.js.map +10 -0
- package/dist/src/dom/applicators/color.js +36 -0
- package/dist/src/dom/applicators/color.js.map +10 -0
- package/dist/src/dom/applicators/display.js +57 -0
- package/dist/src/dom/applicators/display.js.map +10 -0
- package/dist/src/dom/applicators/effects.js +89 -0
- package/dist/src/dom/applicators/effects.js.map +10 -0
- package/dist/src/dom/applicators/events.js +518 -0
- package/dist/src/dom/applicators/events.js.map +10 -0
- package/dist/src/dom/applicators/font.js +39 -0
- package/dist/src/dom/applicators/font.js.map +10 -0
- package/dist/src/dom/applicators/index.js +296 -0
- package/dist/src/dom/applicators/index.js.map +10 -0
- package/dist/src/dom/applicators/layout.js +86 -0
- package/dist/src/dom/applicators/layout.js.map +10 -0
- package/dist/src/dom/applicators/margin.js +32 -0
- package/dist/src/dom/applicators/margin.js.map +10 -0
- package/dist/src/dom/applicators/padding.js +35 -0
- package/dist/src/dom/applicators/padding.js.map +10 -0
- package/dist/src/dom/applicators/size.js +42 -0
- package/dist/src/dom/applicators/size.js.map +10 -0
- package/dist/src/dom/applicators/transform.js +92 -0
- package/dist/src/dom/applicators/transform.js.map +10 -0
- package/dist/src/dom/applicators/transition.js +66 -0
- package/dist/src/dom/applicators/transition.js.map +10 -0
- package/dist/src/dom/applicators/typography.js +87 -0
- package/dist/src/dom/applicators/typography.js.map +10 -0
- package/dist/src/dom/canvas/index.js +50 -0
- package/dist/src/dom/canvas/index.js.map +10 -0
- package/dist/src/dom/components/audio.js +48 -0
- package/dist/src/dom/components/audio.js.map +10 -0
- package/dist/src/dom/components/avatar.js +58 -0
- package/dist/src/dom/components/avatar.js.map +10 -0
- package/dist/src/dom/components/badge.js +55 -0
- package/dist/src/dom/components/badge.js.map +10 -0
- package/dist/src/dom/components/button.js +29 -0
- package/dist/src/dom/components/button.js.map +10 -0
- package/dist/src/dom/components/card.js +33 -0
- package/dist/src/dom/components/card.js.map +10 -0
- package/dist/src/dom/components/center.js +32 -0
- package/dist/src/dom/components/center.js.map +10 -0
- package/dist/src/dom/components/checkbox.js +54 -0
- package/dist/src/dom/components/checkbox.js.map +10 -0
- package/dist/src/dom/components/column.js +31 -0
- package/dist/src/dom/components/column.js.map +10 -0
- package/dist/src/dom/components/container.js +29 -0
- package/dist/src/dom/components/container.js.map +10 -0
- package/dist/src/dom/components/divider.js +45 -0
- package/dist/src/dom/components/divider.js.map +10 -0
- package/dist/src/dom/components/grid.js +44 -0
- package/dist/src/dom/components/grid.js.map +10 -0
- package/dist/src/dom/components/heading.js +47 -0
- package/dist/src/dom/components/heading.js.map +10 -0
- package/dist/src/dom/components/image.js +39 -0
- package/dist/src/dom/components/image.js.map +10 -0
- package/dist/src/dom/components/index.js +217 -0
- package/dist/src/dom/components/index.js.map +10 -0
- package/dist/src/dom/components/input.js +41 -0
- package/dist/src/dom/components/input.js.map +10 -0
- package/dist/src/dom/components/link.js +42 -0
- package/dist/src/dom/components/link.js.map +10 -0
- package/dist/src/dom/components/list.js +42 -0
- package/dist/src/dom/components/list.js.map +10 -0
- package/dist/src/dom/components/paragraph.js +35 -0
- package/dist/src/dom/components/paragraph.js.map +10 -0
- package/dist/src/dom/components/progressbar.js +57 -0
- package/dist/src/dom/components/progressbar.js.map +10 -0
- package/dist/src/dom/components/route.js +44 -0
- package/dist/src/dom/components/route.js.map +10 -0
- package/dist/src/dom/components/router.js +33 -0
- package/dist/src/dom/components/router.js.map +10 -0
- package/dist/src/dom/components/row.js +31 -0
- package/dist/src/dom/components/row.js.map +10 -0
- package/dist/src/dom/components/select.js +57 -0
- package/dist/src/dom/components/select.js.map +10 -0
- package/dist/src/dom/components/slider.js +48 -0
- package/dist/src/dom/components/slider.js.map +10 -0
- package/dist/src/dom/components/spacer.js +30 -0
- package/dist/src/dom/components/spacer.js.map +10 -0
- package/dist/src/dom/components/spinner.js +65 -0
- package/dist/src/dom/components/spinner.js.map +10 -0
- package/dist/src/dom/components/stack.js +45 -0
- package/dist/src/dom/components/stack.js.map +10 -0
- package/dist/src/dom/components/switch.js +83 -0
- package/dist/src/dom/components/switch.js.map +10 -0
- package/dist/src/dom/components/text.js +37 -0
- package/dist/src/dom/components/text.js.map +10 -0
- package/dist/src/dom/components/textarea.js +51 -0
- package/dist/src/dom/components/textarea.js.map +10 -0
- package/dist/src/dom/components/video.js +51 -0
- package/dist/src/dom/components/video.js.map +10 -0
- package/dist/src/dom/debug.js +170 -0
- package/dist/src/dom/debug.js.map +10 -0
- package/dist/src/dom/events.js +112 -0
- package/dist/src/dom/events.js.map +10 -0
- package/dist/src/dom/index.js +73 -0
- package/dist/src/dom/index.js.map +9 -0
- package/dist/src/dom/renderer.js +277 -0
- package/dist/src/dom/renderer.js.map +10 -0
- package/dist/src/index.js +89 -0
- package/dist/src/index.js.map +9 -0
- package/package.json +84 -0
- package/src/canvas/QUICKSTART.md +421 -0
- package/src/canvas/README.md +376 -0
- package/src/canvas/accessibility.ts +218 -0
- package/src/canvas/events.ts +307 -0
- package/src/canvas/index.ts +35 -0
- package/src/canvas/input.ts +210 -0
- package/src/canvas/layout.ts +401 -0
- package/src/canvas/paint.ts +1321 -0
- package/src/canvas/renderer.ts +422 -0
- package/src/canvas/text.ts +182 -0
- package/src/canvas/types.ts +137 -0
- package/src/canvas/utils.ts +218 -0
- package/src/dom/README.md +265 -0
- package/src/dom/applicators/advanced-layout.ts +128 -0
- package/src/dom/applicators/background.ts +50 -0
- package/src/dom/applicators/border.ts +19 -0
- package/src/dom/applicators/color.ts +23 -0
- package/src/dom/applicators/display.ts +54 -0
- package/src/dom/applicators/effects.ts +97 -0
- package/src/dom/applicators/events.ts +689 -0
- package/src/dom/applicators/font.ts +27 -0
- package/src/dom/applicators/index.ts +354 -0
- package/src/dom/applicators/layout.ts +92 -0
- package/src/dom/applicators/margin.ts +18 -0
- package/src/dom/applicators/padding.ts +18 -0
- package/src/dom/applicators/size.ts +31 -0
- package/src/dom/applicators/transform.ts +93 -0
- package/src/dom/applicators/transition.ts +65 -0
- package/src/dom/applicators/typography.ts +91 -0
- package/src/dom/canvas/index.ts +60 -0
- package/src/dom/components/audio.ts +45 -0
- package/src/dom/components/avatar.ts +49 -0
- package/src/dom/components/badge.ts +45 -0
- package/src/dom/components/button.ts +13 -0
- package/src/dom/components/card.ts +19 -0
- package/src/dom/components/center.ts +16 -0
- package/src/dom/components/checkbox.ts +54 -0
- package/src/dom/components/column.ts +15 -0
- package/src/dom/components/container.ts +13 -0
- package/src/dom/components/divider.ts +37 -0
- package/src/dom/components/grid.ts +40 -0
- package/src/dom/components/heading.ts +41 -0
- package/src/dom/components/image.ts +27 -0
- package/src/dom/components/index.ts +115 -0
- package/src/dom/components/input.ts +29 -0
- package/src/dom/components/link.ts +35 -0
- package/src/dom/components/list.ts +30 -0
- package/src/dom/components/paragraph.ts +23 -0
- package/src/dom/components/progressbar.ts +51 -0
- package/src/dom/components/route.ts +37 -0
- package/src/dom/components/router.ts +22 -0
- package/src/dom/components/row.ts +15 -0
- package/src/dom/components/select.ts +56 -0
- package/src/dom/components/slider.ts +45 -0
- package/src/dom/components/spacer.ts +16 -0
- package/src/dom/components/spinner.ts +60 -0
- package/src/dom/components/stack.ts +34 -0
- package/src/dom/components/switch.ts +86 -0
- package/src/dom/components/text.ts +24 -0
- package/src/dom/components/textarea.ts +50 -0
- package/src/dom/components/video.ts +50 -0
- package/src/dom/debug.ts +247 -0
- package/src/dom/events.ts +168 -0
- package/src/dom/index.ts +11 -0
- package/src/dom/renderer.ts +327 -0
- package/src/index.ts +56 -0
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
+
var __moduleCache = /* @__PURE__ */ new WeakMap;
|
|
6
|
+
var __toCommonJS = (from) => {
|
|
7
|
+
var entry = __moduleCache.get(from), desc;
|
|
8
|
+
if (entry)
|
|
9
|
+
return entry;
|
|
10
|
+
entry = __defProp({}, "__esModule", { value: true });
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function")
|
|
12
|
+
__getOwnPropNames(from).map((key) => !__hasOwnProp.call(entry, key) && __defProp(entry, key, {
|
|
13
|
+
get: () => from[key],
|
|
14
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
15
|
+
}));
|
|
16
|
+
__moduleCache.set(from, entry);
|
|
17
|
+
return entry;
|
|
18
|
+
};
|
|
19
|
+
var __export = (target, all) => {
|
|
20
|
+
for (var name in all)
|
|
21
|
+
__defProp(target, name, {
|
|
22
|
+
get: all[name],
|
|
23
|
+
enumerable: true,
|
|
24
|
+
configurable: true,
|
|
25
|
+
set: (newValue) => all[name] = () => newValue
|
|
26
|
+
});
|
|
27
|
+
};
|
|
28
|
+
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
29
|
+
|
|
30
|
+
export { __toCommonJS, __export, __esm };
|
|
31
|
+
|
|
32
|
+
//# debugId=7CFBE4211FBB190464756E2164756E21
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import"../../chunk-2s02mkzs.js";
|
|
2
|
+
|
|
3
|
+
// src/canvas/accessibility.ts
|
|
4
|
+
class AccessibilityLayer {
|
|
5
|
+
shadowRoot;
|
|
6
|
+
nodeMap = new Map;
|
|
7
|
+
enabled;
|
|
8
|
+
constructor(container, enabled = true) {
|
|
9
|
+
this.enabled = enabled && typeof document !== "undefined";
|
|
10
|
+
if (this.enabled && typeof document !== "undefined") {
|
|
11
|
+
this.shadowRoot = document.createElement("div");
|
|
12
|
+
this.shadowRoot.setAttribute("role", "application");
|
|
13
|
+
this.shadowRoot.setAttribute("aria-label", "Hypen Canvas Application");
|
|
14
|
+
this.shadowRoot.style.position = "absolute";
|
|
15
|
+
this.shadowRoot.style.left = "-9999px";
|
|
16
|
+
this.shadowRoot.style.width = "1px";
|
|
17
|
+
this.shadowRoot.style.height = "1px";
|
|
18
|
+
this.shadowRoot.style.overflow = "hidden";
|
|
19
|
+
if (container) {
|
|
20
|
+
container.appendChild(this.shadowRoot);
|
|
21
|
+
}
|
|
22
|
+
} else {
|
|
23
|
+
this.shadowRoot = {};
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
syncTree(root) {
|
|
27
|
+
if (!this.enabled)
|
|
28
|
+
return;
|
|
29
|
+
this.shadowRoot.innerHTML = "";
|
|
30
|
+
this.nodeMap.clear();
|
|
31
|
+
const shadowNode = this.createShadowNode(root);
|
|
32
|
+
if (shadowNode) {
|
|
33
|
+
this.shadowRoot.appendChild(shadowNode);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
createShadowNode(node) {
|
|
37
|
+
if (!node.visible)
|
|
38
|
+
return null;
|
|
39
|
+
let element;
|
|
40
|
+
switch (node.type.toLowerCase()) {
|
|
41
|
+
case "button":
|
|
42
|
+
element = document.createElement("button");
|
|
43
|
+
element.textContent = this.getNodeText(node);
|
|
44
|
+
if (node.props.onclick) {
|
|
45
|
+
element.setAttribute("aria-label", "Clickable button");
|
|
46
|
+
}
|
|
47
|
+
break;
|
|
48
|
+
case "input":
|
|
49
|
+
element = document.createElement("input");
|
|
50
|
+
element.type = node.props.type || "text";
|
|
51
|
+
element.value = node.props.value || "";
|
|
52
|
+
if (node.props.placeholder) {
|
|
53
|
+
element.placeholder = node.props.placeholder;
|
|
54
|
+
}
|
|
55
|
+
break;
|
|
56
|
+
case "textarea":
|
|
57
|
+
element = document.createElement("textarea");
|
|
58
|
+
element.value = node.props.value || "";
|
|
59
|
+
if (node.props.placeholder) {
|
|
60
|
+
element.placeholder = node.props.placeholder;
|
|
61
|
+
}
|
|
62
|
+
break;
|
|
63
|
+
case "image":
|
|
64
|
+
element = document.createElement("img");
|
|
65
|
+
element.src = node.props.src || "";
|
|
66
|
+
element.alt = node.props.alt || "Image";
|
|
67
|
+
break;
|
|
68
|
+
case "text":
|
|
69
|
+
element = document.createElement("span");
|
|
70
|
+
element.textContent = String(node.props[0] || node.props.text || "");
|
|
71
|
+
break;
|
|
72
|
+
case "column":
|
|
73
|
+
case "row":
|
|
74
|
+
case "container":
|
|
75
|
+
case "box":
|
|
76
|
+
element = document.createElement("div");
|
|
77
|
+
element.setAttribute("role", node.type === "column" ? "group" : "group");
|
|
78
|
+
break;
|
|
79
|
+
default:
|
|
80
|
+
element = document.createElement("div");
|
|
81
|
+
}
|
|
82
|
+
element.setAttribute("data-hypen-id", node.id);
|
|
83
|
+
if (node.props["aria-label"]) {
|
|
84
|
+
element.setAttribute("aria-label", node.props["aria-label"]);
|
|
85
|
+
}
|
|
86
|
+
if (node.focusable) {
|
|
87
|
+
element.tabIndex = 0;
|
|
88
|
+
}
|
|
89
|
+
this.nodeMap.set(node.id, element);
|
|
90
|
+
for (const child of node.children) {
|
|
91
|
+
const childElement = this.createShadowNode(child);
|
|
92
|
+
if (childElement) {
|
|
93
|
+
element.appendChild(childElement);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return element;
|
|
97
|
+
}
|
|
98
|
+
getNodeText(node) {
|
|
99
|
+
if (node.type === "text") {
|
|
100
|
+
return String(node.props[0] || node.props.text || "");
|
|
101
|
+
}
|
|
102
|
+
let text = "";
|
|
103
|
+
for (const child of node.children) {
|
|
104
|
+
text += this.getNodeText(child);
|
|
105
|
+
}
|
|
106
|
+
return text;
|
|
107
|
+
}
|
|
108
|
+
focusNode(nodeId) {
|
|
109
|
+
if (!this.enabled)
|
|
110
|
+
return;
|
|
111
|
+
const element = this.nodeMap.get(nodeId);
|
|
112
|
+
if (element) {
|
|
113
|
+
element.focus();
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
updateNode(node) {
|
|
117
|
+
if (!this.enabled)
|
|
118
|
+
return;
|
|
119
|
+
const element = this.nodeMap.get(node.id);
|
|
120
|
+
if (!element)
|
|
121
|
+
return;
|
|
122
|
+
if (node.type === "text") {
|
|
123
|
+
element.textContent = String(node.props[0] || node.props.text || "");
|
|
124
|
+
}
|
|
125
|
+
if (node.type === "input" || node.type === "textarea") {
|
|
126
|
+
element.value = node.props.value || "";
|
|
127
|
+
}
|
|
128
|
+
element.style.display = node.visible ? "" : "none";
|
|
129
|
+
}
|
|
130
|
+
getElement(nodeId) {
|
|
131
|
+
return this.nodeMap.get(nodeId);
|
|
132
|
+
}
|
|
133
|
+
setEnabled(enabled) {
|
|
134
|
+
this.enabled = enabled;
|
|
135
|
+
if (!enabled && this.shadowRoot.parentElement) {
|
|
136
|
+
this.shadowRoot.remove();
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
destroy() {
|
|
140
|
+
if (this.shadowRoot.parentElement) {
|
|
141
|
+
this.shadowRoot.remove();
|
|
142
|
+
}
|
|
143
|
+
this.nodeMap.clear();
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
export {
|
|
147
|
+
AccessibilityLayer
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
export { AccessibilityLayer };
|
|
151
|
+
|
|
152
|
+
//# debugId=FEB7D90D0DE68F0B64756E2164756E21
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/canvas/accessibility.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"/**\n * Accessibility Layer\n *\n * Maintain shadow DOM for screen readers\n */\n\nimport type { VirtualNode } from \"./types.js\";\nimport { walkTree } from \"./utils.js\";\n\n/**\n * Accessibility Manager\n */\nexport class AccessibilityLayer {\n private shadowRoot: HTMLElement;\n private nodeMap = new Map<string, HTMLElement>();\n private enabled: boolean;\n\n constructor(container: HTMLElement | null, enabled: boolean = true) {\n this.enabled = enabled && typeof document !== \"undefined\";\n\n // Create shadow root container (only in browser)\n if (this.enabled && typeof document !== \"undefined\") {\n this.shadowRoot = document.createElement(\"div\");\n this.shadowRoot.setAttribute(\"role\", \"application\");\n this.shadowRoot.setAttribute(\"aria-label\", \"Hypen Canvas Application\");\n this.shadowRoot.style.position = \"absolute\";\n this.shadowRoot.style.left = \"-9999px\";\n this.shadowRoot.style.width = \"1px\";\n this.shadowRoot.style.height = \"1px\";\n this.shadowRoot.style.overflow = \"hidden\";\n\n if (container) {\n container.appendChild(this.shadowRoot);\n }\n } else {\n // Fallback for non-browser environments\n this.shadowRoot = {} as HTMLElement;\n }\n }\n\n /**\n * Sync shadow DOM with virtual tree\n */\n syncTree(root: VirtualNode): void {\n if (!this.enabled) return;\n\n // Clear existing\n this.shadowRoot.innerHTML = \"\";\n this.nodeMap.clear();\n\n // Build shadow DOM\n const shadowNode = this.createShadowNode(root);\n if (shadowNode) {\n this.shadowRoot.appendChild(shadowNode);\n }\n }\n\n /**\n * Create shadow DOM element for virtual node\n */\n private createShadowNode(node: VirtualNode): HTMLElement | null {\n if (!node.visible) return null;\n\n let element: HTMLElement;\n\n // Create appropriate HTML element\n switch (node.type.toLowerCase()) {\n case \"button\":\n element = document.createElement(\"button\");\n element.textContent = this.getNodeText(node);\n if (node.props.onclick) {\n element.setAttribute(\"aria-label\", \"Clickable button\");\n }\n break;\n\n case \"input\":\n element = document.createElement(\"input\");\n (element as HTMLInputElement).type = node.props.type || \"text\";\n (element as HTMLInputElement).value = node.props.value || \"\";\n if (node.props.placeholder) {\n (element as HTMLInputElement).placeholder = node.props.placeholder;\n }\n break;\n\n case \"textarea\":\n element = document.createElement(\"textarea\");\n (element as HTMLTextAreaElement).value = node.props.value || \"\";\n if (node.props.placeholder) {\n (element as HTMLTextAreaElement).placeholder = node.props.placeholder;\n }\n break;\n\n case \"image\":\n element = document.createElement(\"img\");\n (element as HTMLImageElement).src = node.props.src || \"\";\n (element as HTMLImageElement).alt = node.props.alt || \"Image\";\n break;\n\n case \"text\":\n element = document.createElement(\"span\");\n element.textContent = String(node.props[0] || node.props.text || \"\");\n break;\n\n case \"column\":\n case \"row\":\n case \"container\":\n case \"box\":\n element = document.createElement(\"div\");\n element.setAttribute(\"role\", node.type === \"column\" ? \"group\" : \"group\");\n break;\n\n default:\n element = document.createElement(\"div\");\n }\n\n // Set common attributes\n element.setAttribute(\"data-hypen-id\", node.id);\n\n if (node.props[\"aria-label\"]) {\n element.setAttribute(\"aria-label\", node.props[\"aria-label\"]);\n }\n\n if (node.focusable) {\n element.tabIndex = 0;\n }\n\n // Store mapping\n this.nodeMap.set(node.id, element);\n\n // Add children\n for (const child of node.children) {\n const childElement = this.createShadowNode(child);\n if (childElement) {\n element.appendChild(childElement);\n }\n }\n\n return element;\n }\n\n /**\n * Get text content from node tree\n */\n private getNodeText(node: VirtualNode): string {\n if (node.type === \"text\") {\n return String(node.props[0] || node.props.text || \"\");\n }\n\n let text = \"\";\n for (const child of node.children) {\n text += this.getNodeText(child);\n }\n return text;\n }\n\n /**\n * Focus node in shadow DOM\n */\n focusNode(nodeId: string): void {\n if (!this.enabled) return;\n\n const element = this.nodeMap.get(nodeId);\n if (element) {\n element.focus();\n }\n }\n\n /**\n * Update single node\n */\n updateNode(node: VirtualNode): void {\n if (!this.enabled) return;\n\n const element = this.nodeMap.get(node.id);\n if (!element) return;\n\n // Update text content\n if (node.type === \"text\") {\n element.textContent = String(node.props[0] || node.props.text || \"\");\n }\n\n // Update input value\n if (node.type === \"input\" || node.type === \"textarea\") {\n (element as HTMLInputElement | HTMLTextAreaElement).value = node.props.value || \"\";\n }\n\n // Update visibility\n element.style.display = node.visible ? \"\" : \"none\";\n }\n\n /**\n * Get shadow element by node ID\n */\n getElement(nodeId: string): HTMLElement | undefined {\n return this.nodeMap.get(nodeId);\n }\n\n /**\n * Enable or disable accessibility layer\n */\n setEnabled(enabled: boolean): void {\n this.enabled = enabled;\n if (!enabled && this.shadowRoot.parentElement) {\n this.shadowRoot.remove();\n }\n }\n\n /**\n * Cleanup\n */\n destroy(): void {\n if (this.shadowRoot.parentElement) {\n this.shadowRoot.remove();\n }\n this.nodeMap.clear();\n }\n}\n\n"
|
|
6
|
+
],
|
|
7
|
+
"mappings": "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",
|
|
8
|
+
"debugId": "FEB7D90D0DE68F0B64756E2164756E21",
|
|
9
|
+
"names": []
|
|
10
|
+
}
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getAbsoluteBounds,
|
|
3
|
+
isPointInRoundedRect
|
|
4
|
+
} from "./utils.js";
|
|
5
|
+
import"../../chunk-2s02mkzs.js";
|
|
6
|
+
|
|
7
|
+
// src/canvas/events.ts
|
|
8
|
+
class CanvasEventManager {
|
|
9
|
+
canvas;
|
|
10
|
+
engine;
|
|
11
|
+
rootNode = null;
|
|
12
|
+
hoveredNode = null;
|
|
13
|
+
focusedNode = null;
|
|
14
|
+
mouseDownNode = null;
|
|
15
|
+
constructor(canvas, engine) {
|
|
16
|
+
this.canvas = canvas;
|
|
17
|
+
this.engine = engine;
|
|
18
|
+
this.setupEventListeners();
|
|
19
|
+
}
|
|
20
|
+
setRootNode(node) {
|
|
21
|
+
this.rootNode = node;
|
|
22
|
+
}
|
|
23
|
+
setupEventListeners() {
|
|
24
|
+
this.canvas.addEventListener("mousemove", this.onMouseMove.bind(this));
|
|
25
|
+
this.canvas.addEventListener("mousedown", this.onMouseDown.bind(this));
|
|
26
|
+
this.canvas.addEventListener("mouseup", this.onMouseUp.bind(this));
|
|
27
|
+
this.canvas.addEventListener("click", this.onClick.bind(this));
|
|
28
|
+
this.canvas.addEventListener("dblclick", this.onDoubleClick.bind(this));
|
|
29
|
+
this.canvas.addEventListener("keydown", this.onKeyDown.bind(this));
|
|
30
|
+
this.canvas.addEventListener("keyup", this.onKeyUp.bind(this));
|
|
31
|
+
}
|
|
32
|
+
getCanvasCoordinates(e) {
|
|
33
|
+
const rect = this.canvas.getBoundingClientRect();
|
|
34
|
+
const scaleX = this.canvas.width / rect.width;
|
|
35
|
+
const scaleY = this.canvas.height / rect.height;
|
|
36
|
+
return {
|
|
37
|
+
x: (e.clientX - rect.left) * scaleX,
|
|
38
|
+
y: (e.clientY - rect.top) * scaleY
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
hitTest(point) {
|
|
42
|
+
if (!this.rootNode)
|
|
43
|
+
return null;
|
|
44
|
+
return this.hitTestNode(this.rootNode, point);
|
|
45
|
+
}
|
|
46
|
+
hitTestNode(node, point) {
|
|
47
|
+
if (!node.visible || !node.layout)
|
|
48
|
+
return null;
|
|
49
|
+
const bounds = getAbsoluteBounds(node);
|
|
50
|
+
if (!bounds)
|
|
51
|
+
return null;
|
|
52
|
+
for (let i = node.children.length - 1;i >= 0; i--) {
|
|
53
|
+
const child = node.children[i];
|
|
54
|
+
const hit = this.hitTestNode(child, point);
|
|
55
|
+
if (hit)
|
|
56
|
+
return hit;
|
|
57
|
+
}
|
|
58
|
+
const radius = node.layout.border.radius;
|
|
59
|
+
if (isPointInRoundedRect(point, bounds, radius)) {
|
|
60
|
+
return node;
|
|
61
|
+
}
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
onMouseMove(e) {
|
|
65
|
+
const point = this.getCanvasCoordinates(e);
|
|
66
|
+
const node = this.hitTest(point);
|
|
67
|
+
if (node !== this.hoveredNode) {
|
|
68
|
+
if (this.hoveredNode) {
|
|
69
|
+
this.hoveredNode.hovered = false;
|
|
70
|
+
this.dispatchNodeEvent(this.hoveredNode, "mouseleave", {});
|
|
71
|
+
}
|
|
72
|
+
this.hoveredNode = node;
|
|
73
|
+
if (node) {
|
|
74
|
+
node.hovered = true;
|
|
75
|
+
this.dispatchNodeEvent(node, "mouseenter", {});
|
|
76
|
+
}
|
|
77
|
+
this.updateCursor(node);
|
|
78
|
+
this.requestRedraw();
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
onMouseDown(e) {
|
|
82
|
+
const point = this.getCanvasCoordinates(e);
|
|
83
|
+
const node = this.hitTest(point);
|
|
84
|
+
this.mouseDownNode = node;
|
|
85
|
+
if (node && node.clickable) {
|
|
86
|
+
this.dispatchNodeEvent(node, "mousedown", {
|
|
87
|
+
button: e.button,
|
|
88
|
+
clientX: e.clientX,
|
|
89
|
+
clientY: e.clientY
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
if (node && node.focusable) {
|
|
93
|
+
this.setFocus(node);
|
|
94
|
+
} else {
|
|
95
|
+
this.setFocus(null);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
onMouseUp(e) {
|
|
99
|
+
const point = this.getCanvasCoordinates(e);
|
|
100
|
+
const node = this.hitTest(point);
|
|
101
|
+
if (node && node.clickable) {
|
|
102
|
+
this.dispatchNodeEvent(node, "mouseup", {
|
|
103
|
+
button: e.button,
|
|
104
|
+
clientX: e.clientX,
|
|
105
|
+
clientY: e.clientY
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
this.mouseDownNode = null;
|
|
109
|
+
}
|
|
110
|
+
onClick(e) {
|
|
111
|
+
const point = this.getCanvasCoordinates(e);
|
|
112
|
+
const node = this.hitTest(point);
|
|
113
|
+
if (node && node.clickable && node === this.mouseDownNode) {
|
|
114
|
+
this.dispatchNodeEvent(node, "click", {
|
|
115
|
+
button: e.button,
|
|
116
|
+
clientX: e.clientX,
|
|
117
|
+
clientY: e.clientY
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
onDoubleClick(e) {
|
|
122
|
+
const point = this.getCanvasCoordinates(e);
|
|
123
|
+
const node = this.hitTest(point);
|
|
124
|
+
if (node && node.clickable) {
|
|
125
|
+
this.dispatchNodeEvent(node, "dblclick", {
|
|
126
|
+
button: e.button,
|
|
127
|
+
clientX: e.clientX,
|
|
128
|
+
clientY: e.clientY
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
onKeyDown(e) {
|
|
133
|
+
if (this.focusedNode) {
|
|
134
|
+
this.dispatchNodeEvent(this.focusedNode, "keydown", {
|
|
135
|
+
key: e.key,
|
|
136
|
+
code: e.code,
|
|
137
|
+
ctrlKey: e.ctrlKey,
|
|
138
|
+
shiftKey: e.shiftKey,
|
|
139
|
+
altKey: e.altKey
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
onKeyUp(e) {
|
|
144
|
+
if (this.focusedNode) {
|
|
145
|
+
this.dispatchNodeEvent(this.focusedNode, "keyup", {
|
|
146
|
+
key: e.key,
|
|
147
|
+
code: e.code,
|
|
148
|
+
ctrlKey: e.ctrlKey,
|
|
149
|
+
shiftKey: e.shiftKey,
|
|
150
|
+
altKey: e.altKey
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
setFocus(node) {
|
|
155
|
+
if (node === this.focusedNode)
|
|
156
|
+
return;
|
|
157
|
+
if (this.focusedNode) {
|
|
158
|
+
this.focusedNode.focused = false;
|
|
159
|
+
this.dispatchNodeEvent(this.focusedNode, "blur", {});
|
|
160
|
+
}
|
|
161
|
+
this.focusedNode = node;
|
|
162
|
+
if (node) {
|
|
163
|
+
node.focused = true;
|
|
164
|
+
this.dispatchNodeEvent(node, "focus", {});
|
|
165
|
+
}
|
|
166
|
+
this.requestRedraw();
|
|
167
|
+
}
|
|
168
|
+
updateCursor(node) {
|
|
169
|
+
if (!node) {
|
|
170
|
+
this.canvas.style.cursor = "default";
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
const cursor = node.props.cursor || (node.clickable ? "pointer" : "default");
|
|
174
|
+
this.canvas.style.cursor = cursor;
|
|
175
|
+
}
|
|
176
|
+
dispatchNodeEvent(node, eventType, data) {
|
|
177
|
+
const actionName = node.props[`on${eventType}`] || node.props[eventType];
|
|
178
|
+
if (actionName && typeof actionName === "string") {
|
|
179
|
+
this.engine.dispatchAction(actionName, {
|
|
180
|
+
type: eventType,
|
|
181
|
+
nodeId: node.id,
|
|
182
|
+
timestamp: Date.now(),
|
|
183
|
+
...data
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
requestRedraw() {
|
|
188
|
+
this.canvas.dispatchEvent(new CustomEvent("hypen:redraw"));
|
|
189
|
+
}
|
|
190
|
+
destroy() {}
|
|
191
|
+
}
|
|
192
|
+
export {
|
|
193
|
+
CanvasEventManager
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
export { CanvasEventManager };
|
|
197
|
+
|
|
198
|
+
//# debugId=4735E18D82AF967764756E2164756E21
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/canvas/events.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"/**\n * Event System\n *\n * Hit testing and event handling for canvas nodes\n */\n\nimport type { VirtualNode, Point } from \"./types.js\";\nimport { isPointInRoundedRect, getAbsoluteBounds } from \"./utils.js\";\n\n// Interface for the engine that CanvasEventManager needs\ninterface IEngine {\n dispatchAction(name: string, payload?: any): void;\n}\n\n/**\n * Canvas Event Manager\n */\nexport class CanvasEventManager {\n private canvas: HTMLCanvasElement;\n private engine: IEngine;\n private rootNode: VirtualNode | null = null;\n private hoveredNode: VirtualNode | null = null;\n private focusedNode: VirtualNode | null = null;\n private mouseDownNode: VirtualNode | null = null;\n\n constructor(canvas: HTMLCanvasElement, engine: IEngine) {\n this.canvas = canvas;\n this.engine = engine;\n this.setupEventListeners();\n }\n\n /**\n * Set the root node for hit testing\n */\n setRootNode(node: VirtualNode | null): void {\n this.rootNode = node;\n }\n\n /**\n * Setup canvas event listeners\n */\n private setupEventListeners(): void {\n this.canvas.addEventListener(\"mousemove\", this.onMouseMove.bind(this));\n this.canvas.addEventListener(\"mousedown\", this.onMouseDown.bind(this));\n this.canvas.addEventListener(\"mouseup\", this.onMouseUp.bind(this));\n this.canvas.addEventListener(\"click\", this.onClick.bind(this));\n this.canvas.addEventListener(\"dblclick\", this.onDoubleClick.bind(this));\n this.canvas.addEventListener(\"keydown\", this.onKeyDown.bind(this));\n this.canvas.addEventListener(\"keyup\", this.onKeyUp.bind(this));\n }\n\n /**\n * Get canvas coordinates from mouse event\n */\n private getCanvasCoordinates(e: MouseEvent): Point {\n const rect = this.canvas.getBoundingClientRect();\n const scaleX = this.canvas.width / rect.width;\n const scaleY = this.canvas.height / rect.height;\n\n return {\n x: (e.clientX - rect.left) * scaleX,\n y: (e.clientY - rect.top) * scaleY,\n };\n }\n\n /**\n * Find node at canvas coordinates\n */\n private hitTest(point: Point): VirtualNode | null {\n if (!this.rootNode) return null;\n return this.hitTestNode(this.rootNode, point);\n }\n\n /**\n * Recursively test node and children\n */\n private hitTestNode(node: VirtualNode, point: Point): VirtualNode | null {\n if (!node.visible || !node.layout) return null;\n\n const bounds = getAbsoluteBounds(node);\n if (!bounds) return null;\n\n // Test children first (front to back)\n for (let i = node.children.length - 1; i >= 0; i--) {\n const child = node.children[i];\n const hit = this.hitTestNode(child, point);\n if (hit) return hit;\n }\n\n // Test this node\n const radius = node.layout.border.radius;\n if (isPointInRoundedRect(point, bounds, radius)) {\n return node;\n }\n\n return null;\n }\n\n /**\n * Handle mouse move\n */\n private onMouseMove(e: MouseEvent): void {\n const point = this.getCanvasCoordinates(e);\n const node = this.hitTest(point);\n\n // Update hover state\n if (node !== this.hoveredNode) {\n // Leave old node\n if (this.hoveredNode) {\n this.hoveredNode.hovered = false;\n this.dispatchNodeEvent(this.hoveredNode, \"mouseleave\", {});\n }\n\n // Enter new node\n this.hoveredNode = node;\n if (node) {\n node.hovered = true;\n this.dispatchNodeEvent(node, \"mouseenter\", {});\n }\n\n // Update cursor\n this.updateCursor(node);\n\n // Request redraw for hover effects\n this.requestRedraw();\n }\n }\n\n /**\n * Handle mouse down\n */\n private onMouseDown(e: MouseEvent): void {\n const point = this.getCanvasCoordinates(e);\n const node = this.hitTest(point);\n\n this.mouseDownNode = node;\n\n if (node && node.clickable) {\n this.dispatchNodeEvent(node, \"mousedown\", {\n button: e.button,\n clientX: e.clientX,\n clientY: e.clientY,\n });\n }\n\n // Update focus\n if (node && node.focusable) {\n this.setFocus(node);\n } else {\n this.setFocus(null);\n }\n }\n\n /**\n * Handle mouse up\n */\n private onMouseUp(e: MouseEvent): void {\n const point = this.getCanvasCoordinates(e);\n const node = this.hitTest(point);\n\n if (node && node.clickable) {\n this.dispatchNodeEvent(node, \"mouseup\", {\n button: e.button,\n clientX: e.clientX,\n clientY: e.clientY,\n });\n }\n\n this.mouseDownNode = null;\n }\n\n /**\n * Handle click\n */\n private onClick(e: MouseEvent): void {\n const point = this.getCanvasCoordinates(e);\n const node = this.hitTest(point);\n\n if (node && node.clickable && node === this.mouseDownNode) {\n this.dispatchNodeEvent(node, \"click\", {\n button: e.button,\n clientX: e.clientX,\n clientY: e.clientY,\n });\n }\n }\n\n /**\n * Handle double click\n */\n private onDoubleClick(e: MouseEvent): void {\n const point = this.getCanvasCoordinates(e);\n const node = this.hitTest(point);\n\n if (node && node.clickable) {\n this.dispatchNodeEvent(node, \"dblclick\", {\n button: e.button,\n clientX: e.clientX,\n clientY: e.clientY,\n });\n }\n }\n\n /**\n * Handle keyboard events\n */\n private onKeyDown(e: KeyboardEvent): void {\n if (this.focusedNode) {\n this.dispatchNodeEvent(this.focusedNode, \"keydown\", {\n key: e.key,\n code: e.code,\n ctrlKey: e.ctrlKey,\n shiftKey: e.shiftKey,\n altKey: e.altKey,\n });\n }\n }\n\n private onKeyUp(e: KeyboardEvent): void {\n if (this.focusedNode) {\n this.dispatchNodeEvent(this.focusedNode, \"keyup\", {\n key: e.key,\n code: e.code,\n ctrlKey: e.ctrlKey,\n shiftKey: e.shiftKey,\n altKey: e.altKey,\n });\n }\n }\n\n /**\n * Set focused node\n */\n private setFocus(node: VirtualNode | null): void {\n if (node === this.focusedNode) return;\n\n if (this.focusedNode) {\n this.focusedNode.focused = false;\n this.dispatchNodeEvent(this.focusedNode, \"blur\", {});\n }\n\n this.focusedNode = node;\n\n if (node) {\n node.focused = true;\n this.dispatchNodeEvent(node, \"focus\", {});\n }\n\n this.requestRedraw();\n }\n\n /**\n * Update cursor based on node\n */\n private updateCursor(node: VirtualNode | null): void {\n if (!node) {\n this.canvas.style.cursor = \"default\";\n return;\n }\n\n const cursor = node.props.cursor || (node.clickable ? \"pointer\" : \"default\");\n this.canvas.style.cursor = cursor;\n }\n\n /**\n * Dispatch event to engine\n */\n private dispatchNodeEvent(node: VirtualNode, eventType: string, data: any): void {\n // Check if node has action handler for this event\n const actionName = node.props[`on${eventType}`] || node.props[eventType];\n\n if (actionName && typeof actionName === \"string\") {\n // Dispatch to engine\n this.engine.dispatchAction(actionName, {\n type: eventType,\n nodeId: node.id,\n timestamp: Date.now(),\n ...data,\n });\n }\n }\n\n /**\n * Request redraw from renderer\n */\n private requestRedraw(): void {\n // This will be called via a callback set by the renderer\n // For now, dispatch a custom event\n this.canvas.dispatchEvent(new CustomEvent(\"hypen:redraw\"));\n }\n\n /**\n * Cleanup\n */\n destroy(): void {\n // Remove event listeners if needed\n }\n}\n\n\n\n\n\n\n\n\n\n"
|
|
6
|
+
],
|
|
7
|
+
"mappings": "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",
|
|
8
|
+
"debugId": "4735E18D82AF967764756E2164756E21",
|
|
9
|
+
"names": []
|
|
10
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CanvasRenderer
|
|
3
|
+
} from "./renderer.js";
|
|
4
|
+
import {
|
|
5
|
+
registerPainter
|
|
6
|
+
} from "./paint.js";
|
|
7
|
+
import"./layout.js";
|
|
8
|
+
import {
|
|
9
|
+
CanvasEventManager
|
|
10
|
+
} from "./events.js";
|
|
11
|
+
import {
|
|
12
|
+
AccessibilityLayer
|
|
13
|
+
} from "./accessibility.js";
|
|
14
|
+
import"./text.js";
|
|
15
|
+
import {
|
|
16
|
+
InputOverlay
|
|
17
|
+
} from "./input.js";
|
|
18
|
+
import"./utils.js";
|
|
19
|
+
import"../../chunk-2s02mkzs.js";
|
|
20
|
+
export {
|
|
21
|
+
registerPainter,
|
|
22
|
+
InputOverlay,
|
|
23
|
+
CanvasRenderer,
|
|
24
|
+
CanvasEventManager,
|
|
25
|
+
AccessibilityLayer
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
//# debugId=11D5013CD5400CA064756E2164756E21
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getAbsoluteBounds
|
|
3
|
+
} from "./utils.js";
|
|
4
|
+
import"../../chunk-2s02mkzs.js";
|
|
5
|
+
|
|
6
|
+
// src/canvas/input.ts
|
|
7
|
+
class InputOverlay {
|
|
8
|
+
container;
|
|
9
|
+
overlay = null;
|
|
10
|
+
focusedNode = null;
|
|
11
|
+
onChangeCallback = null;
|
|
12
|
+
constructor(container) {
|
|
13
|
+
this.container = container || {};
|
|
14
|
+
}
|
|
15
|
+
showInput(node, canvasBounds, onChange) {
|
|
16
|
+
if (typeof document === "undefined")
|
|
17
|
+
return;
|
|
18
|
+
this.hideInput();
|
|
19
|
+
const bounds = getAbsoluteBounds(node);
|
|
20
|
+
if (!bounds)
|
|
21
|
+
return;
|
|
22
|
+
const isMultiline = node.type === "textarea";
|
|
23
|
+
this.overlay = isMultiline ? document.createElement("textarea") : document.createElement("input");
|
|
24
|
+
this.styleOverlay(node, bounds, canvasBounds);
|
|
25
|
+
const value = node.props.value || "";
|
|
26
|
+
this.overlay.value = value;
|
|
27
|
+
this.onChangeCallback = onChange;
|
|
28
|
+
this.overlay.addEventListener("input", this.onInput.bind(this));
|
|
29
|
+
this.overlay.addEventListener("blur", this.onBlur.bind(this));
|
|
30
|
+
this.overlay.addEventListener("keydown", this.onKeyDown.bind(this));
|
|
31
|
+
this.container.appendChild(this.overlay);
|
|
32
|
+
this.overlay.focus();
|
|
33
|
+
this.focusedNode = node;
|
|
34
|
+
}
|
|
35
|
+
hideInput() {
|
|
36
|
+
if (this.overlay) {
|
|
37
|
+
this.overlay.remove();
|
|
38
|
+
this.overlay = null;
|
|
39
|
+
}
|
|
40
|
+
this.focusedNode = null;
|
|
41
|
+
this.onChangeCallback = null;
|
|
42
|
+
}
|
|
43
|
+
updatePosition(node, canvasBounds) {
|
|
44
|
+
if (!this.overlay || node !== this.focusedNode)
|
|
45
|
+
return;
|
|
46
|
+
const bounds = getAbsoluteBounds(node);
|
|
47
|
+
if (!bounds)
|
|
48
|
+
return;
|
|
49
|
+
this.positionOverlay(bounds, canvasBounds);
|
|
50
|
+
}
|
|
51
|
+
styleOverlay(node, bounds, canvasBounds) {
|
|
52
|
+
if (!this.overlay)
|
|
53
|
+
return;
|
|
54
|
+
const props = node.props;
|
|
55
|
+
this.positionOverlay(bounds, canvasBounds);
|
|
56
|
+
const fontSize = parseFloat(props.fontSize) || 16;
|
|
57
|
+
const fontWeight = props.fontWeight || "normal";
|
|
58
|
+
const fontFamily = props.fontFamily || "system-ui, sans-serif";
|
|
59
|
+
const color = props.color || "#000000";
|
|
60
|
+
Object.assign(this.overlay.style, {
|
|
61
|
+
fontSize: `${fontSize}px`,
|
|
62
|
+
fontWeight,
|
|
63
|
+
fontFamily,
|
|
64
|
+
color,
|
|
65
|
+
border: "none",
|
|
66
|
+
outline: "2px solid #007bff",
|
|
67
|
+
backgroundColor: props.backgroundColor || "#ffffff",
|
|
68
|
+
padding: `${props.padding || 8}px`,
|
|
69
|
+
borderRadius: `${props.borderRadius || 4}px`,
|
|
70
|
+
boxSizing: "border-box",
|
|
71
|
+
resize: "none"
|
|
72
|
+
});
|
|
73
|
+
if (props.placeholder) {
|
|
74
|
+
this.overlay.placeholder = props.placeholder;
|
|
75
|
+
}
|
|
76
|
+
if (this.overlay instanceof HTMLInputElement && props.type) {
|
|
77
|
+
this.overlay.type = props.type;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
positionOverlay(bounds, canvasBounds) {
|
|
81
|
+
if (!this.overlay)
|
|
82
|
+
return;
|
|
83
|
+
const canvas = this.container.querySelector("canvas");
|
|
84
|
+
const scaleX = canvasBounds.width / canvas.width;
|
|
85
|
+
const scaleY = canvasBounds.height / canvas.height;
|
|
86
|
+
const left = bounds.x * scaleX;
|
|
87
|
+
const top = bounds.y * scaleY;
|
|
88
|
+
const width = bounds.width * scaleX;
|
|
89
|
+
const height = bounds.height * scaleY;
|
|
90
|
+
Object.assign(this.overlay.style, {
|
|
91
|
+
position: "absolute",
|
|
92
|
+
left: `${left}px`,
|
|
93
|
+
top: `${top}px`,
|
|
94
|
+
width: `${width}px`,
|
|
95
|
+
height: `${height}px`
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
onInput(e) {
|
|
99
|
+
if (!this.overlay || !this.onChangeCallback)
|
|
100
|
+
return;
|
|
101
|
+
const value = this.overlay.value;
|
|
102
|
+
this.onChangeCallback(value);
|
|
103
|
+
}
|
|
104
|
+
onBlur() {
|
|
105
|
+
this.hideInput();
|
|
106
|
+
}
|
|
107
|
+
onKeyDown(e) {
|
|
108
|
+
if (!this.overlay)
|
|
109
|
+
return;
|
|
110
|
+
if (e.key === "Enter" && this.overlay instanceof HTMLInputElement) {
|
|
111
|
+
e.preventDefault();
|
|
112
|
+
this.overlay.blur();
|
|
113
|
+
}
|
|
114
|
+
if (e.key === "Escape") {
|
|
115
|
+
e.preventDefault();
|
|
116
|
+
this.overlay.blur();
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
isShown() {
|
|
120
|
+
return this.overlay !== null;
|
|
121
|
+
}
|
|
122
|
+
getFocusedNode() {
|
|
123
|
+
return this.focusedNode;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
export {
|
|
127
|
+
InputOverlay
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
export { InputOverlay };
|
|
131
|
+
|
|
132
|
+
//# debugId=222277311BC256D364756E2164756E21
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/canvas/input.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"/**\n * Input Overlay System\n *\n * Handle text input using DOM overlay elements\n */\n\nimport type { VirtualNode, Rectangle } from \"./types.js\";\nimport { getAbsoluteBounds } from \"./utils.js\";\n\n/**\n * Input Overlay Manager\n */\nexport class InputOverlay {\n private container: HTMLElement;\n private overlay: HTMLInputElement | HTMLTextAreaElement | null = null;\n private focusedNode: VirtualNode | null = null;\n private onChangeCallback: ((value: string) => void) | null = null;\n\n constructor(container: HTMLElement | null) {\n this.container = container || ({} as HTMLElement);\n }\n\n /**\n * Show input overlay for a node\n */\n showInput(\n node: VirtualNode,\n canvasBounds: DOMRect,\n onChange: (value: string) => void\n ): void {\n // Skip if document is not available (non-browser environment)\n if (typeof document === \"undefined\") return;\n\n this.hideInput();\n\n const bounds = getAbsoluteBounds(node);\n if (!bounds) return;\n\n const isMultiline = node.type === \"textarea\";\n this.overlay = isMultiline\n ? document.createElement(\"textarea\")\n : document.createElement(\"input\");\n\n // Style overlay\n this.styleOverlay(node, bounds, canvasBounds);\n\n // Set initial value\n const value = node.props.value || \"\";\n this.overlay.value = value;\n\n // Setup event handlers\n this.onChangeCallback = onChange;\n this.overlay.addEventListener(\"input\", this.onInput.bind(this));\n this.overlay.addEventListener(\"blur\", this.onBlur.bind(this));\n this.overlay.addEventListener(\"keydown\", this.onKeyDown.bind(this) as EventListener);\n\n // Add to DOM and focus\n this.container.appendChild(this.overlay);\n this.overlay.focus();\n\n this.focusedNode = node;\n }\n\n /**\n * Hide input overlay\n */\n hideInput(): void {\n if (this.overlay) {\n this.overlay.remove();\n this.overlay = null;\n }\n this.focusedNode = null;\n this.onChangeCallback = null;\n }\n\n /**\n * Update overlay position\n */\n updatePosition(node: VirtualNode, canvasBounds: DOMRect): void {\n if (!this.overlay || node !== this.focusedNode) return;\n\n const bounds = getAbsoluteBounds(node);\n if (!bounds) return;\n\n this.positionOverlay(bounds, canvasBounds);\n }\n\n /**\n * Style overlay to match canvas node\n */\n private styleOverlay(\n node: VirtualNode,\n bounds: Rectangle,\n canvasBounds: DOMRect\n ): void {\n if (!this.overlay) return;\n\n const props = node.props;\n\n // Position\n this.positionOverlay(bounds, canvasBounds);\n\n // Font and text styling\n const fontSize = parseFloat(props.fontSize) || 16;\n const fontWeight = props.fontWeight || \"normal\";\n const fontFamily = props.fontFamily || \"system-ui, sans-serif\";\n const color = props.color || \"#000000\";\n\n Object.assign(this.overlay.style, {\n fontSize: `${fontSize}px`,\n fontWeight: fontWeight,\n fontFamily: fontFamily,\n color: color,\n border: \"none\",\n outline: \"2px solid #007bff\",\n backgroundColor: props.backgroundColor || \"#ffffff\",\n padding: `${props.padding || 8}px`,\n borderRadius: `${props.borderRadius || 4}px`,\n boxSizing: \"border-box\",\n resize: \"none\",\n });\n\n // Placeholder\n if (props.placeholder) {\n this.overlay.placeholder = props.placeholder;\n }\n\n // Input type\n if (this.overlay instanceof HTMLInputElement && props.type) {\n this.overlay.type = props.type;\n }\n }\n\n /**\n * Position overlay over canvas node\n */\n private positionOverlay(bounds: Rectangle, canvasBounds: DOMRect): void {\n if (!this.overlay) return;\n\n // Calculate scale factor between canvas and display\n const canvas = this.container.querySelector(\"canvas\") as HTMLCanvasElement;\n const scaleX = canvasBounds.width / canvas.width;\n const scaleY = canvasBounds.height / canvas.height;\n\n const left = bounds.x * scaleX;\n const top = bounds.y * scaleY;\n const width = bounds.width * scaleX;\n const height = bounds.height * scaleY;\n\n Object.assign(this.overlay.style, {\n position: \"absolute\",\n left: `${left}px`,\n top: `${top}px`,\n width: `${width}px`,\n height: `${height}px`,\n });\n }\n\n /**\n * Handle input event\n */\n private onInput(e: Event): void {\n if (!this.overlay || !this.onChangeCallback) return;\n\n const value = this.overlay.value;\n this.onChangeCallback(value);\n }\n\n /**\n * Handle blur event\n */\n private onBlur(): void {\n // Hide overlay when focus is lost\n this.hideInput();\n }\n\n /**\n * Handle keyboard events\n */\n private onKeyDown(e: KeyboardEvent): void {\n if (!this.overlay) return;\n\n // Enter key submits (unless multiline)\n if (e.key === \"Enter\" && this.overlay instanceof HTMLInputElement) {\n e.preventDefault();\n this.overlay.blur();\n }\n\n // Escape cancels\n if (e.key === \"Escape\") {\n e.preventDefault();\n this.overlay.blur();\n }\n }\n\n /**\n * Check if input is currently shown\n */\n isShown(): boolean {\n return this.overlay !== null;\n }\n\n /**\n * Get current focused node\n */\n getFocusedNode(): VirtualNode | null {\n return this.focusedNode;\n }\n}\n\n"
|
|
6
|
+
],
|
|
7
|
+
"mappings": "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",
|
|
8
|
+
"debugId": "222277311BC256D364756E2164756E21",
|
|
9
|
+
"names": []
|
|
10
|
+
}
|