@rollstack/rscanvas 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +386 -0
- package/dist/index.d.mts +269 -0
- package/dist/index.d.ts +269 -0
- package/dist/index.js +4545 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +4507 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +76 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
import * as orderedmap from 'orderedmap';
|
|
2
|
+
import * as prosemirror_model from 'prosemirror-model';
|
|
3
|
+
import { Schema } from 'prosemirror-model';
|
|
4
|
+
|
|
5
|
+
interface RSObjectOptionsConfig {
|
|
6
|
+
}
|
|
7
|
+
interface RSObjectConfig {
|
|
8
|
+
type: string;
|
|
9
|
+
x: number;
|
|
10
|
+
y: number;
|
|
11
|
+
width: number;
|
|
12
|
+
height: number;
|
|
13
|
+
rotation: number;
|
|
14
|
+
options: RSObjectOptionsConfig;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* State configuration for the canvas.
|
|
18
|
+
*/
|
|
19
|
+
interface RSCanvasStateConfig {
|
|
20
|
+
/**
|
|
21
|
+
* Objects configuration for the canvas as key-value pairs of object id and object config.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
/**
|
|
25
|
+
* Example (!!! claude-generated :| !!!!)
|
|
26
|
+
*
|
|
27
|
+
* ```ts
|
|
28
|
+
* const canvasState: RSCanvasStateConfig = {
|
|
29
|
+
* objects: {
|
|
30
|
+
* "text1": {
|
|
31
|
+
* type: "text",
|
|
32
|
+
* x: 100,
|
|
33
|
+
* y: 80,
|
|
34
|
+
* width: 200,
|
|
35
|
+
* height: 60,
|
|
36
|
+
* options: {
|
|
37
|
+
* text: "Hello world!",
|
|
38
|
+
* fontSize: 20,
|
|
39
|
+
* color: "#222"
|
|
40
|
+
* }
|
|
41
|
+
* },
|
|
42
|
+
* "image1": {
|
|
43
|
+
* type: "image",
|
|
44
|
+
* x: 250,
|
|
45
|
+
* y: 170,
|
|
46
|
+
* width: 120,
|
|
47
|
+
* height: 90,
|
|
48
|
+
* options: {
|
|
49
|
+
* url: "https://placekitten.com/200/300"
|
|
50
|
+
* }
|
|
51
|
+
* },
|
|
52
|
+
* "richtext1": {
|
|
53
|
+
* type: "richtext",
|
|
54
|
+
* x: 400,
|
|
55
|
+
* y: 230,
|
|
56
|
+
* width: 300,
|
|
57
|
+
* height: 120,
|
|
58
|
+
* options: {
|
|
59
|
+
* content: [
|
|
60
|
+
* { type: "paragraph", children: [{ text: "Supports " }, { text: "rich", bold: true }, { text: " text." }] }
|
|
61
|
+
* ]
|
|
62
|
+
* }
|
|
63
|
+
* }
|
|
64
|
+
* }
|
|
65
|
+
* }
|
|
66
|
+
* ```
|
|
67
|
+
*/
|
|
68
|
+
objects: Record<string, RSObjectConfig>;
|
|
69
|
+
}
|
|
70
|
+
interface RSObject<T> {
|
|
71
|
+
isStateEqual(state: T): boolean;
|
|
72
|
+
updateState(state: T): void;
|
|
73
|
+
getStateSFCT(state: T): void;
|
|
74
|
+
renderSFCT(node: HTMLElement): void;
|
|
75
|
+
destroy(): void;
|
|
76
|
+
}
|
|
77
|
+
interface RSObjectEditor {
|
|
78
|
+
destroy(): void;
|
|
79
|
+
}
|
|
80
|
+
interface RSEditorHandle<T extends RSObjectOptionsConfig> {
|
|
81
|
+
onCommit(newState: T): void;
|
|
82
|
+
onEnd(): void;
|
|
83
|
+
}
|
|
84
|
+
interface RSObjectEditingSessionHandle {
|
|
85
|
+
onEnd(): void;
|
|
86
|
+
}
|
|
87
|
+
type RSObjectEditorConstructor<T extends RSObjectOptionsConfig> = new (canvas: RSCanvasLike, state: T, container: HTMLElement, handle: RSEditorHandle<T>) => RSObjectEditor;
|
|
88
|
+
type RSObjectConstructor<T> = (state: T, invalidate: () => void) => RSObject<T>;
|
|
89
|
+
type RSCanvasEventType = 'mousedown' | 'mouseup' | 'mouseenter' | 'mouseleave' | 'mousemove' | 'click' | 'dblclick' | 'scroll' | 'keydown' | 'keyup' | 'highlight' | 'stateChanged';
|
|
90
|
+
type RSCanvasEvent = {
|
|
91
|
+
type: RSCanvasEventType;
|
|
92
|
+
viewX?: number;
|
|
93
|
+
viewY?: number;
|
|
94
|
+
deltaY?: number | null;
|
|
95
|
+
preventDefault?: () => void;
|
|
96
|
+
objectId?: string | null;
|
|
97
|
+
key?: string;
|
|
98
|
+
metaKey?: boolean;
|
|
99
|
+
ctrlKey?: boolean;
|
|
100
|
+
};
|
|
101
|
+
/** Handler for the highlight event. Receives the highlighted object ID or null when cleared. */
|
|
102
|
+
type RSCanvasHighlightHandler = (objectId: string | null) => void;
|
|
103
|
+
/** Handler for the stateChanged event. Receives the canvas instance. */
|
|
104
|
+
type RSCanvasStateChangedHandler<T = RSCanvasLike> = (canvas: T) => void;
|
|
105
|
+
/** Corner of an object's bounding box. */
|
|
106
|
+
type RSCanvasCorner = "top-left" | "top-right" | "bottom-left" | "bottom-right";
|
|
107
|
+
/** View-space coordinates (pixels relative to canvas element). */
|
|
108
|
+
interface RSViewXY {
|
|
109
|
+
viewX: number;
|
|
110
|
+
viewY: number;
|
|
111
|
+
}
|
|
112
|
+
/** World-space coordinates (canvas content space). */
|
|
113
|
+
interface RSWorldXY {
|
|
114
|
+
worldX: number;
|
|
115
|
+
worldY: number;
|
|
116
|
+
}
|
|
117
|
+
interface RSControl {
|
|
118
|
+
handleEvent(event: RSCanvasEvent): RSControl | null;
|
|
119
|
+
render(node: HTMLElement): void;
|
|
120
|
+
destroy(): void;
|
|
121
|
+
}
|
|
122
|
+
interface RSCanvasLike {
|
|
123
|
+
changeCursor(cursor: string): void;
|
|
124
|
+
getScale(): number;
|
|
125
|
+
toWorldX(viewX: number): number;
|
|
126
|
+
toWorldY(viewY: number): number;
|
|
127
|
+
objectIdAtXY(viewX: number, viewY: number): string | null;
|
|
128
|
+
objectIdAtLowerRightCorner(viewX: number, viewY: number): string | null;
|
|
129
|
+
objectIdAtUpperRightCorner(viewX: number, viewY: number): string | null;
|
|
130
|
+
getCornerWorldXYSFCT(objectId: string, corner: RSCanvasCorner, out: RSWorldXY): boolean;
|
|
131
|
+
getCanvasWidth(): number;
|
|
132
|
+
getCanvasHeight(): number;
|
|
133
|
+
getObjectNode(objectId: string): {
|
|
134
|
+
getX(): number;
|
|
135
|
+
getY(): number;
|
|
136
|
+
getWidth(): number;
|
|
137
|
+
getHeight(): number;
|
|
138
|
+
} | null;
|
|
139
|
+
resizeObject(objectId: string, dw: number, dh: number): void;
|
|
140
|
+
rotateObject(objectId: string, dAngle: number): void;
|
|
141
|
+
translateObject(objectId: string, dx: number, dy: number): void;
|
|
142
|
+
translate(dx: number, dy: number): void;
|
|
143
|
+
scaleAtXY(scaleFactor: number, viewX: number, viewY: number): void;
|
|
144
|
+
highlightObject(id: string): void;
|
|
145
|
+
clearHighlight(): void;
|
|
146
|
+
setHighlightColor(color: string): void;
|
|
147
|
+
getHighlightedObjectId(): string | null;
|
|
148
|
+
canEditObject(objectId: string): boolean;
|
|
149
|
+
startEditSession(objectId: string, handle: RSObjectEditingSessionHandle): boolean;
|
|
150
|
+
deleteObject(objectId: string): void;
|
|
151
|
+
addControlToFront(ControlCtor: new (canvas: RSCanvasLike) => RSControl): RSControl;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
type RSCanvasOptions = {
|
|
155
|
+
width?: number;
|
|
156
|
+
height?: number;
|
|
157
|
+
};
|
|
158
|
+
declare class RSCanvas implements RSCanvasLike {
|
|
159
|
+
private readonly _containerNode;
|
|
160
|
+
private readonly _innerContainerNode;
|
|
161
|
+
private readonly _overlayNode;
|
|
162
|
+
private _width;
|
|
163
|
+
private _height;
|
|
164
|
+
private _scale;
|
|
165
|
+
private _translateX;
|
|
166
|
+
private _translateY;
|
|
167
|
+
private _objects;
|
|
168
|
+
private _objectConstructors;
|
|
169
|
+
private _objectEditorConstructors;
|
|
170
|
+
private _editingObjectId;
|
|
171
|
+
private _highlightedObjectId;
|
|
172
|
+
private _highlightColor;
|
|
173
|
+
private _activeControl;
|
|
174
|
+
private _rafId;
|
|
175
|
+
private _listeners;
|
|
176
|
+
private _destroyed;
|
|
177
|
+
private _dirtyTransform;
|
|
178
|
+
private _pendingState;
|
|
179
|
+
private _internalStateVersion;
|
|
180
|
+
private _pendingStateVersion;
|
|
181
|
+
private readonly _cornerPosScratch;
|
|
182
|
+
private _resizeObserver;
|
|
183
|
+
private _boundingClientRect;
|
|
184
|
+
private readonly _controls;
|
|
185
|
+
private readonly _onPaint;
|
|
186
|
+
private readonly _localInvalidate;
|
|
187
|
+
constructor(container: HTMLDivElement, options?: RSCanvasOptions);
|
|
188
|
+
private _setupEventListeners;
|
|
189
|
+
private _updateBoundingClientRect;
|
|
190
|
+
private _viewXFromEvent;
|
|
191
|
+
private _viewYFromEvent;
|
|
192
|
+
private _emit;
|
|
193
|
+
private _paint;
|
|
194
|
+
private _invalidate;
|
|
195
|
+
private _cornerWorldPosSFCT;
|
|
196
|
+
private _emitStateChanged;
|
|
197
|
+
private _dispatchToControls;
|
|
198
|
+
private _createPointerEvent;
|
|
199
|
+
private _onMouseDown;
|
|
200
|
+
private _onMouseUp;
|
|
201
|
+
private _onMouseEnter;
|
|
202
|
+
private _onMouseLeave;
|
|
203
|
+
private _onMouseMove;
|
|
204
|
+
private _onClick;
|
|
205
|
+
private _onDblClick;
|
|
206
|
+
private _onScroll;
|
|
207
|
+
private _onKeyDown;
|
|
208
|
+
private _onKeyUp;
|
|
209
|
+
private _on;
|
|
210
|
+
private _getObjectEditorConstructor;
|
|
211
|
+
private _updateObjectTree;
|
|
212
|
+
onHighlight(fn: RSCanvasHighlightHandler): void;
|
|
213
|
+
onStateChanged(fn: RSCanvasStateChangedHandler<RSCanvas>): void;
|
|
214
|
+
registerObjectType(objectType: string, constructor: RSObjectConstructor<RSObjectOptionsConfig>): void;
|
|
215
|
+
registerObjectTypeEditor(objectType: string, constructor: RSObjectEditorConstructor<RSObjectOptionsConfig>): void;
|
|
216
|
+
setState(state: RSCanvasStateConfig): void;
|
|
217
|
+
getStateSFCT(state: RSCanvasStateConfig): void;
|
|
218
|
+
changeCursor(cursor: string): void;
|
|
219
|
+
addControlToFront(ControlCtor: new (canvas: RSCanvasLike) => RSControl): RSControl;
|
|
220
|
+
getScale(): number;
|
|
221
|
+
toWorldX(viewX: number): number;
|
|
222
|
+
toWorldY(viewY: number): number;
|
|
223
|
+
toViewX(worldX: number): number;
|
|
224
|
+
toViewY(worldY: number): number;
|
|
225
|
+
objectIdAtXY(viewX: number, viewY: number): string | null;
|
|
226
|
+
objectIdAtLowerRightCorner(viewX: number, viewY: number): string | null;
|
|
227
|
+
objectIdAtUpperRightCorner(viewX: number, viewY: number): string | null;
|
|
228
|
+
getCornerWorldXYSFCT(objectId: string, corner: RSCanvasCorner, out: RSWorldXY): boolean;
|
|
229
|
+
getCanvasWidth(): number;
|
|
230
|
+
getCanvasHeight(): number;
|
|
231
|
+
getObjectNode(objectId: string): {
|
|
232
|
+
getX(): number;
|
|
233
|
+
getY(): number;
|
|
234
|
+
getWidth(): number;
|
|
235
|
+
getHeight(): number;
|
|
236
|
+
} | null;
|
|
237
|
+
resizeObject(objectId: string, dw: number, dh: number): void;
|
|
238
|
+
rotateObject(objectId: string, dAngle: number): void;
|
|
239
|
+
translateObject(objectId: string, dx: number, dy: number): void;
|
|
240
|
+
translate(dx: number, dy: number): void;
|
|
241
|
+
scaleAtXY(scaleFactor: number, viewX: number, viewY: number): void;
|
|
242
|
+
center(): void;
|
|
243
|
+
highlightObject(id: string): void;
|
|
244
|
+
clearHighlight(): void;
|
|
245
|
+
setHighlightColor(color: string): void;
|
|
246
|
+
getHighlightedObjectId(): string | null;
|
|
247
|
+
canEditObject(objectId: string): boolean;
|
|
248
|
+
startEditSession(objectId: string, hostHandle: RSObjectEditingSessionHandle): boolean;
|
|
249
|
+
deleteObject(objectId: string): void;
|
|
250
|
+
saveToImage(callback: (blob: Blob) => void): Promise<void>;
|
|
251
|
+
destroy(): void;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
interface RSRichTextObjectOptionsConfig extends RSObjectOptionsConfig {
|
|
255
|
+
doc: Record<string, unknown>;
|
|
256
|
+
}
|
|
257
|
+
declare const richTextSchema: Schema<keyof orderedmap.default<prosemirror_model.NodeSpec>, keyof orderedmap.default<prosemirror_model.MarkSpec>>;
|
|
258
|
+
|
|
259
|
+
interface RSTextObjectOptionsConfig extends RSObjectOptionsConfig {
|
|
260
|
+
text: string;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
interface RSImageObjectOptionsConfig extends RSObjectOptionsConfig {
|
|
264
|
+
type: "url" | "localStorage";
|
|
265
|
+
url?: string;
|
|
266
|
+
key?: string;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
export { RSCanvas, type RSCanvasCorner, type RSCanvasEvent, type RSCanvasEventType, type RSCanvasHighlightHandler, type RSCanvasLike, type RSCanvasOptions, type RSCanvasStateChangedHandler, type RSCanvasStateConfig, type RSControl, type RSEditorHandle, type RSImageObjectOptionsConfig, type RSObject, type RSObjectConfig, type RSObjectConstructor, type RSObjectEditingSessionHandle, type RSObjectEditor, type RSObjectEditorConstructor, type RSObjectOptionsConfig, type RSRichTextObjectOptionsConfig, type RSTextObjectOptionsConfig, type RSViewXY, type RSWorldXY, richTextSchema };
|