@rasamjs/tools 0.1.0 → 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.
Files changed (85) hide show
  1. package/API.md +122 -2
  2. package/CHANGELOG.md +9 -1
  3. package/README.md +37 -0
  4. package/RELEASING.md +16 -3
  5. package/dist/advanced/context.d.ts +15 -0
  6. package/dist/advanced/context.d.ts.map +1 -0
  7. package/dist/advanced/context.js +2 -0
  8. package/dist/advanced/context.js.map +1 -0
  9. package/dist/advanced/curves.d.ts +5 -0
  10. package/dist/advanced/curves.d.ts.map +1 -0
  11. package/dist/advanced/curves.js +65 -0
  12. package/dist/advanced/curves.js.map +1 -0
  13. package/dist/advanced/geometry.d.ts +17 -0
  14. package/dist/advanced/geometry.d.ts.map +1 -0
  15. package/dist/advanced/geometry.js +61 -0
  16. package/dist/advanced/geometry.js.map +1 -0
  17. package/dist/advanced/rotation.d.ts +4 -0
  18. package/dist/advanced/rotation.d.ts.map +1 -0
  19. package/dist/advanced/rotation.js +86 -0
  20. package/dist/advanced/rotation.js.map +1 -0
  21. package/dist/advanced/session.d.ts +5 -0
  22. package/dist/advanced/session.d.ts.map +1 -0
  23. package/dist/advanced/session.js +240 -0
  24. package/dist/advanced/session.js.map +1 -0
  25. package/dist/advanced/snapper.d.ts +29 -0
  26. package/dist/advanced/snapper.d.ts.map +1 -0
  27. package/dist/advanced/snapper.js +118 -0
  28. package/dist/advanced/snapper.js.map +1 -0
  29. package/dist/advanced/types.d.ts +30 -0
  30. package/dist/advanced/types.d.ts.map +1 -0
  31. package/dist/advanced/types.js +2 -0
  32. package/dist/advanced/types.js.map +1 -0
  33. package/dist/drawing.d.ts +5 -0
  34. package/dist/drawing.d.ts.map +1 -0
  35. package/dist/drawing.js +3 -0
  36. package/dist/drawing.js.map +1 -0
  37. package/dist/editor/draw-tool.d.ts +35 -0
  38. package/dist/editor/draw-tool.d.ts.map +1 -0
  39. package/dist/editor/draw-tool.js +174 -0
  40. package/dist/editor/draw-tool.js.map +1 -0
  41. package/dist/editor/path-editor.d.ts +34 -0
  42. package/dist/editor/path-editor.d.ts.map +1 -0
  43. package/dist/editor/path-editor.js +208 -0
  44. package/dist/editor/path-editor.js.map +1 -0
  45. package/dist/editor/pointer.d.ts +21 -0
  46. package/dist/editor/pointer.d.ts.map +1 -0
  47. package/dist/editor/pointer.js +86 -0
  48. package/dist/editor/pointer.js.map +1 -0
  49. package/dist/editor/surface.d.ts +31 -0
  50. package/dist/editor/surface.d.ts.map +1 -0
  51. package/dist/editor/surface.js +138 -0
  52. package/dist/editor/surface.js.map +1 -0
  53. package/dist/grid.d.ts +23 -0
  54. package/dist/grid.d.ts.map +1 -0
  55. package/dist/grid.js +84 -0
  56. package/dist/grid.js.map +1 -0
  57. package/dist/rulers.d.ts +30 -0
  58. package/dist/rulers.d.ts.map +1 -0
  59. package/dist/rulers.js +234 -0
  60. package/dist/rulers.js.map +1 -0
  61. package/dist/snapping/advanced.d.ts +3 -0
  62. package/dist/snapping/advanced.d.ts.map +1 -0
  63. package/dist/snapping/advanced.js +2 -0
  64. package/dist/snapping/advanced.js.map +1 -0
  65. package/dist/snapping/targets.d.ts +1 -0
  66. package/dist/snapping/targets.d.ts.map +1 -1
  67. package/dist/snapping/targets.js +5 -1
  68. package/dist/snapping/targets.js.map +1 -1
  69. package/package.json +24 -4
  70. package/src/advanced/context.ts +15 -0
  71. package/src/advanced/curves.ts +65 -0
  72. package/src/advanced/geometry.ts +74 -0
  73. package/src/advanced/rotation.ts +93 -0
  74. package/src/advanced/session.ts +276 -0
  75. package/src/advanced/snapper.ts +124 -0
  76. package/src/advanced/types.ts +31 -0
  77. package/src/drawing.ts +4 -0
  78. package/src/editor/draw-tool.ts +190 -0
  79. package/src/editor/path-editor.ts +224 -0
  80. package/src/editor/pointer.ts +85 -0
  81. package/src/editor/surface.ts +141 -0
  82. package/src/grid.ts +99 -0
  83. package/src/rulers.ts +245 -0
  84. package/src/snapping/advanced.ts +8 -0
  85. package/src/snapping/targets.ts +11 -2
