@geometra/core 0.1.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +42 -0
- package/dist/a11y.d.ts +19 -0
- package/dist/a11y.d.ts.map +1 -0
- package/dist/a11y.js +78 -0
- package/dist/a11y.js.map +1 -0
- package/dist/animation.d.ts +29 -0
- package/dist/animation.d.ts.map +1 -0
- package/dist/animation.js +102 -0
- package/dist/animation.js.map +1 -0
- package/dist/app.d.ts +17 -2
- package/dist/app.d.ts.map +1 -1
- package/dist/app.js +41 -9
- package/dist/app.js.map +1 -1
- package/dist/elements.d.ts +13 -1
- package/dist/elements.d.ts.map +1 -1
- package/dist/elements.js +21 -3
- package/dist/elements.js.map +1 -1
- package/dist/focus.d.ts +19 -0
- package/dist/focus.d.ts.map +1 -0
- package/dist/focus.js +61 -0
- package/dist/focus.js.map +1 -0
- package/dist/fonts.d.ts +14 -0
- package/dist/fonts.d.ts.map +1 -0
- package/dist/fonts.js +67 -0
- package/dist/fonts.js.map +1 -0
- package/dist/hit-test.d.ts +13 -2
- package/dist/hit-test.d.ts.map +1 -1
- package/dist/hit-test.js +74 -7
- package/dist/hit-test.js.map +1 -1
- package/dist/index.d.ts +20 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +19 -2
- package/dist/index.js.map +1 -1
- package/dist/keyboard.d.ts +10 -0
- package/dist/keyboard.d.ts.map +1 -0
- package/dist/keyboard.js +49 -0
- package/dist/keyboard.js.map +1 -0
- package/dist/selection.d.ts +46 -0
- package/dist/selection.d.ts.map +1 -0
- package/dist/selection.js +94 -0
- package/dist/selection.js.map +1 -0
- package/dist/seo.d.ts +29 -0
- package/dist/seo.d.ts.map +1 -0
- package/dist/seo.js +109 -0
- package/dist/seo.js.map +1 -0
- package/dist/text-input-history.d.ts +15 -0
- package/dist/text-input-history.d.ts.map +1 -0
- package/dist/text-input-history.js +62 -0
- package/dist/text-input-history.js.map +1 -0
- package/dist/text-input.d.ts +42 -0
- package/dist/text-input.d.ts.map +1 -0
- package/dist/text-input.js +249 -0
- package/dist/text-input.js.map +1 -0
- package/dist/tree.d.ts.map +1 -1
- package/dist/tree.js +9 -3
- package/dist/tree.js.map +1 -1
- package/dist/types.d.ts +81 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +3 -3
package/dist/fonts.js
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
const GENERIC_FAMILIES = new Set([
|
|
2
|
+
'serif',
|
|
3
|
+
'sans-serif',
|
|
4
|
+
'monospace',
|
|
5
|
+
'cursive',
|
|
6
|
+
'fantasy',
|
|
7
|
+
'system-ui',
|
|
8
|
+
'ui-sans-serif',
|
|
9
|
+
'ui-serif',
|
|
10
|
+
'ui-monospace',
|
|
11
|
+
'emoji',
|
|
12
|
+
]);
|
|
13
|
+
/**
|
|
14
|
+
* Extract custom font family names from a CSS `font` shorthand (e.g. `600 14px Inter`).
|
|
15
|
+
* Drops generic fallbacks like `sans-serif`. Best-effort parsing for common patterns.
|
|
16
|
+
*/
|
|
17
|
+
export function extractFontFamiliesFromCSSFont(font) {
|
|
18
|
+
const trimmed = font.trim();
|
|
19
|
+
const m = trimmed.match(/\b(\d+(?:\.\d+)?(?:px|em|rem))(?:\/\s*[\d.]+(?:px|em|rem)?)?\s+(.+)$/i);
|
|
20
|
+
const tail = m ? m[2] : trimmed;
|
|
21
|
+
return tail
|
|
22
|
+
.split(',')
|
|
23
|
+
.map(s => s.trim().replace(/^["']|["']$/g, ''))
|
|
24
|
+
.filter(f => f.length > 0 && !GENERIC_FAMILIES.has(f.toLowerCase()));
|
|
25
|
+
}
|
|
26
|
+
/** Collect unique font families referenced by text nodes in a UI tree. */
|
|
27
|
+
export function collectFontFamiliesFromTree(root) {
|
|
28
|
+
const out = new Set();
|
|
29
|
+
function walk(el) {
|
|
30
|
+
if (el.kind === 'text') {
|
|
31
|
+
for (const f of extractFontFamiliesFromCSSFont(el.props.font)) {
|
|
32
|
+
out.add(f);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
else if (el.kind === 'box') {
|
|
36
|
+
for (const c of el.children)
|
|
37
|
+
walk(c);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
walk(root);
|
|
41
|
+
return [...out];
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Wait for web fonts used by the app. Browser only; no-op on server.
|
|
45
|
+
* Uses `document.fonts.load` per family; timeouts are swallowed so startup never hard-fails.
|
|
46
|
+
*/
|
|
47
|
+
export async function waitForFonts(families, timeoutMs = 10_000) {
|
|
48
|
+
if (typeof document === 'undefined' || families.length === 0)
|
|
49
|
+
return;
|
|
50
|
+
const api = document.fonts;
|
|
51
|
+
if (!api?.load)
|
|
52
|
+
return;
|
|
53
|
+
const unique = [...new Set(families)];
|
|
54
|
+
const work = Promise.all(unique.map(f => api.load(`16px ${f}`).catch(() => undefined))).then(() => api.ready);
|
|
55
|
+
try {
|
|
56
|
+
await Promise.race([
|
|
57
|
+
work,
|
|
58
|
+
new Promise((_, reject) => {
|
|
59
|
+
setTimeout(() => reject(new Error('Font load timeout')), timeoutMs);
|
|
60
|
+
}),
|
|
61
|
+
]);
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
/* best-effort */
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=fonts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fonts.js","sourceRoot":"","sources":["../src/fonts.ts"],"names":[],"mappings":"AAEA,MAAM,gBAAgB,GAAG,IAAI,GAAG,CAAC;IAC/B,OAAO;IACP,YAAY;IACZ,WAAW;IACX,SAAS;IACT,SAAS;IACT,WAAW;IACX,eAAe;IACf,UAAU;IACV,cAAc;IACd,OAAO;CACR,CAAC,CAAA;AAEF;;;GAGG;AACH,MAAM,UAAU,8BAA8B,CAAC,IAAY;IACzD,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAA;IAC3B,MAAM,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,uEAAuE,CAAC,CAAA;IAChG,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC,OAAO,CAAA;IAChC,OAAO,IAAI;SACR,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC;SAC9C,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAA;AACxE,CAAC;AAED,0EAA0E;AAC1E,MAAM,UAAU,2BAA2B,CAAC,IAAe;IACzD,MAAM,GAAG,GAAG,IAAI,GAAG,EAAU,CAAA;IAC7B,SAAS,IAAI,CAAC,EAAa;QACzB,IAAI,EAAE,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YACvB,KAAK,MAAM,CAAC,IAAI,8BAA8B,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC9D,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;YACZ,CAAC;QACH,CAAC;aAAM,IAAI,EAAE,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;YAC7B,KAAK,MAAM,CAAC,IAAI,EAAE,CAAC,QAAQ;gBAAE,IAAI,CAAC,CAAC,CAAC,CAAA;QACtC,CAAC;IACH,CAAC;IACD,IAAI,CAAC,IAAI,CAAC,CAAA;IACV,OAAO,CAAC,GAAG,GAAG,CAAC,CAAA;AACjB,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,QAAkB,EAAE,SAAS,GAAG,MAAM;IACvE,IAAI,OAAO,QAAQ,KAAK,WAAW,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAM;IACpE,MAAM,GAAG,GAAG,QAAQ,CAAC,KAAK,CAAA;IAC1B,IAAI,CAAC,GAAG,EAAE,IAAI;QAAE,OAAM;IAEtB,MAAM,MAAM,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAA;IACrC,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CAChG,GAAG,CAAC,KAAK,CACV,CAAA;IAED,IAAI,CAAC;QACH,MAAM,OAAO,CAAC,IAAI,CAAC;YACjB,IAAI;YACJ,IAAI,OAAO,CAAO,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE;gBAC9B,UAAU,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC,EAAE,SAAS,CAAC,CAAA;YACrE,CAAC,CAAC;SACH,CAAC,CAAA;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,iBAAiB;IACnB,CAAC;AACH,CAAC"}
|
package/dist/hit-test.d.ts
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
import type { ComputedLayout } from 'textura';
|
|
2
|
-
import type { UIElement, EventHandlers } from './types.js';
|
|
2
|
+
import type { UIElement, BoxElement, EventHandlers } from './types.js';
|
|
3
|
+
/** Result of routing a pointer/keyboard-style hit to handlers. */
|
|
4
|
+
export interface HitDispatchResult {
|
|
5
|
+
handled: boolean;
|
|
6
|
+
/** Set when a focusable box handled `onClick` (for keyboard focus). */
|
|
7
|
+
focusTarget?: {
|
|
8
|
+
element: BoxElement;
|
|
9
|
+
layout: ComputedLayout;
|
|
10
|
+
};
|
|
11
|
+
}
|
|
3
12
|
/** Dispatch an event at (x, y) against the element tree. Returns true if any handler fired. */
|
|
4
|
-
export declare function dispatchHit(element: UIElement, layout: ComputedLayout, eventType: keyof EventHandlers, x: number, y: number):
|
|
13
|
+
export declare function dispatchHit(element: UIElement, layout: ComputedLayout, eventType: keyof EventHandlers, x: number, y: number, extra?: Record<string, unknown>): HitDispatchResult;
|
|
14
|
+
/** Get the cursor style at a given point by walking the tree. Returns the deepest element's cursor prop. */
|
|
15
|
+
export declare function getCursorAtPoint(element: UIElement, layout: ComputedLayout, x: number, y: number, offsetX?: number, offsetY?: number): string | null;
|
|
5
16
|
//# sourceMappingURL=hit-test.d.ts.map
|
package/dist/hit-test.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hit-test.d.ts","sourceRoot":"","sources":["../src/hit-test.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAC7C,OAAO,KAAK,EAAE,SAAS,
|
|
1
|
+
{"version":3,"file":"hit-test.d.ts","sourceRoot":"","sources":["../src/hit-test.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAC7C,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,aAAa,EAAY,MAAM,YAAY,CAAA;AA8BhF,kEAAkE;AAClE,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,OAAO,CAAA;IAChB,uEAAuE;IACvE,WAAW,CAAC,EAAE;QAAE,OAAO,EAAE,UAAU,CAAC;QAAC,MAAM,EAAE,cAAc,CAAA;KAAE,CAAA;CAC9D;AAqDD,+FAA+F;AAC/F,wBAAgB,WAAW,CACzB,OAAO,EAAE,SAAS,EAClB,MAAM,EAAE,cAAc,EACtB,SAAS,EAAE,MAAM,aAAa,EAC9B,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,iBAAiB,CAwBnB;AAED,4GAA4G;AAC5G,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,SAAS,EAClB,MAAM,EAAE,cAAc,EACtB,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,OAAO,SAAI,EACX,OAAO,SAAI,GACV,MAAM,GAAG,IAAI,CA+Bf"}
|
package/dist/hit-test.js
CHANGED
|
@@ -1,7 +1,37 @@
|
|
|
1
|
+
const zIndexOrderCache = new WeakMap();
|
|
2
|
+
function zIndexOf(el) {
|
|
3
|
+
return el.props.zIndex ?? 0;
|
|
4
|
+
}
|
|
5
|
+
function getChildrenByZDesc(boxEl) {
|
|
6
|
+
const signature = boxEl.children.map((child, i) => `${i}:${zIndexOf(child)}`).join('|');
|
|
7
|
+
const cached = zIndexOrderCache.get(boxEl);
|
|
8
|
+
if (cached && cached.signature === signature) {
|
|
9
|
+
return cached.desc;
|
|
10
|
+
}
|
|
11
|
+
const desc = boxEl.children.map((_, i) => i).sort((a, b) => zIndexOf(boxEl.children[b]) - zIndexOf(boxEl.children[a]));
|
|
12
|
+
zIndexOrderCache.set(boxEl, { signature, desc });
|
|
13
|
+
return desc;
|
|
14
|
+
}
|
|
1
15
|
/** Walk the element tree + computed layout in parallel to find hit targets at (x, y). */
|
|
2
16
|
function collectHits(element, layout, x, y, offsetX, offsetY, results) {
|
|
3
17
|
const absX = offsetX + layout.x;
|
|
4
18
|
const absY = offsetY + layout.y;
|
|
19
|
+
// Apply scroll offset for scroll containers
|
|
20
|
+
let childOffsetX = absX;
|
|
21
|
+
let childOffsetY = absY;
|
|
22
|
+
if (element.kind === 'box') {
|
|
23
|
+
const { overflow, scrollX, scrollY } = element.props;
|
|
24
|
+
if (overflow === 'hidden' || overflow === 'scroll') {
|
|
25
|
+
// Point must be inside the box to hit children
|
|
26
|
+
if (x < absX || x > absX + layout.width || y < absY || y > absY + layout.height) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
if (scrollX)
|
|
31
|
+
childOffsetX -= scrollX;
|
|
32
|
+
if (scrollY)
|
|
33
|
+
childOffsetY -= scrollY;
|
|
34
|
+
}
|
|
5
35
|
const inside = x >= absX &&
|
|
6
36
|
x <= absX + layout.width &&
|
|
7
37
|
y >= absY &&
|
|
@@ -11,18 +41,18 @@ function collectHits(element, layout, x, y, offsetX, offsetY, results) {
|
|
|
11
41
|
if (element.kind === 'box') {
|
|
12
42
|
const boxEl = element;
|
|
13
43
|
if (boxEl.handlers) {
|
|
14
|
-
results.push({ layout, handlers: boxEl.handlers });
|
|
44
|
+
results.push({ layout, handlers: boxEl.handlers, element: boxEl });
|
|
15
45
|
}
|
|
16
|
-
for (
|
|
46
|
+
for (const i of getChildrenByZDesc(boxEl)) {
|
|
17
47
|
const childLayout = layout.children[i];
|
|
18
48
|
if (childLayout) {
|
|
19
|
-
collectHits(boxEl.children[i], childLayout, x, y,
|
|
49
|
+
collectHits(boxEl.children[i], childLayout, x, y, childOffsetX, childOffsetY, results);
|
|
20
50
|
}
|
|
21
51
|
}
|
|
22
52
|
}
|
|
23
53
|
}
|
|
24
54
|
/** Dispatch an event at (x, y) against the element tree. Returns true if any handler fired. */
|
|
25
|
-
export function dispatchHit(element, layout, eventType, x, y) {
|
|
55
|
+
export function dispatchHit(element, layout, eventType, x, y, extra) {
|
|
26
56
|
const hits = [];
|
|
27
57
|
collectHits(element, layout, x, y, 0, 0, hits);
|
|
28
58
|
// Deepest hit first (last in list = most nested)
|
|
@@ -30,11 +60,48 @@ export function dispatchHit(element, layout, eventType, x, y) {
|
|
|
30
60
|
const hit = hits[i];
|
|
31
61
|
const handler = hit.handlers[eventType];
|
|
32
62
|
if (handler) {
|
|
33
|
-
const event = { x, y, target: hit.layout };
|
|
63
|
+
const event = { x, y, target: hit.layout, ...extra };
|
|
34
64
|
handler(event);
|
|
35
|
-
|
|
65
|
+
const focusable = !!(hit.handlers.onClick ||
|
|
66
|
+
hit.handlers.onKeyDown ||
|
|
67
|
+
hit.handlers.onKeyUp);
|
|
68
|
+
const focusTarget = eventType === 'onClick' && focusable
|
|
69
|
+
? { element: hit.element, layout: hit.layout }
|
|
70
|
+
: undefined;
|
|
71
|
+
return { handled: true, focusTarget };
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return { handled: false };
|
|
75
|
+
}
|
|
76
|
+
/** Get the cursor style at a given point by walking the tree. Returns the deepest element's cursor prop. */
|
|
77
|
+
export function getCursorAtPoint(element, layout, x, y, offsetX = 0, offsetY = 0) {
|
|
78
|
+
const absX = offsetX + layout.x;
|
|
79
|
+
const absY = offsetY + layout.y;
|
|
80
|
+
const inside = x >= absX && x <= absX + layout.width &&
|
|
81
|
+
y >= absY && y <= absY + layout.height;
|
|
82
|
+
if (!inside)
|
|
83
|
+
return null;
|
|
84
|
+
// Check children (deepest first via recursion)
|
|
85
|
+
if (element.kind === 'box') {
|
|
86
|
+
let childOffX = absX;
|
|
87
|
+
let childOffY = absY;
|
|
88
|
+
if (element.props.scrollX)
|
|
89
|
+
childOffX -= element.props.scrollX;
|
|
90
|
+
if (element.props.scrollY)
|
|
91
|
+
childOffY -= element.props.scrollY;
|
|
92
|
+
const indices = getChildrenByZDesc(element);
|
|
93
|
+
for (let ii = 0; ii < indices.length; ii++) {
|
|
94
|
+
const i = indices[ii];
|
|
95
|
+
const childLayout = layout.children[i];
|
|
96
|
+
if (childLayout) {
|
|
97
|
+
const childCursor = getCursorAtPoint(element.children[i], childLayout, x, y, childOffX, childOffY);
|
|
98
|
+
if (childCursor)
|
|
99
|
+
return childCursor;
|
|
100
|
+
}
|
|
36
101
|
}
|
|
37
102
|
}
|
|
38
|
-
|
|
103
|
+
// Return this element's cursor
|
|
104
|
+
const cursor = element.props.cursor;
|
|
105
|
+
return cursor ?? null;
|
|
39
106
|
}
|
|
40
107
|
//# sourceMappingURL=hit-test.js.map
|
package/dist/hit-test.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hit-test.js","sourceRoot":"","sources":["../src/hit-test.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"hit-test.js","sourceRoot":"","sources":["../src/hit-test.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,26 @@
|
|
|
1
1
|
export { signal, computed, effect, batch } from './signals.js';
|
|
2
2
|
export type { Signal, Computed } from './signals.js';
|
|
3
|
-
export { box, text } from './elements.js';
|
|
3
|
+
export { box, text, image } from './elements.js';
|
|
4
4
|
export { createApp } from './app.js';
|
|
5
5
|
export type { App, AppOptions } from './app.js';
|
|
6
6
|
export { toLayoutTree } from './tree.js';
|
|
7
|
-
export { dispatchHit } from './hit-test.js';
|
|
8
|
-
export type {
|
|
7
|
+
export { dispatchHit, getCursorAtPoint } from './hit-test.js';
|
|
8
|
+
export type { HitDispatchResult } from './hit-test.js';
|
|
9
|
+
export { extractFontFamiliesFromCSSFont, collectFontFamiliesFromTree, waitForFonts, } from './fonts.js';
|
|
10
|
+
export { focusedElement, setFocus, clearFocus, focusNext, focusPrev } from './focus.js';
|
|
11
|
+
export { dispatchKeyboardEvent } from './keyboard.js';
|
|
12
|
+
export { dispatchCompositionEvent } from './keyboard.js';
|
|
13
|
+
export { collectTextNodes, getSelectedText, hitTestText } from './selection.js';
|
|
14
|
+
export type { TextNodeInfo, TextLineInfo, SelectionRange } from './selection.js';
|
|
15
|
+
export { transition, spring, easing, animationLoop } from './animation.js';
|
|
16
|
+
export type { EasingFn } from './animation.js';
|
|
17
|
+
export { toSemanticHTML } from './seo.js';
|
|
18
|
+
export type { SemanticHTMLOptions } from './seo.js';
|
|
19
|
+
export { toAccessibilityTree } from './a11y.js';
|
|
20
|
+
export type { AccessibilityNode, AccessibilityBounds } from './a11y.js';
|
|
21
|
+
export { isCollapsedSelection, getInputSelectionText, replaceInputSelection, insertInputText, backspaceInput, deleteInput, moveInputCaret, getInputCaretGeometry, } from './text-input.js';
|
|
22
|
+
export type { TextInputState, TextInputEditResult, CaretGeometry } from './text-input.js';
|
|
23
|
+
export { createTextInputHistory, pushTextInputHistory, undoTextInputHistory, redoTextInputHistory, } from './text-input-history.js';
|
|
24
|
+
export type { TextInputHistoryState } from './text-input-history.js';
|
|
25
|
+
export type { UIElement, BoxElement, TextElement, ImageElement, StyleProps, SemanticProps, EventHandlers, HitEvent, KeyboardHitEvent, CompositionHitEvent, Component, Renderer, } from './types.js';
|
|
9
26
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,cAAc,CAAA;AAC9D,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAGpD,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,eAAe,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,cAAc,CAAA;AAC9D,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAGpD,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,eAAe,CAAA;AAGhD,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AACpC,YAAY,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAG/C,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAGxC,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAC7D,YAAY,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAA;AAGtD,OAAO,EACL,8BAA8B,EAC9B,2BAA2B,EAC3B,YAAY,GACb,MAAM,YAAY,CAAA;AAGnB,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,UAAU,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AACvF,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAA;AACrD,OAAO,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAA;AAGxD,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAC/E,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAGhF,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAC1E,YAAY,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAG9C,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AACzC,YAAY,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAA;AAGnD,OAAO,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAA;AAC/C,YAAY,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAA;AAGvE,OAAO,EACL,oBAAoB,EACpB,qBAAqB,EACrB,qBAAqB,EACrB,eAAe,EACf,cAAc,EACd,WAAW,EACX,cAAc,EACd,qBAAqB,GACtB,MAAM,iBAAiB,CAAA;AACxB,YAAY,EAAE,cAAc,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AACzF,OAAO,EACL,sBAAsB,EACtB,oBAAoB,EACpB,oBAAoB,EACpB,oBAAoB,GACrB,MAAM,yBAAyB,CAAA;AAChC,YAAY,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAA;AAGpE,YAAY,EACV,SAAS,EACT,UAAU,EACV,WAAW,EACX,YAAY,EACZ,UAAU,EACV,aAAa,EACb,aAAa,EACb,QAAQ,EACR,gBAAgB,EAChB,mBAAmB,EACnB,SAAS,EACT,QAAQ,GACT,MAAM,YAAY,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -1,11 +1,28 @@
|
|
|
1
1
|
// Reactivity
|
|
2
2
|
export { signal, computed, effect, batch } from './signals.js';
|
|
3
3
|
// Element constructors
|
|
4
|
-
export { box, text } from './elements.js';
|
|
4
|
+
export { box, text, image } from './elements.js';
|
|
5
5
|
// App mount
|
|
6
6
|
export { createApp } from './app.js';
|
|
7
7
|
// Tree conversion
|
|
8
8
|
export { toLayoutTree } from './tree.js';
|
|
9
9
|
// Hit testing
|
|
10
|
-
export { dispatchHit } from './hit-test.js';
|
|
10
|
+
export { dispatchHit, getCursorAtPoint } from './hit-test.js';
|
|
11
|
+
// Web fonts (browser)
|
|
12
|
+
export { extractFontFamiliesFromCSSFont, collectFontFamiliesFromTree, waitForFonts, } from './fonts.js';
|
|
13
|
+
// Focus management
|
|
14
|
+
export { focusedElement, setFocus, clearFocus, focusNext, focusPrev } from './focus.js';
|
|
15
|
+
export { dispatchKeyboardEvent } from './keyboard.js';
|
|
16
|
+
export { dispatchCompositionEvent } from './keyboard.js';
|
|
17
|
+
// Text selection
|
|
18
|
+
export { collectTextNodes, getSelectedText, hitTestText } from './selection.js';
|
|
19
|
+
// Animation
|
|
20
|
+
export { transition, spring, easing, animationLoop } from './animation.js';
|
|
21
|
+
// SEO
|
|
22
|
+
export { toSemanticHTML } from './seo.js';
|
|
23
|
+
// Runtime accessibility
|
|
24
|
+
export { toAccessibilityTree } from './a11y.js';
|
|
25
|
+
// Text input foundation
|
|
26
|
+
export { isCollapsedSelection, getInputSelectionText, replaceInputSelection, insertInputText, backspaceInput, deleteInput, moveInputCaret, getInputCaretGeometry, } from './text-input.js';
|
|
27
|
+
export { createTextInputHistory, pushTextInputHistory, undoTextInputHistory, redoTextInputHistory, } from './text-input-history.js';
|
|
11
28
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,aAAa;AACb,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,cAAc,CAAA;AAG9D,uBAAuB;AACvB,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,eAAe,CAAA;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,aAAa;AACb,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,cAAc,CAAA;AAG9D,uBAAuB;AACvB,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,eAAe,CAAA;AAEhD,YAAY;AACZ,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AAGpC,kBAAkB;AAClB,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAExC,cAAc;AACd,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAG7D,sBAAsB;AACtB,OAAO,EACL,8BAA8B,EAC9B,2BAA2B,EAC3B,YAAY,GACb,MAAM,YAAY,CAAA;AAEnB,mBAAmB;AACnB,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,UAAU,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AACvF,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAA;AACrD,OAAO,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAA;AAExD,iBAAiB;AACjB,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAG/E,YAAY;AACZ,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAG1E,MAAM;AACN,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AAGzC,wBAAwB;AACxB,OAAO,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAA;AAG/C,wBAAwB;AACxB,OAAO,EACL,oBAAoB,EACpB,qBAAqB,EACrB,qBAAqB,EACrB,eAAe,EACf,cAAc,EACd,WAAW,EACX,cAAc,EACd,qBAAqB,GACtB,MAAM,iBAAiB,CAAA;AAExB,OAAO,EACL,sBAAsB,EACtB,oBAAoB,EACpB,oBAAoB,EACpB,oBAAoB,GACrB,MAAM,yBAAyB,CAAA"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ComputedLayout } from 'textura';
|
|
2
|
+
import type { UIElement, KeyboardHitEvent, CompositionHitEvent } from './types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Dispatch keyboard events to the focused element.
|
|
5
|
+
* Also handles Tab/Shift+Tab focus traversal.
|
|
6
|
+
*/
|
|
7
|
+
export declare function dispatchKeyboardEvent(tree: UIElement, layout: ComputedLayout, eventType: 'onKeyDown' | 'onKeyUp', partialEvent: Omit<KeyboardHitEvent, 'target'>): boolean;
|
|
8
|
+
/** Dispatch IME composition events to the focused element. */
|
|
9
|
+
export declare function dispatchCompositionEvent(_tree: UIElement, _layout: ComputedLayout, eventType: 'onCompositionStart' | 'onCompositionUpdate' | 'onCompositionEnd', partialEvent: Omit<CompositionHitEvent, 'target'>): boolean;
|
|
10
|
+
//# sourceMappingURL=keyboard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keyboard.d.ts","sourceRoot":"","sources":["../src/keyboard.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAC7C,OAAO,KAAK,EAAE,SAAS,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAA;AAGlF;;;GAGG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,SAAS,EACf,MAAM,EAAE,cAAc,EACtB,SAAS,EAAE,WAAW,GAAG,SAAS,EAClC,YAAY,EAAE,IAAI,CAAC,gBAAgB,EAAE,QAAQ,CAAC,GAC7C,OAAO,CA+BT;AAED,8DAA8D;AAC9D,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,SAAS,EAChB,OAAO,EAAE,cAAc,EACvB,SAAS,EAAE,oBAAoB,GAAG,qBAAqB,GAAG,kBAAkB,EAC5E,YAAY,EAAE,IAAI,CAAC,mBAAmB,EAAE,QAAQ,CAAC,GAChD,OAAO,CAQT"}
|
package/dist/keyboard.js
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { focusedElement, focusNext, focusPrev } from './focus.js';
|
|
2
|
+
/**
|
|
3
|
+
* Dispatch keyboard events to the focused element.
|
|
4
|
+
* Also handles Tab/Shift+Tab focus traversal.
|
|
5
|
+
*/
|
|
6
|
+
export function dispatchKeyboardEvent(tree, layout, eventType, partialEvent) {
|
|
7
|
+
const focused = focusedElement.peek();
|
|
8
|
+
if (!focused) {
|
|
9
|
+
if (partialEvent.key === 'Tab') {
|
|
10
|
+
if (partialEvent.shiftKey) {
|
|
11
|
+
focusPrev(tree, layout);
|
|
12
|
+
}
|
|
13
|
+
else {
|
|
14
|
+
focusNext(tree, layout);
|
|
15
|
+
}
|
|
16
|
+
return true;
|
|
17
|
+
}
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
const handler = focused.element.handlers?.[eventType];
|
|
21
|
+
if (handler) {
|
|
22
|
+
const event = { ...partialEvent, target: focused.layout };
|
|
23
|
+
handler(event);
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
if (partialEvent.key === 'Tab') {
|
|
27
|
+
if (partialEvent.shiftKey) {
|
|
28
|
+
focusPrev(tree, layout);
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
focusNext(tree, layout);
|
|
32
|
+
}
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
/** Dispatch IME composition events to the focused element. */
|
|
38
|
+
export function dispatchCompositionEvent(_tree, _layout, eventType, partialEvent) {
|
|
39
|
+
const focused = focusedElement.peek();
|
|
40
|
+
if (!focused)
|
|
41
|
+
return false;
|
|
42
|
+
const handler = focused.element.handlers?.[eventType];
|
|
43
|
+
if (!handler)
|
|
44
|
+
return false;
|
|
45
|
+
const event = { ...partialEvent, target: focused.layout };
|
|
46
|
+
handler(event);
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=keyboard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keyboard.js","sourceRoot":"","sources":["../src/keyboard.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAEjE;;;GAGG;AACH,MAAM,UAAU,qBAAqB,CACnC,IAAe,EACf,MAAsB,EACtB,SAAkC,EAClC,YAA8C;IAE9C,MAAM,OAAO,GAAG,cAAc,CAAC,IAAI,EAAE,CAAA;IACrC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,IAAI,YAAY,CAAC,GAAG,KAAK,KAAK,EAAE,CAAC;YAC/B,IAAI,YAAY,CAAC,QAAQ,EAAE,CAAC;gBAC1B,SAAS,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;YACzB,CAAC;iBAAM,CAAC;gBACN,SAAS,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;YACzB,CAAC;YACD,OAAO,IAAI,CAAA;QACb,CAAC;QACD,OAAO,KAAK,CAAA;IACd,CAAC;IAED,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,SAAS,CAAC,CAAA;IACrD,IAAI,OAAO,EAAE,CAAC;QACZ,MAAM,KAAK,GAAqB,EAAE,GAAG,YAAY,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAA;QAC3E,OAAO,CAAC,KAAK,CAAC,CAAA;QACd,OAAO,IAAI,CAAA;IACb,CAAC;IAED,IAAI,YAAY,CAAC,GAAG,KAAK,KAAK,EAAE,CAAC;QAC/B,IAAI,YAAY,CAAC,QAAQ,EAAE,CAAC;YAC1B,SAAS,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;QACzB,CAAC;aAAM,CAAC;YACN,SAAS,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;QACzB,CAAC;QACD,OAAO,IAAI,CAAA;IACb,CAAC;IAED,OAAO,KAAK,CAAA;AACd,CAAC;AAED,8DAA8D;AAC9D,MAAM,UAAU,wBAAwB,CACtC,KAAgB,EAChB,OAAuB,EACvB,SAA4E,EAC5E,YAAiD;IAEjD,MAAM,OAAO,GAAG,cAAc,CAAC,IAAI,EAAE,CAAA;IACrC,IAAI,CAAC,OAAO;QAAE,OAAO,KAAK,CAAA;IAC1B,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,SAAS,CAAC,CAAA;IACrD,IAAI,CAAC,OAAO;QAAE,OAAO,KAAK,CAAA;IAC1B,MAAM,KAAK,GAAwB,EAAE,GAAG,YAAY,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAA;IAC9E,OAAO,CAAC,KAAK,CAAC,CAAA;IACd,OAAO,IAAI,CAAA;AACb,CAAC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { ComputedLayout } from 'textura';
|
|
2
|
+
import type { UIElement, TextElement } from './types.js';
|
|
3
|
+
/** Info about a rendered text node's position and content. */
|
|
4
|
+
export interface TextNodeInfo {
|
|
5
|
+
element: TextElement;
|
|
6
|
+
/** Absolute x position. */
|
|
7
|
+
x: number;
|
|
8
|
+
/** Absolute y position. */
|
|
9
|
+
y: number;
|
|
10
|
+
width: number;
|
|
11
|
+
height: number;
|
|
12
|
+
/** Rendered lines with character-level offsets. */
|
|
13
|
+
lines: TextLineInfo[];
|
|
14
|
+
/** Index in the flat list of all text nodes (document order). */
|
|
15
|
+
index: number;
|
|
16
|
+
}
|
|
17
|
+
export interface TextLineInfo {
|
|
18
|
+
text: string;
|
|
19
|
+
x: number;
|
|
20
|
+
y: number;
|
|
21
|
+
/** Cumulative x offset of each character start, relative to line x. */
|
|
22
|
+
charOffsets: number[];
|
|
23
|
+
/** Width of each character. */
|
|
24
|
+
charWidths: number[];
|
|
25
|
+
}
|
|
26
|
+
/** A selection range across text nodes. */
|
|
27
|
+
export interface SelectionRange {
|
|
28
|
+
/** Index of the anchor text node. */
|
|
29
|
+
anchorNode: number;
|
|
30
|
+
/** Character offset within the anchor node's full text. */
|
|
31
|
+
anchorOffset: number;
|
|
32
|
+
/** Index of the focus text node. */
|
|
33
|
+
focusNode: number;
|
|
34
|
+
/** Character offset within the focus node's full text. */
|
|
35
|
+
focusOffset: number;
|
|
36
|
+
}
|
|
37
|
+
/** Collect all selectable text nodes from the element tree with their absolute positions. */
|
|
38
|
+
export declare function collectTextNodes(element: UIElement, layout: ComputedLayout, offsetX: number, offsetY: number, results: TextNodeInfo[]): void;
|
|
39
|
+
/** Get the selected text from a selection range and text node info list. */
|
|
40
|
+
export declare function getSelectedText(range: SelectionRange, textNodes: TextNodeInfo[]): string;
|
|
41
|
+
/** Find which text node and character offset is at a given (x, y) point. */
|
|
42
|
+
export declare function hitTestText(textNodes: TextNodeInfo[], px: number, py: number): {
|
|
43
|
+
nodeIndex: number;
|
|
44
|
+
charOffset: number;
|
|
45
|
+
} | null;
|
|
46
|
+
//# sourceMappingURL=selection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"selection.d.ts","sourceRoot":"","sources":["../src/selection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAC7C,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAExD,8DAA8D;AAC9D,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,WAAW,CAAA;IACpB,2BAA2B;IAC3B,CAAC,EAAE,MAAM,CAAA;IACT,2BAA2B;IAC3B,CAAC,EAAE,MAAM,CAAA;IACT,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;IACd,mDAAmD;IACnD,KAAK,EAAE,YAAY,EAAE,CAAA;IACrB,iEAAiE;IACjE,KAAK,EAAE,MAAM,CAAA;CACd;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;IACT,uEAAuE;IACvE,WAAW,EAAE,MAAM,EAAE,CAAA;IACrB,+BAA+B;IAC/B,UAAU,EAAE,MAAM,EAAE,CAAA;CACrB;AAED,2CAA2C;AAC3C,MAAM,WAAW,cAAc;IAC7B,qCAAqC;IACrC,UAAU,EAAE,MAAM,CAAA;IAClB,2DAA2D;IAC3D,YAAY,EAAE,MAAM,CAAA;IACpB,oCAAoC;IACpC,SAAS,EAAE,MAAM,CAAA;IACjB,0DAA0D;IAC1D,WAAW,EAAE,MAAM,CAAA;CACpB;AAED,6FAA6F;AAC7F,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,SAAS,EAClB,MAAM,EAAE,cAAc,EACtB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,YAAY,EAAE,GACtB,IAAI,CA2BN;AAED,4EAA4E;AAC5E,wBAAgB,eAAe,CAC7B,KAAK,EAAE,cAAc,EACrB,SAAS,EAAE,YAAY,EAAE,GACxB,MAAM,CA+BR;AAED,4EAA4E;AAC5E,wBAAgB,WAAW,CACzB,SAAS,EAAE,YAAY,EAAE,EACzB,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,GACT;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAgClD"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/** Collect all selectable text nodes from the element tree with their absolute positions. */
|
|
2
|
+
export function collectTextNodes(element, layout, offsetX, offsetY, results) {
|
|
3
|
+
const x = offsetX + layout.x;
|
|
4
|
+
const y = offsetY + layout.y;
|
|
5
|
+
if (element.kind === 'text') {
|
|
6
|
+
if (element.props.selectable !== false) {
|
|
7
|
+
results.push({
|
|
8
|
+
element,
|
|
9
|
+
x,
|
|
10
|
+
y,
|
|
11
|
+
width: layout.width,
|
|
12
|
+
height: layout.height,
|
|
13
|
+
lines: [], // Populated by the renderer (needs ctx.measureText)
|
|
14
|
+
index: results.length,
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
if (element.kind !== 'box')
|
|
20
|
+
return;
|
|
21
|
+
for (let i = 0; i < element.children.length; i++) {
|
|
22
|
+
const childLayout = layout.children[i];
|
|
23
|
+
if (childLayout) {
|
|
24
|
+
collectTextNodes(element.children[i], childLayout, x, y, results);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/** Get the selected text from a selection range and text node info list. */
|
|
29
|
+
export function getSelectedText(range, textNodes) {
|
|
30
|
+
if (textNodes.length === 0)
|
|
31
|
+
return '';
|
|
32
|
+
// Normalize: ensure start <= end
|
|
33
|
+
let startNode = range.anchorNode;
|
|
34
|
+
let startOffset = range.anchorOffset;
|
|
35
|
+
let endNode = range.focusNode;
|
|
36
|
+
let endOffset = range.focusOffset;
|
|
37
|
+
if (startNode > endNode || (startNode === endNode && startOffset > endOffset)) {
|
|
38
|
+
;
|
|
39
|
+
[startNode, endNode] = [endNode, startNode];
|
|
40
|
+
[startOffset, endOffset] = [endOffset, startOffset];
|
|
41
|
+
}
|
|
42
|
+
const parts = [];
|
|
43
|
+
for (let i = startNode; i <= endNode; i++) {
|
|
44
|
+
const node = textNodes[i];
|
|
45
|
+
if (!node)
|
|
46
|
+
continue;
|
|
47
|
+
const fullText = node.element.props.text;
|
|
48
|
+
if (i === startNode && i === endNode) {
|
|
49
|
+
parts.push(fullText.slice(startOffset, endOffset));
|
|
50
|
+
}
|
|
51
|
+
else if (i === startNode) {
|
|
52
|
+
parts.push(fullText.slice(startOffset));
|
|
53
|
+
}
|
|
54
|
+
else if (i === endNode) {
|
|
55
|
+
parts.push(fullText.slice(0, endOffset));
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
parts.push(fullText);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return parts.join('\n');
|
|
62
|
+
}
|
|
63
|
+
/** Find which text node and character offset is at a given (x, y) point. */
|
|
64
|
+
export function hitTestText(textNodes, px, py) {
|
|
65
|
+
for (const node of textNodes) {
|
|
66
|
+
// Check if point is within the text node's bounding box
|
|
67
|
+
if (px < node.x || px > node.x + node.width || py < node.y || py > node.y + node.height) {
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
// Find the line
|
|
71
|
+
let globalCharOffset = 0;
|
|
72
|
+
for (const line of node.lines) {
|
|
73
|
+
const lineBottom = line.y + (node.element.props.lineHeight);
|
|
74
|
+
if (py >= line.y && py < lineBottom) {
|
|
75
|
+
// Find the character within the line
|
|
76
|
+
const localX = px - line.x;
|
|
77
|
+
for (let c = 0; c < line.charOffsets.length; c++) {
|
|
78
|
+
const charStart = line.charOffsets[c];
|
|
79
|
+
const charEnd = charStart + line.charWidths[c];
|
|
80
|
+
if (localX < (charStart + charEnd) / 2) {
|
|
81
|
+
return { nodeIndex: node.index, charOffset: globalCharOffset + c };
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
// Past the end of the line — snap to end
|
|
85
|
+
return { nodeIndex: node.index, charOffset: globalCharOffset + line.text.length };
|
|
86
|
+
}
|
|
87
|
+
globalCharOffset += line.text.length;
|
|
88
|
+
}
|
|
89
|
+
// Point is within node bounds but between lines — snap to nearest
|
|
90
|
+
return { nodeIndex: node.index, charOffset: 0 };
|
|
91
|
+
}
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=selection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"selection.js","sourceRoot":"","sources":["../src/selection.ts"],"names":[],"mappings":"AAwCA,6FAA6F;AAC7F,MAAM,UAAU,gBAAgB,CAC9B,OAAkB,EAClB,MAAsB,EACtB,OAAe,EACf,OAAe,EACf,OAAuB;IAEvB,MAAM,CAAC,GAAG,OAAO,GAAG,MAAM,CAAC,CAAC,CAAA;IAC5B,MAAM,CAAC,GAAG,OAAO,GAAG,MAAM,CAAC,CAAC,CAAA;IAE5B,IAAI,OAAO,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;QAC5B,IAAI,OAAO,CAAC,KAAK,CAAC,UAAU,KAAK,KAAK,EAAE,CAAC;YACvC,OAAO,CAAC,IAAI,CAAC;gBACX,OAAO;gBACP,CAAC;gBACD,CAAC;gBACD,KAAK,EAAE,MAAM,CAAC,KAAK;gBACnB,MAAM,EAAE,MAAM,CAAC,MAAM;gBACrB,KAAK,EAAE,EAAE,EAAE,oDAAoD;gBAC/D,KAAK,EAAE,OAAO,CAAC,MAAM;aACtB,CAAC,CAAA;QACJ,CAAC;QACD,OAAM;IACR,CAAC;IAED,IAAI,OAAO,CAAC,IAAI,KAAK,KAAK;QAAE,OAAM;IAElC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACjD,MAAM,WAAW,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAA;QACtC,IAAI,WAAW,EAAE,CAAC;YAChB,gBAAgB,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAE,EAAE,WAAW,EAAE,CAAC,EAAE,CAAC,EAAE,OAAO,CAAC,CAAA;QACpE,CAAC;IACH,CAAC;AACH,CAAC;AAED,4EAA4E;AAC5E,MAAM,UAAU,eAAe,CAC7B,KAAqB,EACrB,SAAyB;IAEzB,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAA;IAErC,iCAAiC;IACjC,IAAI,SAAS,GAAG,KAAK,CAAC,UAAU,CAAA;IAChC,IAAI,WAAW,GAAG,KAAK,CAAC,YAAY,CAAA;IACpC,IAAI,OAAO,GAAG,KAAK,CAAC,SAAS,CAAA;IAC7B,IAAI,SAAS,GAAG,KAAK,CAAC,WAAW,CAAA;IAEjC,IAAI,SAAS,GAAG,OAAO,IAAI,CAAC,SAAS,KAAK,OAAO,IAAI,WAAW,GAAG,SAAS,CAAC,EAAE,CAAC;QAC9E,CAAC;QAAA,CAAC,SAAS,EAAE,OAAO,CAAC,GAAG,CAAC,OAAO,EAAE,SAAS,CAAC,CAC3C;QAAA,CAAC,WAAW,EAAE,SAAS,CAAC,GAAG,CAAC,SAAS,EAAE,WAAW,CAAC,CAAA;IACtD,CAAC;IAED,MAAM,KAAK,GAAa,EAAE,CAAA;IAC1B,KAAK,IAAI,CAAC,GAAG,SAAS,EAAE,CAAC,IAAI,OAAO,EAAE,CAAC,EAAE,EAAE,CAAC;QAC1C,MAAM,IAAI,GAAG,SAAS,CAAC,CAAC,CAAC,CAAA;QACzB,IAAI,CAAC,IAAI;YAAE,SAAQ;QACnB,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAA;QACxC,IAAI,CAAC,KAAK,SAAS,IAAI,CAAC,KAAK,OAAO,EAAE,CAAC;YACrC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC,CAAA;QACpD,CAAC;aAAM,IAAI,CAAC,KAAK,SAAS,EAAE,CAAC;YAC3B,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAA;QACzC,CAAC;aAAM,IAAI,CAAC,KAAK,OAAO,EAAE,CAAC;YACzB,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,CAAA;QAC1C,CAAC;aAAM,CAAC;YACN,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;QACtB,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACzB,CAAC;AAED,4EAA4E;AAC5E,MAAM,UAAU,WAAW,CACzB,SAAyB,EACzB,EAAU,EACV,EAAU;IAEV,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;QAC7B,wDAAwD;QACxD,IAAI,EAAE,GAAG,IAAI,CAAC,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,IAAI,EAAE,GAAG,IAAI,CAAC,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;YACxF,SAAQ;QACV,CAAC;QAED,gBAAgB;QAChB,IAAI,gBAAgB,GAAG,CAAC,CAAA;QACxB,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YAC9B,MAAM,UAAU,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,CAAA;YAC3D,IAAI,EAAE,IAAI,IAAI,CAAC,CAAC,IAAI,EAAE,GAAG,UAAU,EAAE,CAAC;gBACpC,qCAAqC;gBACrC,MAAM,MAAM,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,CAAA;gBAC1B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;oBACjD,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC,CAAE,CAAA;oBACtC,MAAM,OAAO,GAAG,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAE,CAAA;oBAC/C,IAAI,MAAM,GAAG,CAAC,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;wBACvC,OAAO,EAAE,SAAS,EAAE,IAAI,CAAC,KAAK,EAAE,UAAU,EAAE,gBAAgB,GAAG,CAAC,EAAE,CAAA;oBACpE,CAAC;gBACH,CAAC;gBACD,yCAAyC;gBACzC,OAAO,EAAE,SAAS,EAAE,IAAI,CAAC,KAAK,EAAE,UAAU,EAAE,gBAAgB,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAA;YACnF,CAAC;YACD,gBAAgB,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,CAAA;QACtC,CAAC;QAED,kEAAkE;QAClE,OAAO,EAAE,SAAS,EAAE,IAAI,CAAC,KAAK,EAAE,UAAU,EAAE,CAAC,EAAE,CAAA;IACjD,CAAC;IAED,OAAO,IAAI,CAAA;AACb,CAAC"}
|
package/dist/seo.d.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { UIElement } from './types.js';
|
|
2
|
+
/** Options for semantic HTML generation. */
|
|
3
|
+
export interface SemanticHTMLOptions {
|
|
4
|
+
/** Page title for the <title> tag. */
|
|
5
|
+
title?: string;
|
|
6
|
+
/** Meta description. */
|
|
7
|
+
description?: string;
|
|
8
|
+
/** Canonical URL. */
|
|
9
|
+
canonical?: string;
|
|
10
|
+
/** Open Graph metadata. */
|
|
11
|
+
og?: {
|
|
12
|
+
title?: string;
|
|
13
|
+
description?: string;
|
|
14
|
+
image?: string;
|
|
15
|
+
url?: string;
|
|
16
|
+
type?: string;
|
|
17
|
+
};
|
|
18
|
+
/** Additional <head> content (raw HTML string). */
|
|
19
|
+
headExtra?: string;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Generate semantic HTML from a UIElement tree.
|
|
23
|
+
*
|
|
24
|
+
* This produces a full HTML document suitable for search engine crawlers.
|
|
25
|
+
* Serve this to user-agents like Googlebot while rendering the canvas
|
|
26
|
+
* version for real users.
|
|
27
|
+
*/
|
|
28
|
+
export declare function toSemanticHTML(tree: UIElement, options?: SemanticHTMLOptions): string;
|
|
29
|
+
//# sourceMappingURL=seo.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seo.d.ts","sourceRoot":"","sources":["../src/seo.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAyC,MAAM,YAAY,CAAA;AAElF,4CAA4C;AAC5C,MAAM,WAAW,mBAAmB;IAClC,sCAAsC;IACtC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,wBAAwB;IACxB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,qBAAqB;IACrB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,2BAA2B;IAC3B,EAAE,CAAC,EAAE;QACH,KAAK,CAAC,EAAE,MAAM,CAAA;QACd,WAAW,CAAC,EAAE,MAAM,CAAA;QACpB,KAAK,CAAC,EAAE,MAAM,CAAA;QACd,GAAG,CAAC,EAAE,MAAM,CAAA;QACZ,IAAI,CAAC,EAAE,MAAM,CAAA;KACd,CAAA;IACD,mDAAmD;IACnD,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAmED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,SAAS,EACf,OAAO,GAAE,mBAAwB,GAChC,MAAM,CA+BR"}
|