@hypen-space/web 0.4.46 → 0.4.81

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 (69) hide show
  1. package/README.md +4 -4
  2. package/dist/canvas/dirty.d.ts +40 -0
  3. package/dist/canvas/dirty.js +100 -0
  4. package/dist/canvas/dirty.js.map +1 -0
  5. package/dist/canvas/events.d.ts +5 -0
  6. package/dist/canvas/events.js +30 -3
  7. package/dist/canvas/events.js.map +1 -1
  8. package/dist/canvas/index.d.ts +5 -1
  9. package/dist/canvas/index.js +4 -0
  10. package/dist/canvas/index.js.map +1 -1
  11. package/dist/canvas/layout.d.ts +12 -2
  12. package/dist/canvas/layout.js +593 -63
  13. package/dist/canvas/layout.js.map +1 -1
  14. package/dist/canvas/paint.d.ts +2 -0
  15. package/dist/canvas/paint.js +88 -11
  16. package/dist/canvas/paint.js.map +1 -1
  17. package/dist/canvas/renderer.d.ts +16 -0
  18. package/dist/canvas/renderer.js +154 -15
  19. package/dist/canvas/renderer.js.map +1 -1
  20. package/dist/canvas/scroll.d.ts +82 -0
  21. package/dist/canvas/scroll.js +639 -0
  22. package/dist/canvas/scroll.js.map +1 -0
  23. package/dist/canvas/selection.d.ts +63 -0
  24. package/dist/canvas/selection.js +466 -0
  25. package/dist/canvas/selection.js.map +1 -0
  26. package/dist/canvas/text.d.ts +6 -3
  27. package/dist/canvas/text.js +82 -43
  28. package/dist/canvas/text.js.map +1 -1
  29. package/dist/canvas/types.d.ts +18 -0
  30. package/dist/canvas/utils.d.ts +8 -2
  31. package/dist/canvas/utils.js +42 -16
  32. package/dist/canvas/utils.js.map +1 -1
  33. package/dist/canvas/virtualize.d.ts +25 -0
  34. package/dist/canvas/virtualize.js +65 -0
  35. package/dist/canvas/virtualize.js.map +1 -0
  36. package/dist/dom/applicators/index.js +0 -1
  37. package/dist/dom/applicators/index.js.map +1 -1
  38. package/dist/dom/applicators/margin.js +58 -17
  39. package/dist/dom/applicators/margin.js.map +1 -1
  40. package/dist/dom/applicators/padding.js +42 -17
  41. package/dist/dom/applicators/padding.js.map +1 -1
  42. package/dist/dom/components/icon.d.ts +9 -0
  43. package/dist/dom/components/icon.js +67 -0
  44. package/dist/dom/components/icon.js.map +1 -0
  45. package/dist/dom/components/index.js +2 -0
  46. package/dist/dom/components/index.js.map +1 -1
  47. package/dist/dom/renderer.d.ts +19 -5
  48. package/dist/dom/renderer.js +147 -17
  49. package/dist/dom/renderer.js.map +1 -1
  50. package/package.json +4 -2
  51. package/src/canvas/QUICKSTART.md +5 -5
  52. package/src/canvas/dirty.ts +116 -0
  53. package/src/canvas/events.ts +34 -3
  54. package/src/canvas/index.ts +5 -0
  55. package/src/canvas/layout.ts +653 -100
  56. package/src/canvas/paint.ts +109 -11
  57. package/src/canvas/renderer.ts +189 -16
  58. package/src/canvas/scroll.ts +729 -0
  59. package/src/canvas/selection.ts +560 -0
  60. package/src/canvas/text.ts +97 -54
  61. package/src/canvas/types.ts +26 -0
  62. package/src/canvas/utils.ts +47 -17
  63. package/src/canvas/virtualize.ts +81 -0
  64. package/src/dom/applicators/index.ts +1 -1
  65. package/src/dom/applicators/margin.ts +57 -11
  66. package/src/dom/applicators/padding.ts +45 -11
  67. package/src/dom/components/icon.ts +84 -0
  68. package/src/dom/components/index.ts +2 -0
  69. package/src/dom/renderer.ts +155 -17
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Text Selection System
3
+ *
4
+ * Enables click-to-place-cursor, drag-to-select, double-click-word,
5
+ * triple-click-line, and Ctrl/Cmd+C copy for canvas-rendered text.
6
+ */
7
+ import type { VirtualNode } from "./types.js";
8
+ /** A caret position within a text node. */
9
+ export interface TextPosition {
10
+ /** The VirtualNode (must be type "text") */
11
+ nodeId: string;
12
+ /** Index into the resolved text string */
13
+ offset: number;
14
+ }
15
+ /** Active selection range (anchor → focus, may be reversed). */
16
+ export interface TextSelection {
17
+ anchor: TextPosition;
18
+ focus: TextPosition;
19
+ }
20
+ /** Resolved geometry for painting a selection highlight on one line. */
21
+ export interface SelectionRect {
22
+ x: number;
23
+ y: number;
24
+ width: number;
25
+ height: number;
26
+ }
27
+ export declare class SelectionManager {
28
+ private canvas;
29
+ private rootNode;
30
+ private requestRedraw;
31
+ /** Current selection (null = nothing selected). */
32
+ selection: TextSelection | null;
33
+ private dragging;
34
+ private clickCount;
35
+ private lastClickTime;
36
+ private lastClickNodeId;
37
+ private boundMouseDown;
38
+ private boundMouseMove;
39
+ private boundMouseUp;
40
+ private boundKeyDown;
41
+ constructor(canvas: HTMLCanvasElement, requestRedraw: () => void);
42
+ setRootNode(node: VirtualNode | null): void;
43
+ private setupListeners;
44
+ private canvasPoint;
45
+ private onMouseDown;
46
+ private onMouseMove;
47
+ private onMouseUp;
48
+ private onKeyDown;
49
+ private selectWord;
50
+ private selectAll;
51
+ getSelectedText(): string | null;
52
+ /**
53
+ * Find which text node and character offset a canvas point maps to.
54
+ */
55
+ private hitTestText;
56
+ private hitTestTextNode;
57
+ /**
58
+ * Paint selection highlight for a text node (called before text is drawn).
59
+ */
60
+ paintSelection(ctx: CanvasRenderingContext2D, node: VirtualNode): void;
61
+ private findNodeById;
62
+ destroy(): void;
63
+ }
@@ -0,0 +1,466 @@
1
+ /**
2
+ * Text Selection System
3
+ *
4
+ * Enables click-to-place-cursor, drag-to-select, double-click-word,
5
+ * triple-click-line, and Ctrl/Cmd+C copy for canvas-rendered text.
6
+ */
7
+ import { getScrollAwareBounds } from "./scroll.js";
8
+ import { measureText } from "./text.js";
9
+ import { createFontString } from "./utils.js";
10
+ // ---------------------------------------------------------------------------
11
+ // Selection state
12
+ // ---------------------------------------------------------------------------
13
+ const HIGHLIGHT_COLOR = "rgba(59, 130, 246, 0.35)";
14
+ // ---------------------------------------------------------------------------
15
+ // SelectionManager
16
+ // ---------------------------------------------------------------------------
17
+ export class SelectionManager {
18
+ canvas;
19
+ rootNode = null;
20
+ requestRedraw;
21
+ /** Current selection (null = nothing selected). */
22
+ selection = null;
23
+ // Drag tracking
24
+ dragging = false;
25
+ clickCount = 0;
26
+ lastClickTime = 0;
27
+ lastClickNodeId = "";
28
+ // Bound handlers
29
+ boundMouseDown;
30
+ boundMouseMove;
31
+ boundMouseUp;
32
+ boundKeyDown;
33
+ constructor(canvas, requestRedraw) {
34
+ this.canvas = canvas;
35
+ this.requestRedraw = requestRedraw;
36
+ this.setupListeners();
37
+ }
38
+ setRootNode(node) {
39
+ this.rootNode = node;
40
+ }
41
+ // -------------------------------------------------------------------------
42
+ // Event wiring
43
+ // -------------------------------------------------------------------------
44
+ setupListeners() {
45
+ this.boundMouseDown = this.onMouseDown.bind(this);
46
+ this.boundMouseMove = this.onMouseMove.bind(this);
47
+ this.boundMouseUp = this.onMouseUp.bind(this);
48
+ this.boundKeyDown = this.onKeyDown.bind(this);
49
+ this.canvas.addEventListener("mousedown", this.boundMouseDown);
50
+ this.canvas.addEventListener("mousemove", this.boundMouseMove);
51
+ this.canvas.addEventListener("mouseup", this.boundMouseUp);
52
+ // keydown on window so it works even without canvas focus
53
+ (typeof window !== "undefined" ? window : this.canvas).addEventListener("keydown", this.boundKeyDown);
54
+ }
55
+ // -------------------------------------------------------------------------
56
+ // Mouse handlers
57
+ // -------------------------------------------------------------------------
58
+ canvasPoint(e) {
59
+ const rect = this.canvas.getBoundingClientRect();
60
+ const scaleX = this.canvas.width / rect.width;
61
+ const scaleY = this.canvas.height / rect.height;
62
+ return {
63
+ x: (e.clientX - rect.left) * scaleX,
64
+ y: (e.clientY - rect.top) * scaleY,
65
+ };
66
+ }
67
+ onMouseDown(e) {
68
+ if (e.button !== 0)
69
+ return; // left-click only
70
+ const point = this.canvasPoint(e);
71
+ const hit = this.hitTestText(point);
72
+ if (!hit) {
73
+ if (this.selection) {
74
+ this.selection = null;
75
+ this.requestRedraw();
76
+ }
77
+ return;
78
+ }
79
+ // Detect multi-click (double/triple)
80
+ const now = performance.now();
81
+ if (now - this.lastClickTime < 400 &&
82
+ this.lastClickNodeId === hit.nodeId) {
83
+ this.clickCount++;
84
+ }
85
+ else {
86
+ this.clickCount = 1;
87
+ }
88
+ this.lastClickTime = now;
89
+ this.lastClickNodeId = hit.nodeId;
90
+ if (this.clickCount === 2) {
91
+ // Double-click: select word
92
+ this.selectWord(hit);
93
+ }
94
+ else if (this.clickCount >= 3) {
95
+ // Triple-click: select entire text node
96
+ this.selectAll(hit.nodeId);
97
+ this.clickCount = 0;
98
+ }
99
+ else {
100
+ // Single click: place caret, start drag
101
+ this.selection = { anchor: hit, focus: { ...hit } };
102
+ this.dragging = true;
103
+ }
104
+ this.requestRedraw();
105
+ }
106
+ onMouseMove(e) {
107
+ if (!this.dragging || !this.selection)
108
+ return;
109
+ const point = this.canvasPoint(e);
110
+ const hit = this.hitTestText(point);
111
+ if (hit && hit.nodeId === this.selection.anchor.nodeId) {
112
+ this.selection.focus = hit;
113
+ this.requestRedraw();
114
+ }
115
+ }
116
+ onMouseUp(_e) {
117
+ this.dragging = false;
118
+ }
119
+ // -------------------------------------------------------------------------
120
+ // Keyboard (copy)
121
+ // -------------------------------------------------------------------------
122
+ onKeyDown(e) {
123
+ const isCopy = (e.ctrlKey || e.metaKey) && e.key === "c";
124
+ const isSelectAll = (e.ctrlKey || e.metaKey) && e.key === "a";
125
+ if (isCopy && this.selection) {
126
+ e.preventDefault();
127
+ const text = this.getSelectedText();
128
+ if (text && typeof navigator !== "undefined" && navigator.clipboard) {
129
+ navigator.clipboard.writeText(text).catch(() => {
130
+ // Fallback: execCommand (deprecated but works in more contexts)
131
+ fallbackCopy(text);
132
+ });
133
+ }
134
+ else if (text) {
135
+ fallbackCopy(text);
136
+ }
137
+ }
138
+ if (isSelectAll && this.selection) {
139
+ e.preventDefault();
140
+ this.selectAll(this.selection.anchor.nodeId);
141
+ this.requestRedraw();
142
+ }
143
+ }
144
+ // -------------------------------------------------------------------------
145
+ // Selection logic
146
+ // -------------------------------------------------------------------------
147
+ selectWord(pos) {
148
+ const node = this.findNodeById(pos.nodeId);
149
+ if (!node)
150
+ return;
151
+ const text = resolveText(node);
152
+ const start = wordBoundaryBefore(text, pos.offset);
153
+ const end = wordBoundaryAfter(text, pos.offset);
154
+ this.selection = {
155
+ anchor: { nodeId: pos.nodeId, offset: start },
156
+ focus: { nodeId: pos.nodeId, offset: end },
157
+ };
158
+ }
159
+ selectAll(nodeId) {
160
+ const node = this.findNodeById(nodeId);
161
+ if (!node)
162
+ return;
163
+ const text = resolveText(node);
164
+ this.selection = {
165
+ anchor: { nodeId, offset: 0 },
166
+ focus: { nodeId, offset: text.length },
167
+ };
168
+ }
169
+ getSelectedText() {
170
+ if (!this.selection)
171
+ return null;
172
+ const node = this.findNodeById(this.selection.anchor.nodeId);
173
+ if (!node)
174
+ return null;
175
+ const text = resolveText(node);
176
+ const [start, end] = normalizeRange(this.selection);
177
+ return text.slice(start, end);
178
+ }
179
+ // -------------------------------------------------------------------------
180
+ // Hit testing — map canvas point → TextPosition
181
+ // -------------------------------------------------------------------------
182
+ /**
183
+ * Find which text node and character offset a canvas point maps to.
184
+ */
185
+ hitTestText(point) {
186
+ if (!this.rootNode)
187
+ return null;
188
+ return this.hitTestTextNode(this.rootNode, point);
189
+ }
190
+ hitTestTextNode(node, point) {
191
+ if (!node.visible || !node.layout)
192
+ return null;
193
+ // Check children first (front-to-back)
194
+ for (let i = node.children.length - 1; i >= 0; i--) {
195
+ const result = this.hitTestTextNode(node.children[i], point);
196
+ if (result)
197
+ return result;
198
+ }
199
+ // Only text nodes are selectable
200
+ if (node.type !== "text")
201
+ return null;
202
+ const bounds = getScrollAwareBounds(node);
203
+ if (!bounds)
204
+ return null;
205
+ if (point.x < bounds.x || point.x > bounds.x + bounds.width ||
206
+ point.y < bounds.y || point.y > bounds.y + bounds.height) {
207
+ return null;
208
+ }
209
+ // Map point to character offset within this text node
210
+ const offset = pointToOffset(this.canvas, node, bounds, point);
211
+ return { nodeId: node.id, offset };
212
+ }
213
+ // -------------------------------------------------------------------------
214
+ // Painting — called from paint pipeline
215
+ // -------------------------------------------------------------------------
216
+ /**
217
+ * Paint selection highlight for a text node (called before text is drawn).
218
+ */
219
+ paintSelection(ctx, node) {
220
+ if (!this.selection)
221
+ return;
222
+ if (this.selection.anchor.nodeId !== node.id)
223
+ return;
224
+ const [start, end] = normalizeRange(this.selection);
225
+ if (start === end)
226
+ return; // caret only, no highlight
227
+ const rects = getSelectionRects(ctx, node, start, end);
228
+ ctx.save();
229
+ ctx.fillStyle = HIGHLIGHT_COLOR;
230
+ for (const r of rects) {
231
+ ctx.fillRect(r.x, r.y, r.width, r.height);
232
+ }
233
+ ctx.restore();
234
+ }
235
+ // -------------------------------------------------------------------------
236
+ // Helpers
237
+ // -------------------------------------------------------------------------
238
+ findNodeById(id) {
239
+ if (!this.rootNode)
240
+ return null;
241
+ return findById(this.rootNode, id);
242
+ }
243
+ destroy() {
244
+ this.canvas.removeEventListener("mousedown", this.boundMouseDown);
245
+ this.canvas.removeEventListener("mousemove", this.boundMouseMove);
246
+ this.canvas.removeEventListener("mouseup", this.boundMouseUp);
247
+ (typeof window !== "undefined" ? window : this.canvas).removeEventListener("keydown", this.boundKeyDown);
248
+ this.rootNode = null;
249
+ this.selection = null;
250
+ }
251
+ }
252
+ // ---------------------------------------------------------------------------
253
+ // Pure helpers
254
+ // ---------------------------------------------------------------------------
255
+ function resolveText(node) {
256
+ const raw = node.props[0] || node.props.text || "";
257
+ let text = String(raw);
258
+ const tt = node.props.textTransform || "none";
259
+ if (tt === "uppercase")
260
+ text = text.toUpperCase();
261
+ else if (tt === "lowercase")
262
+ text = text.toLowerCase();
263
+ else if (tt === "capitalize")
264
+ text = text.replace(/\b\w/g, (c) => c.toUpperCase());
265
+ return text;
266
+ }
267
+ function normalizeRange(sel) {
268
+ const a = sel.anchor.offset;
269
+ const b = sel.focus.offset;
270
+ return a <= b ? [a, b] : [b, a];
271
+ }
272
+ function wordBoundaryBefore(text, offset) {
273
+ let i = Math.min(offset, text.length - 1);
274
+ // Skip non-word chars
275
+ while (i > 0 && !/\w/.test(text[i]))
276
+ i--;
277
+ // Walk back through word chars
278
+ while (i > 0 && /\w/.test(text[i - 1]))
279
+ i--;
280
+ return i;
281
+ }
282
+ function wordBoundaryAfter(text, offset) {
283
+ let i = offset;
284
+ // Skip non-word chars
285
+ while (i < text.length && !/\w/.test(text[i]))
286
+ i++;
287
+ // Walk forward through word chars
288
+ while (i < text.length && /\w/.test(text[i]))
289
+ i++;
290
+ return i;
291
+ }
292
+ function findById(node, id) {
293
+ if (node.id === id)
294
+ return node;
295
+ for (const child of node.children) {
296
+ const found = findById(child, id);
297
+ if (found)
298
+ return found;
299
+ }
300
+ return null;
301
+ }
302
+ // ---------------------------------------------------------------------------
303
+ // Geometry: map a canvas point to a character offset
304
+ // ---------------------------------------------------------------------------
305
+ /**
306
+ * Given a point inside a text node's bounds, return the character index
307
+ * that the point falls on.
308
+ */
309
+ function pointToOffset(canvas, node, bounds, point) {
310
+ const ctx = canvas.getContext("2d");
311
+ if (!ctx)
312
+ return 0;
313
+ const props = node.props;
314
+ const text = resolveText(node);
315
+ const layout = node.layout;
316
+ const fontSize = parseFloat(props.fontSize) || 16;
317
+ const fontWeight = props.fontWeight || "normal";
318
+ const fontFamily = props.fontFamily || "system-ui, sans-serif";
319
+ const lineHeight = parseFloat(props.lineHeight) || fontSize * 1.2;
320
+ const textAlign = props.textAlign || "left";
321
+ const fontStyle = { fontSize, fontWeight, fontFamily, lineHeight };
322
+ const font = createFontString(fontSize, fontWeight, fontFamily);
323
+ ctx.save();
324
+ ctx.font = font;
325
+ const metrics = measureText(ctx, text, fontStyle, layout.contentWidth);
326
+ const contentX = bounds.x + layout.contentX;
327
+ const contentY = bounds.y + layout.contentY;
328
+ // Find which line the point falls on
329
+ const relY = point.y - contentY;
330
+ let lineIndex = Math.floor(relY / metrics.lineHeight);
331
+ lineIndex = Math.max(0, Math.min(lineIndex, metrics.lines.length - 1));
332
+ // Calculate character offset before this line
333
+ let charsBefore = 0;
334
+ for (let i = 0; i < lineIndex; i++) {
335
+ charsBefore += metrics.lines[i].length;
336
+ // Account for space/newline between lines (word wrap eats the space)
337
+ if (i < metrics.lines.length - 1) {
338
+ const nextLineStart = text.indexOf(metrics.lines[i + 1], charsBefore);
339
+ if (nextLineStart > charsBefore)
340
+ charsBefore = nextLineStart;
341
+ }
342
+ }
343
+ const line = metrics.lines[lineIndex];
344
+ // Calculate line X offset (for text-align)
345
+ let lineX = contentX;
346
+ if (textAlign === "center") {
347
+ const lw = ctx.measureText(line).width;
348
+ lineX = contentX + (layout.contentWidth - lw) / 2;
349
+ }
350
+ else if (textAlign === "right") {
351
+ const lw = ctx.measureText(line).width;
352
+ lineX = contentX + layout.contentWidth - lw;
353
+ }
354
+ // Binary search for the character at point.x
355
+ const relX = point.x - lineX;
356
+ let best = 0;
357
+ for (let i = 0; i <= line.length; i++) {
358
+ const w = ctx.measureText(line.slice(0, i)).width;
359
+ if (w <= relX) {
360
+ best = i;
361
+ }
362
+ else {
363
+ // Check if we're closer to this char or the previous
364
+ const prevW = ctx.measureText(line.slice(0, i - 1)).width;
365
+ if (relX - prevW < w - relX) {
366
+ best = i - 1;
367
+ }
368
+ else {
369
+ best = i;
370
+ }
371
+ break;
372
+ }
373
+ }
374
+ ctx.restore();
375
+ return charsBefore + best;
376
+ }
377
+ // ---------------------------------------------------------------------------
378
+ // Geometry: compute highlight rectangles for a selection range
379
+ // ---------------------------------------------------------------------------
380
+ /**
381
+ * Return a list of rectangles to paint as the selection highlight for
382
+ * characters [start, end) within a text node.
383
+ */
384
+ function getSelectionRects(ctx, node, start, end) {
385
+ const props = node.props;
386
+ const layout = node.layout;
387
+ const text = resolveText(node);
388
+ const fontSize = parseFloat(props.fontSize) || 16;
389
+ const fontWeight = props.fontWeight || "normal";
390
+ const fontFamily = props.fontFamily || "system-ui, sans-serif";
391
+ const lineHeight = parseFloat(props.lineHeight) || fontSize * 1.2;
392
+ const textAlign = props.textAlign || "left";
393
+ const fontStyle = { fontSize, fontWeight, fontFamily, lineHeight };
394
+ const font = createFontString(fontSize, fontWeight, fontFamily);
395
+ ctx.save();
396
+ ctx.font = font;
397
+ const metrics = measureText(ctx, text, fontStyle, layout.contentWidth);
398
+ const x = layout.x + layout.contentX;
399
+ const y = layout.y + layout.contentY;
400
+ const rects = [];
401
+ // Map lines to character ranges
402
+ let charOffset = 0;
403
+ for (let i = 0; i < metrics.lines.length; i++) {
404
+ const line = metrics.lines[i];
405
+ const lineStart = charOffset;
406
+ const lineEnd = charOffset + line.length;
407
+ // Find actual position in original text for this line
408
+ if (i > 0) {
409
+ const idx = text.indexOf(line, charOffset);
410
+ if (idx > charOffset)
411
+ charOffset = idx;
412
+ }
413
+ const actualLineStart = charOffset;
414
+ const actualLineEnd = charOffset + line.length;
415
+ // Does this line overlap with the selection?
416
+ if (actualLineEnd <= start || actualLineStart >= end) {
417
+ charOffset = actualLineEnd;
418
+ continue;
419
+ }
420
+ // Clamp selection to this line
421
+ const selStart = Math.max(0, start - actualLineStart);
422
+ const selEnd = Math.min(line.length, end - actualLineStart);
423
+ // Calculate line X offset (text-align)
424
+ let lineX = x;
425
+ const lineWidth = ctx.measureText(line).width;
426
+ if (textAlign === "center") {
427
+ lineX = x + (layout.contentWidth - lineWidth) / 2;
428
+ }
429
+ else if (textAlign === "right") {
430
+ lineX = x + layout.contentWidth - lineWidth;
431
+ }
432
+ // Measure selection bounds within this line
433
+ const startX = ctx.measureText(line.slice(0, selStart)).width;
434
+ const endX = ctx.measureText(line.slice(0, selEnd)).width;
435
+ rects.push({
436
+ x: lineX + startX,
437
+ y: y + i * metrics.lineHeight,
438
+ width: endX - startX,
439
+ height: metrics.lineHeight,
440
+ });
441
+ charOffset = actualLineEnd;
442
+ }
443
+ ctx.restore();
444
+ return rects;
445
+ }
446
+ // ---------------------------------------------------------------------------
447
+ // Clipboard fallback
448
+ // ---------------------------------------------------------------------------
449
+ function fallbackCopy(text) {
450
+ if (typeof document === "undefined")
451
+ return;
452
+ const textarea = document.createElement("textarea");
453
+ textarea.value = text;
454
+ textarea.style.position = "fixed";
455
+ textarea.style.left = "-9999px";
456
+ document.body.appendChild(textarea);
457
+ textarea.select();
458
+ try {
459
+ document.execCommand("copy");
460
+ }
461
+ catch {
462
+ // ignore
463
+ }
464
+ document.body.removeChild(textarea);
465
+ }
466
+ //# sourceMappingURL=selection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"selection.js","sourceRoot":"","sources":["../../src/canvas/selection.ts"],"names":[],"mappings":"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"}
@@ -1,11 +1,14 @@
1
1
  /**
2
2
  * Text Rendering System
3
3
  *
4
- * Text measurement, wrapping, and rendering
4
+ * Text measurement, wrapping, and rendering using pretext for accurate
5
+ * multilingual line breaking (CJK, bidi, emoji, etc.). Falls back to
6
+ * basic word-splitting in environments without OffscreenCanvas (e.g. tests).
5
7
  */
6
8
  import type { FontStyle, TextMetrics, TextStyle } from "./types.js";
7
9
  /**
8
- * Measure text dimensions
10
+ * Measure text dimensions. Uses pretext for accurate multilingual line
11
+ * breaking when available, falls back to basic word-splitting otherwise.
9
12
  */
10
13
  export declare function measureText(ctx: CanvasRenderingContext2D, text: string, fontStyle: FontStyle, maxWidth?: number): TextMetrics;
11
14
  /**
@@ -13,7 +16,7 @@ export declare function measureText(ctx: CanvasRenderingContext2D, text: string,
13
16
  */
14
17
  export declare function renderText(ctx: CanvasRenderingContext2D, text: string, x: number, y: number, width: number, height: number, style: TextStyle): void;
15
18
  /**
16
- * Clear text metrics cache
19
+ * Clear text metrics cache (both local and pretext internal caches)
17
20
  */
18
21
  export declare function clearTextCache(): void;
19
22
  /**