@@ -0,0 +1,138 @@
1
+ import { Matrix } from '@rasamjs/core';
2
+ import { Guards } from '@rasamjs/core/advanced';
3
+ export function svg(document, tag, attributes = {}) {
4
+ const element = document.createElementNS('http://www.w3.org/2000/svg', tag);
5
+ for (const [key, value] of Object.entries(attributes))
6
+ element.setAttribute(key, String(value));
7
+ return element;
8
+ }
9
+ /** Owns an editor-only SVG and every observer/listener registered by its tool. */
10
+ export class Surface {
11
+ drawing;
12
+ render;
13
+ element;
14
+ view;
15
+ cleanups = [];
16
+ pending = null;
17
+ disposed = false;
18
+ constructor(drawing, name, render) {
19
+ this.drawing = drawing;
20
+ this.render = render;
21
+ if (!Guards.isTransformable(drawing) ||
22
+ drawing.isDestroyed ||
23
+ drawing.el.localName !== 'svg' ||
24
+ !drawing.el.isConnected ||
25
+ !drawing.el.ownerDocument.defaultView)
26
+ throw new TypeError('Editor overlay needs a live mounted drawing');
27
+ this.view = drawing.el.ownerDocument.defaultView;
28
+ this.element = svg(drawing.el.ownerDocument, 'svg', {
29
+ class: name,
30
+ width: '100%',
31
+ height: '100%',
32
+ 'aria-label': name.replaceAll('-', ' '),
33
+ });
34
+ Object.assign(this.element.style, {
35
+ position: 'absolute',
36
+ inset: '0',
37
+ overflow: 'visible',
38
+ pointerEvents: 'none',
39
+ });
40
+ let outer = drawing.el;
41
+ while (outer.ownerSVGElement)
42
+ outer = outer.ownerSVGElement;
43
+ const host = outer.parentElement;
44
+ host.append(this.element);
45
+ const observer = new this.view.MutationObserver(this.schedule);
46
+ for (let ancestor = drawing.el; ancestor && ancestor !== host; ancestor = ancestor.parentElement)
47
+ observer.observe(ancestor, { attributes: true });
48
+ this.cleanup(() => observer.disconnect());
49
+ const resize = new this.view.ResizeObserver(this.schedule);
50
+ resize.observe(host);
51
+ this.cleanup(() => resize.disconnect());
52
+ this.listen(this.view, 'resize', this.schedule);
53
+ this.listen(this.view, 'scroll', this.schedule, true);
54
+ this.cleanup(drawing.onDispose(() => this.destroy()));
55
+ this.schedule();
56
+ }
57
+ cleanup(callback) {
58
+ this.cleanups.push(callback);
59
+ }
60
+ get isDestroyed() {
61
+ return this.disposed;
62
+ }
63
+ listen(target, type, listener, capture = false) {
64
+ target.addEventListener(type, listener, capture);
65
+ this.cleanup(() => target.removeEventListener(type, listener, capture));
66
+ }
67
+ schedule = () => {
68
+ if (!this.disposed && this.pending === null)
69
+ this.pending = this.view.requestAnimationFrame(() => {
70
+ this.pending = null;
71
+ this.update();
72
+ });
73
+ };
74
+ update() {
75
+ if (this.pending !== null)
76
+ this.view.cancelAnimationFrame(this.pending);
77
+ this.pending = null;
78
+ if (!this.disposed)
79
+ this.render();
80
+ return this;
81
+ }
82
+ screenMatrix() {
83
+ const m = this.element.getScreenCTM?.();
84
+ return m ? new Matrix(m.a, m.b, m.c, m.d, m.e, m.f) : null;
85
+ }
86
+ fromClient(point) {
87
+ return this.screenMatrix()?.inverse()?.apply(point) ?? null;
88
+ }
89
+ fromRoot(point) {
90
+ const client = this.drawing.toClient(point);
91
+ return client && this.fromClient(client);
92
+ }
93
+ extent() {
94
+ const rect = this.element.getBoundingClientRect();
95
+ return {
96
+ x: this.element.clientWidth || rect.width,
97
+ y: this.element.clientHeight || rect.height,
98
+ };
99
+ }
100
+ rootBounds() {
101
+ const matrix = this.screenMatrix(), size = this.extent();
102
+ if (!matrix || !size.x || !size.y)
103
+ return null;
104
+ const points = [
105
+ { x: 0, y: 0 },
106
+ { x: size.x, y: 0 },
107
+ { x: size.x, y: size.y },
108
+ { x: 0, y: size.y },
109
+ ].map((p) => this.drawing.fromClient(matrix.apply(p)));
110
+ if (points.some((p) => !p))
111
+ return null;
112
+ return {
113
+ left: Math.min(...points.map((p) => p.x)),
114
+ right: Math.max(...points.map((p) => p.x)),
115
+ top: Math.min(...points.map((p) => p.y)),
116
+ bottom: Math.max(...points.map((p) => p.y)),
117
+ };
118
+ }
119
+ destroy() {
120
+ if (this.disposed)
121
+ return;
122
+ this.disposed = true;
123
+ if (this.pending !== null)
124
+ this.view.cancelAnimationFrame(this.pending);
125
+ const failures = [];
126
+ for (const callback of this.cleanups.reverse())
127
+ try {
128
+ callback();
129
+ }
130
+ catch (e) {
131
+ failures.push(e);
132
+ }
133
+ this.element.remove();
134
+ if (failures.length)
135
+ throw new AggregateError(failures, 'Editor overlay cleanup failed');
136
+ }
137
+ }
138
+ //# sourceMappingURL=surface.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"surface.js","sourceRoot":"","sources":["../../src/editor/surface.ts"],"names":[],"mappings":"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"}
package/dist/grid.d.ts ADDED
@@ -0,0 +1,23 @@
1
+ import type { Point, Svg } from '@rasamjs/core';
2
+ export interface GridOptions {
3
+ readonly size: number;
4
+ readonly origin?: Point;
5
+ readonly stroke?: string;
6
+ }
7
+ /** A camera-aware grid outside the exported SVG, with bounded rendering at extreme zoom. */
8
+ export declare class GridOverlay {
9
+ private readonly drawing;
10
+ private readonly options;
11
+ private readonly surface;
12
+ private readonly path;
13
+ private readonly origin;
14
+ private enabledState;
15
+ constructor(drawing: Svg, options: GridOptions);
16
+ get enabled(): boolean;
17
+ get isDestroyed(): boolean;
18
+ set enabled(value: boolean);
19
+ update(): this;
20
+ destroy(): void;
21
+ private render;
22
+ }
23
+ //# sourceMappingURL=grid.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grid.d.ts","sourceRoot":"","sources":["../src/grid.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,eAAe,CAAC;AAIhD,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,CAAC,EAAE,KAAK,CAAC;IACxB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B;AACD,4FAA4F;AAC5F,qBAAa,WAAW;IAMpB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAN1B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAU;IAClC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAiB;IACtC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAQ;IAC/B,OAAO,CAAC,YAAY,CAAQ;IAC5B,YACmB,OAAO,EAAE,GAAG,EACZ,OAAO,EAAE,WAAW,EAuBtC;IACD,IAAI,OAAO,IAAI,OAAO,CAErB;IACD,IAAI,WAAW,IAAI,OAAO,CAEzB;IACD,IAAI,OAAO,CAAC,KAAK,EAAE,OAAO,EAIzB;IACD,MAAM,IAAI,IAAI,CAGb;IACD,OAAO,IAAI,IAAI,CAEd;IACD,OAAO,CAAC,MAAM;CAuCf"}
package/dist/grid.js ADDED
@@ -0,0 +1,84 @@
1
+ import { assertPoint } from './snapping/options.js';
2
+ import { Surface, svg } from './editor/surface.js';
3
+ /** A camera-aware grid outside the exported SVG, with bounded rendering at extreme zoom. */
4
+ export class GridOverlay {
5
+ drawing;
6
+ options;
7
+ surface;
8
+ path;
9
+ origin;
10
+ enabledState = true;
11
+ constructor(drawing, options) {
12
+ this.drawing = drawing;
13
+ this.options = options;
14
+ if (!Number.isFinite(options?.size) || options.size <= 0)
15
+ throw new RangeError('Grid size must be positive and finite');
16
+ this.options = { ...options };
17
+ this.origin = { ...(options.origin ?? { x: 0, y: 0 }) };
18
+ assertPoint(this.origin, 'Grid origin');
19
+ if (options.stroke !== undefined &&
20
+ (typeof options.stroke !== 'string' || !options.stroke.trim()))
21
+ throw new TypeError('Grid stroke must be nonempty');
22
+ this.surface = new Surface(drawing, 'rasam-grid', () => this.render());
23
+ this.surface.element.style.zIndex = '-1';
24
+ this.surface.element.setAttribute('aria-hidden', 'true');
25
+ this.path = svg(drawing.el.ownerDocument, 'path', {
26
+ fill: 'none',
27
+ stroke: options.stroke ?? '#d9dee8',
28
+ 'stroke-width': 1,
29
+ 'vector-effect': 'non-scaling-stroke',
30
+ });
31
+ this.surface.element.append(this.path);
32
+ this.update();
33
+ }
34
+ get enabled() {
35
+ return this.enabledState;
36
+ }
37
+ get isDestroyed() {
38
+ return this.surface.isDestroyed;
39
+ }
40
+ set enabled(value) {
41
+ if (typeof value !== 'boolean')
42
+ throw new TypeError('enabled must be boolean');
43
+ this.enabledState = value;
44
+ this.update();
45
+ }
46
+ update() {
47
+ this.surface.update();
48
+ return this;
49
+ }
50
+ destroy() {
51
+ this.surface.destroy();
52
+ }
53
+ render() {
54
+ this.surface.element.style.display = this.enabledState ? '' : 'none';
55
+ const bounds = this.surface.rootBounds();
56
+ if (!this.enabledState || !bounds) {
57
+ this.path.setAttribute('d', '');
58
+ return;
59
+ }
60
+ const a = this.drawing.toClient({ x: 0, y: 0 }), b = this.drawing.toClient({ x: this.options.size, y: 0 });
61
+ const c = this.drawing.toClient({ x: 0, y: this.options.size });
62
+ if (!a || !b || !c)
63
+ return;
64
+ let step = this.options.size;
65
+ const pixels = Math.min(Math.hypot(b.x - a.x, b.y - a.y), Math.hypot(c.x - a.x, c.y - a.y));
66
+ if (pixels <= 0)
67
+ return;
68
+ while ((step / this.options.size) * pixels < 8 ||
69
+ (bounds.right - bounds.left + bounds.bottom - bounds.top) / step > 512)
70
+ step *= 2;
71
+ const segments = [];
72
+ const line = (a, b) => {
73
+ const from = this.surface.fromRoot(a), to = this.surface.fromRoot(b);
74
+ if (from && to)
75
+ segments.push(`M${from.x},${from.y}L${to.x},${to.y}`);
76
+ };
77
+ for (let x = this.origin.x + Math.ceil((bounds.left - this.origin.x) / step) * step; x <= bounds.right; x += step)
78
+ line({ x, y: bounds.top }, { x, y: bounds.bottom });
79
+ for (let y = this.origin.y + Math.ceil((bounds.top - this.origin.y) / step) * step; y <= bounds.bottom; y += step)
80
+ line({ x: bounds.left, y }, { x: bounds.right, y });
81
+ this.path.setAttribute('d', segments.join(''));
82
+ }
83
+ }
84
+ //# sourceMappingURL=grid.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grid.js","sourceRoot":"","sources":["../src/grid.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,qBAAqB,CAAC;AAOnD,4FAA4F;AAC5F,MAAM,OAAO,WAAW;IAMH,OAAO;IACP,OAAO;IANT,OAAO,CAAU;IACjB,IAAI,CAAiB;IACrB,MAAM,CAAQ;IACvB,YAAY,GAAG,IAAI,CAAC;IAC5B,YACmB,OAAY,EACZ,OAAoB;uBADpB,OAAO;uBACP,OAAO;QAExB,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,IAAI,OAAO,CAAC,IAAI,IAAI,CAAC;YACtD,MAAM,IAAI,UAAU,CAAC,uCAAuC,CAAC,CAAC;QAChE,IAAI,CAAC,OAAO,GAAG,EAAE,GAAG,OAAO,EAAE,CAAC;QAC9B,IAAI,CAAC,MAAM,GAAG,EAAE,GAAG,CAAC,OAAO,CAAC,MAAM,IAAI,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;QACxD,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;QACxC,IACE,OAAO,CAAC,MAAM,KAAK,SAAS;YAC5B,CAAC,OAAO,OAAO,CAAC,MAAM,KAAK,QAAQ,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;YAE9D,MAAM,IAAI,SAAS,CAAC,8BAA8B,CAAC,CAAC;QACtD,IAAI,CAAC,OAAO,GAAG,IAAI,OAAO,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;QACvE,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC;QACzC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,YAAY,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;QACzD,IAAI,CAAC,IAAI,GAAG,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,aAAa,EAAE,MAAM,EAAE;YAChD,IAAI,EAAE,MAAM;YACZ,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,SAAS;YACnC,cAAc,EAAE,CAAC;YACjB,eAAe,EAAE,oBAAoB;SACtC,CAAC,CAAC;QACH,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACvC,IAAI,CAAC,MAAM,EAAE,CAAC;IAChB,CAAC;IACD,IAAI,OAAO;QACT,OAAO,IAAI,CAAC,YAAY,CAAC;IAC3B,CAAC;IACD,IAAI,WAAW;QACb,OAAO,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC;IAClC,CAAC;IACD,IAAI,OAAO,CAAC,KAAc;QACxB,IAAI,OAAO,KAAK,KAAK,SAAS;YAAE,MAAM,IAAI,SAAS,CAAC,yBAAyB,CAAC,CAAC;QAC/E,IAAI,CAAC,YAAY,GAAG,KAAK,CAAC;QAC1B,IAAI,CAAC,MAAM,EAAE,CAAC;IAChB,CAAC;IACD,MAAM;QACJ,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;QACtB,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO;QACL,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;IACzB,CAAC;IACO,MAAM;QACZ,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;QACrE,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC;QACzC,IAAI,CAAC,IAAI,CAAC,YAAY,IAAI,CAAC,MAAM,EAAE,CAAC;YAClC,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;YAChC,OAAO;QACT,CAAC;QACD,MAAM,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAC7C,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;QAC5D,MAAM,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;QAChE,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC;YAAE,OAAO;QAC3B,IAAI,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;QAC7B,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC5F,IAAI,MAAM,IAAI,CAAC;YAAE,OAAO;QACxB,OACE,CAAC,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,MAAM,GAAG,CAAC;YACvC,CAAC,MAAM,CAAC,KAAK,GAAG,MAAM,CAAC,IAAI,GAAG,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,IAAI,GAAG,GAAG;YAEtE,IAAI,IAAI,CAAC,CAAC;QACZ,MAAM,QAAQ,GAAa,EAAE,CAAC;QAC9B,MAAM,IAAI,GAAG,CAAC,CAAQ,EAAE,CAAQ,EAAE,EAAE;YAClC,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,EACnC,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;YAChC,IAAI,IAAI,IAAI,EAAE;gBAAE,QAAQ,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;QACxE,CAAC,CAAC;QACF,KACE,IAAI,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,IAAI,EAC9E,CAAC,IAAI,MAAM,CAAC,KAAK,EACjB,CAAC,IAAI,IAAI;YAET,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,GAAG,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;QACtD,KACE,IAAI,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,IAAI,EAC7E,CAAC,IAAI,MAAM,CAAC,MAAM,EAClB,CAAC,IAAI,IAAI;YAET,IAAI,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;QACtD,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,GAAG,EAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;IACjD,CAAC;CACF"}
@@ -0,0 +1,30 @@
1
+ import type { Svg } from '@rasamjs/core';
2
+ import type { RulerGuide } from './advanced/types.js';
3
+ export interface RulerOptions {
4
+ readonly stroke?: string;
5
+ readonly onChange?: (guides: readonly NamedGuide[]) => void;
6
+ }
7
+ export interface NamedGuide extends RulerGuide {
8
+ readonly id: number;
9
+ }
10
+ export declare class RulerGuides {
11
+ private readonly drawing;
12
+ private readonly options;
13
+ private readonly surface;
14
+ private readonly values;
15
+ private next;
16
+ private drag;
17
+ constructor(drawing: Svg, options?: RulerOptions);
18
+ get guides(): readonly NamedGuide[];
19
+ get isDestroyed(): boolean;
20
+ add(axis: 'x' | 'y', position: number): number;
21
+ move(id: number, position: number): void;
22
+ remove(id: number): boolean;
23
+ clear(): void;
24
+ update(): this;
25
+ destroy(): void;
26
+ private changed;
27
+ private assertLive;
28
+ private render;
29
+ }
30
+ //# sourceMappingURL=rulers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rulers.d.ts","sourceRoot":"","sources":["../src/rulers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAS,GAAG,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAItD,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,SAAS,UAAU,EAAE,KAAK,IAAI,CAAC;CAC7D;AACD,MAAM,WAAW,UAAW,SAAQ,UAAU;IAC5C,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;CACrB;AACD,qBAAa,WAAW;IAMpB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAN1B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAU;IAClC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAiC;IACxD,OAAO,CAAC,IAAI,CAAK;IACjB,OAAO,CAAC,IAAI,CAAsD;IAClE,YACmB,OAAO,EAAE,GAAG,EACZ,OAAO,GAAE,YAAiB,EAiG5C;IACD,IAAI,MAAM,IAAI,SAAS,UAAU,EAAE,CAElC;IACD,IAAI,WAAW,IAAI,OAAO,CAEzB;IACD,GAAG,CAAC,IAAI,EAAE,GAAG,GAAG,GAAG,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAQ7C;IACD,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAOvC;IACD,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAK1B;IACD,KAAK,IAAI,IAAI,CAIZ;IACD,MAAM,IAAI,IAAI,CAGb;IACD,OAAO,IAAI,IAAI,CAGd;IACD,OAAO,CAAC,OAAO;IAIf,OAAO,CAAC,UAAU;IAGlB,OAAO,CAAC,MAAM;CA8Ef"}
package/dist/rulers.js ADDED
@@ -0,0 +1,234 @@
1
+ import { Surface, svg } from './editor/surface.js';
2
+ import { PointerDrag } from './editor/pointer.js';
3
+ export class RulerGuides {
4
+ drawing;
5
+ options;
6
+ surface;
7
+ values = new Map();
8
+ next = 1;
9
+ drag = null;
10
+ constructor(drawing, options = {}) {
11
+ this.drawing = drawing;
12
+ this.options = options;
13
+ if (options.stroke !== undefined &&
14
+ (typeof options.stroke !== 'string' || !options.stroke.trim()))
15
+ throw new TypeError('Guide stroke must be nonempty');
16
+ if (options.onChange !== undefined && typeof options.onChange !== 'function')
17
+ throw new TypeError('onChange must be a function');
18
+ this.options = { ...options };
19
+ this.surface = new Surface(drawing, 'rasam-rulers', () => this.render());
20
+ this.surface.element.style.zIndex = '30';
21
+ new PointerDrag(this.surface, {
22
+ start: (event) => {
23
+ const target = event.target;
24
+ const existing = target.closest('[data-guide-id]');
25
+ const ruler = target.closest('[data-ruler-axis]');
26
+ if (!existing && !ruler)
27
+ return false;
28
+ const point = this.drawing.fromClient({ x: event.clientX, y: event.clientY });
29
+ if (!point)
30
+ return false;
31
+ if (existing) {
32
+ const id = Number(existing.getAttribute('data-guide-id'));
33
+ this.drag = { id, before: this.values.get(id).position };
34
+ }
35
+ else {
36
+ const axis = ruler.getAttribute('data-ruler-axis');
37
+ this.drag = { id: this.add(axis, point[axis]), before: null };
38
+ }
39
+ return true;
40
+ },
41
+ move: (event) => {
42
+ const point = this.drawing.fromClient({ x: event.clientX, y: event.clientY });
43
+ if (this.drag && point) {
44
+ const guide = this.values.get(this.drag.id);
45
+ this.move(guide.id, point[guide.axis]);
46
+ }
47
+ },
48
+ end: (cancelled, event) => {
49
+ const drag = this.drag;
50
+ this.drag = null;
51
+ if (!drag)
52
+ return;
53
+ if (this.surface.isDestroyed)
54
+ return;
55
+ if (cancelled) {
56
+ if (drag.before === null)
57
+ this.remove(drag.id);
58
+ else
59
+ this.move(drag.id, drag.before);
60
+ }
61
+ else if (event) {
62
+ const point = this.surface.fromClient({ x: event.clientX, y: event.clientY }), size = this.surface.extent();
63
+ if (!point || point.x < 20 || point.y < 20 || point.x > size.x || point.y > size.y)
64
+ this.remove(drag.id);
65
+ }
66
+ },
67
+ });
68
+ this.surface.listen(this.surface.element, 'dblclick', ((event) => {
69
+ const guide = event.target.closest('[data-guide-id]');
70
+ if (guide) {
71
+ event.preventDefault();
72
+ this.remove(Number(guide.getAttribute('data-guide-id')));
73
+ }
74
+ }));
75
+ this.surface.listen(this.surface.element, 'keydown', ((event) => {
76
+ const target = event.target, handle = target.closest('[data-guide-id]');
77
+ if (handle) {
78
+ const id = Number(handle.getAttribute('data-guide-id')), guide = this.values.get(id);
79
+ const direction = guide.axis === 'x'
80
+ ? { ArrowLeft: -1, ArrowRight: 1 }
81
+ : { ArrowUp: -1, ArrowDown: 1 };
82
+ if (direction[event.key]) {
83
+ event.preventDefault();
84
+ event.stopPropagation();
85
+ this.move(id, guide.position + direction[event.key] * (event.shiftKey ? 10 : 1));
86
+ }
87
+ else if (event.key === 'Delete' || event.key === 'Backspace') {
88
+ event.preventDefault();
89
+ event.stopPropagation();
90
+ this.remove(id);
91
+ }
92
+ }
93
+ else if (event.key === 'Enter' || event.key === ' ') {
94
+ const ruler = target.closest('[data-ruler-axis]'), bounds = this.surface.rootBounds();
95
+ if (!ruler || !bounds)
96
+ return;
97
+ event.preventDefault();
98
+ event.stopPropagation();
99
+ const axis = ruler.getAttribute('data-ruler-axis');
100
+ const id = this.add(axis, axis === 'x' ? (bounds.left + bounds.right) / 2 : (bounds.top + bounds.bottom) / 2);
101
+ this.surface.element.querySelector(`[data-guide-id="${id}"]`)?.focus();
102
+ }
103
+ }));
104
+ this.surface.cleanup(() => {
105
+ this.drag = null;
106
+ this.values.clear();
107
+ });
108
+ this.update();
109
+ }
110
+ get guides() {
111
+ return Object.freeze([...this.values.values()].map((g) => Object.freeze({ ...g })));
112
+ }
113
+ get isDestroyed() {
114
+ return this.surface.isDestroyed;
115
+ }
116
+ add(axis, position) {
117
+ this.assertLive();
118
+ if (!['x', 'y'].includes(axis) || !Number.isFinite(position))
119
+ throw new TypeError('Guide needs an axis and finite position');
120
+ const id = this.next++;
121
+ this.values.set(id, { id, axis, position });
122
+ this.changed();
123
+ return id;
124
+ }
125
+ move(id, position) {
126
+ this.assertLive();
127
+ const guide = this.values.get(id);
128
+ if (!guide)
129
+ throw new RangeError('Unknown guide');
130
+ if (!Number.isFinite(position))
131
+ throw new TypeError('Guide position must be finite');
132
+ this.values.set(id, { ...guide, position });
133
+ this.changed();
134
+ }
135
+ remove(id) {
136
+ this.assertLive();
137
+ const removed = this.values.delete(id);
138
+ if (removed)
139
+ this.changed();
140
+ return removed;
141
+ }
142
+ clear() {
143
+ this.assertLive();
144
+ this.values.clear();
145
+ this.changed();
146
+ }
147
+ update() {
148
+ this.surface.update();
149
+ return this;
150
+ }
151
+ destroy() {
152
+ this.surface.destroy();
153
+ this.values.clear();
154
+ }
155
+ changed() {
156
+ this.update();
157
+ this.options.onChange?.(this.guides);
158
+ }
159
+ assertLive() {
160
+ if (this.isDestroyed)
161
+ throw new Error('Ruler guides are destroyed');
162
+ }
163
+ render() {
164
+ const document = this.drawing.el.ownerDocument, size = this.surface.extent(), bounds = this.surface.rootBounds();
165
+ const focus = document.activeElement;
166
+ const activeId = focus && this.surface.element.contains(focus) ? focus.getAttribute('data-guide-id') : null;
167
+ const parts = [];
168
+ for (const axis of ['x', 'y']) {
169
+ const rect = svg(document, 'rect', {
170
+ x: 0,
171
+ y: 0,
172
+ width: axis === 'x' ? 20 : size.x,
173
+ height: axis === 'x' ? size.y : 20,
174
+ fill: '#edf0f5',
175
+ stroke: '#bbc3cf',
176
+ 'data-ruler-axis': axis,
177
+ tabindex: 0,
178
+ role: 'button',
179
+ 'aria-label': `Drag ${axis === 'x' ? 'vertical' : 'horizontal'} guide`,
180
+ });
181
+ rect.style.pointerEvents = 'all';
182
+ parts.push(rect);
183
+ }
184
+ if (bounds) {
185
+ for (const guide of this.values.values()) {
186
+ const a = this.surface.fromRoot(guide.axis === 'x'
187
+ ? { x: guide.position, y: bounds.top }
188
+ : { x: bounds.left, y: guide.position });
189
+ const b = this.surface.fromRoot(guide.axis === 'x'
190
+ ? { x: guide.position, y: bounds.bottom }
191
+ : { x: bounds.right, y: guide.position });
192
+ if (!a || !b)
193
+ continue;
194
+ const line = svg(document, 'line', {
195
+ x1: a.x,
196
+ y1: a.y,
197
+ x2: b.x,
198
+ y2: b.y,
199
+ stroke: this.options.stroke ?? '#d23cdd',
200
+ 'stroke-width': 1,
201
+ 'vector-effect': 'non-scaling-stroke',
202
+ 'data-guide-id': guide.id,
203
+ tabindex: 0,
204
+ role: 'button',
205
+ 'aria-label': `${guide.axis} guide at ${guide.position}`,
206
+ });
207
+ line.style.pointerEvents = 'stroke';
208
+ line.style.cursor = guide.axis === 'x' ? 'ew-resize' : 'ns-resize';
209
+ parts.push(line);
210
+ }
211
+ for (const axis of ['x', 'y']) {
212
+ const low = axis === 'x' ? bounds.left : bounds.top, high = axis === 'x' ? bounds.right : bounds.bottom;
213
+ const step = Math.pow(10, Math.ceil(Math.log10(Math.max(1, (high - low) / 10))));
214
+ for (let value = Math.ceil(low / step) * step; value <= high; value += step) {
215
+ const p = this.surface.fromRoot(axis === 'x' ? { x: value, y: bounds.top } : { x: bounds.left, y: value });
216
+ if (!p)
217
+ continue;
218
+ const text = svg(document, 'text', {
219
+ x: axis === 'x' ? p.x + 2 : 2,
220
+ y: axis === 'x' ? 12 : p.y + 12,
221
+ 'font-size': 10,
222
+ fill: '#536174',
223
+ });
224
+ text.textContent = String(value);
225
+ parts.push(text);
226
+ }
227
+ }
228
+ }
229
+ this.surface.element.replaceChildren(...parts);
230
+ if (activeId)
231
+ this.surface.element.querySelector(`[data-guide-id="${activeId}"]`)?.focus();
232
+ }
233
+ }
234
+ //# sourceMappingURL=rulers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rulers.js","sourceRoot":"","sources":["../src/rulers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export { AdvancedSnapper } from '../advanced/snapper.js';
2
+ export type { AdvancedSnapperOptions, AdvancedSnapRequest, RulerGuide, RotationSnapRequest, RotationSnapSession, } from '../advanced/types.js';
3
+ //# sourceMappingURL=advanced.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"advanced.d.ts","sourceRoot":"","sources":["../../src/snapping/advanced.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,YAAY,EACV,sBAAsB,EACtB,mBAAmB,EACnB,UAAU,EACV,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,sBAAsB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { AdvancedSnapper } from '../advanced/snapper.js';
2
+ //# sourceMappingURL=advanced.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"advanced.js","sourceRoot":"","sources":["../../src/snapping/advanced.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC"}
@@ -2,5 +2,6 @@ import type { AnyNode, Box, Svg } from '@rasamjs/core';
2
2
  import type { ResolvedOptions } from './options.js';
3
3
  export declare function validateNodes(nodes: readonly AnyNode[], drawing: Svg): void;
4
4
  export declare function movingBox(nodes: readonly AnyNode[], drawing: Svg): Box | null;
5
+ export declare function targetNodes(drawing: Svg, nodes: readonly AnyNode[], options: ResolvedOptions): AnyNode[];
5
6
  export declare function measureTargets(drawing: Svg, nodes: readonly AnyNode[], options: ResolvedOptions): Box[];
6
7
  //# sourceMappingURL=targets.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"targets.d.ts","sourceRoot":"","sources":["../../src/snapping/targets.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,eAAe,CAAC;AAGvD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAEpD,wBAAgB,aAAa,CAAC,KAAK,EAAE,SAAS,OAAO,EAAE,EAAE,OAAO,EAAE,GAAG,GAAG,IAAI,CAW3E;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,SAAS,OAAO,EAAE,EAAE,OAAO,EAAE,GAAG,GAAG,GAAG,GAAG,IAAI,CAgB7E;AAWD,wBAAgB,cAAc,CAC5B,OAAO,EAAE,GAAG,EACZ,KAAK,EAAE,SAAS,OAAO,EAAE,EACzB,OAAO,EAAE,eAAe,GACvB,GAAG,EAAE,CA6BP"}
1
+ {"version":3,"file":"targets.d.ts","sourceRoot":"","sources":["../../src/snapping/targets.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,eAAe,CAAC;AAGvD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAEpD,wBAAgB,aAAa,CAAC,KAAK,EAAE,SAAS,OAAO,EAAE,EAAE,OAAO,EAAE,GAAG,GAAG,IAAI,CAW3E;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,SAAS,OAAO,EAAE,EAAE,OAAO,EAAE,GAAG,GAAG,GAAG,GAAG,IAAI,CAgB7E;AAWD,wBAAgB,WAAW,CACzB,OAAO,EAAE,GAAG,EACZ,KAAK,EAAE,SAAS,OAAO,EAAE,EACzB,OAAO,EAAE,eAAe,GACvB,OAAO,EAAE,CAwBX;AAED,wBAAgB,cAAc,CAC5B,OAAO,EAAE,GAAG,EACZ,KAAK,EAAE,SAAS,OAAO,EAAE,EACzB,OAAO,EAAE,eAAe,GACvB,GAAG,EAAE,CAQP"}
@@ -37,7 +37,7 @@ function visible(node) {
37
37
  return false;
38
38
  return true;
39
39
  }
40
- export function measureTargets(drawing, nodes, options) {
40
+ export function targetNodes(drawing, nodes, options) {
41
41
  const candidates = options.targets
42
42
  ? options.targets(nodes)
43
43
  : nodes.length
@@ -56,7 +56,11 @@ export function measureTargets(drawing, nodes, options) {
56
56
  }
57
57
  // All eligible nodes are attached to the same document; bit 4 means FOLLOWING.
58
58
  const ordered = [...eligible].sort((a, b) => a === b ? 0 : a.el.compareDocumentPosition(b.el) & 4 ? -1 : 1);
59
+ return ordered;
60
+ }
61
+ export function measureTargets(drawing, nodes, options) {
59
62
  const boxes = [];
63
+ const ordered = targetNodes(drawing, nodes, options);
60
64
  for (const node of ordered) {
61
65
  const bounds = boundsIn(node, drawing);
62
66
  if ('box' in bounds)
@@ -1 +1 @@
1
- {"version":3,"file":"targets.js","sourceRoot":"","sources":["../../src/snapping/targets.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"targets.js","sourceRoot":"","sources":["../../src/snapping/targets.ts"],"names":[],"mappings":"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"}