@canvas-commons/2d 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 (183) hide show
  1. package/LICENSE +22 -0
  2. package/editor/index.css +40 -0
  3. package/editor/index.js +525 -0
  4. package/editor/index.js.map +1 -0
  5. package/lib/index-OvpZ-GsA.d.ts +5673 -0
  6. package/lib/index-OvpZ-GsA.d.ts.map +1 -0
  7. package/lib/index.d.ts +2 -0
  8. package/lib/index.js +10326 -0
  9. package/lib/index.js.map +1 -0
  10. package/lib/jsx-dev-runtime.d.ts +2 -0
  11. package/lib/jsx-dev-runtime.js +2 -0
  12. package/lib/jsx-runtime.d.ts +2 -0
  13. package/lib/jsx-runtime.js +28 -0
  14. package/lib/jsx-runtime.js.map +1 -0
  15. package/package.json +79 -0
  16. package/src/editor/NodeInspectorConfig.tsx +76 -0
  17. package/src/editor/PreviewOverlayConfig.tsx +65 -0
  18. package/src/editor/Provider.tsx +109 -0
  19. package/src/editor/SceneGraphTabConfig.tsx +87 -0
  20. package/src/editor/icons/CircleIcon.tsx +7 -0
  21. package/src/editor/icons/CodeIcon.tsx +8 -0
  22. package/src/editor/icons/CurveIcon.tsx +7 -0
  23. package/src/editor/icons/GridIcon.tsx +7 -0
  24. package/src/editor/icons/IconMap.ts +35 -0
  25. package/src/editor/icons/ImgIcon.tsx +8 -0
  26. package/src/editor/icons/LayoutIcon.tsx +9 -0
  27. package/src/editor/icons/LineIcon.tsx +7 -0
  28. package/src/editor/icons/NodeIcon.tsx +7 -0
  29. package/src/editor/icons/RayIcon.tsx +7 -0
  30. package/src/editor/icons/RectIcon.tsx +7 -0
  31. package/src/editor/icons/ShapeIcon.tsx +7 -0
  32. package/src/editor/icons/TxtIcon.tsx +8 -0
  33. package/src/editor/icons/VideoIcon.tsx +7 -0
  34. package/src/editor/icons/View2DIcon.tsx +10 -0
  35. package/src/editor/index.css +0 -0
  36. package/src/editor/index.ts +19 -0
  37. package/src/editor/shortcuts.ts +27 -0
  38. package/src/editor/tree/DetachedRoot.tsx +27 -0
  39. package/src/editor/tree/NodeElement.tsx +72 -0
  40. package/src/editor/tree/TreeElement.tsx +70 -0
  41. package/src/editor/tree/TreeRoot.tsx +10 -0
  42. package/src/editor/tree/ViewRoot.tsx +20 -0
  43. package/src/editor/tree/index.module.scss +45 -0
  44. package/src/editor/tree/index.ts +4 -0
  45. package/src/editor/tree/navigation.ts +145 -0
  46. package/src/editor/tsconfig.build.json +5 -0
  47. package/src/editor/tsconfig.json +12 -0
  48. package/src/editor/tsdoc.json +4 -0
  49. package/src/editor/utils/SignalSet.ts +37 -0
  50. package/src/editor/utils/index.ts +1 -0
  51. package/src/editor/vite-env.d.ts +1 -0
  52. package/src/lib/code/CodeCursor.ts +468 -0
  53. package/src/lib/code/CodeDiffer.ts +77 -0
  54. package/src/lib/code/CodeFragment.ts +96 -0
  55. package/src/lib/code/CodeHighlighter.ts +73 -0
  56. package/src/lib/code/CodeMetrics.ts +47 -0
  57. package/src/lib/code/CodeRange.test.ts +113 -0
  58. package/src/lib/code/CodeRange.ts +222 -0
  59. package/src/lib/code/CodeScope.ts +100 -0
  60. package/src/lib/code/CodeSelection.ts +28 -0
  61. package/src/lib/code/CodeSignal.ts +348 -0
  62. package/src/lib/code/CodeTokenizer.ts +54 -0
  63. package/src/lib/code/DefaultHighlightStyle.ts +98 -0
  64. package/src/lib/code/LezerHighlighter.ts +113 -0
  65. package/src/lib/code/diff.test.ts +311 -0
  66. package/src/lib/code/diff.ts +319 -0
  67. package/src/lib/code/extractRange.ts +125 -0
  68. package/src/lib/code/index.ts +13 -0
  69. package/src/lib/components/Bezier.ts +103 -0
  70. package/src/lib/components/Camera.ts +401 -0
  71. package/src/lib/components/Circle.ts +310 -0
  72. package/src/lib/components/Code.ts +532 -0
  73. package/src/lib/components/CubicBezier.ts +115 -0
  74. package/src/lib/components/Curve.ts +460 -0
  75. package/src/lib/components/Grid.ts +134 -0
  76. package/src/lib/components/Icon.ts +153 -0
  77. package/src/lib/components/Img.ts +328 -0
  78. package/src/lib/components/Knot.ts +156 -0
  79. package/src/lib/components/Latex.ts +537 -0
  80. package/src/lib/components/Layout.ts +1101 -0
  81. package/src/lib/components/Line.ts +394 -0
  82. package/src/lib/components/Node.ts +1941 -0
  83. package/src/lib/components/Path.ts +132 -0
  84. package/src/lib/components/Polygon.ts +266 -0
  85. package/src/lib/components/QuadBezier.ts +103 -0
  86. package/src/lib/components/Ray.ts +126 -0
  87. package/src/lib/components/Rect.ts +219 -0
  88. package/src/lib/components/SVG.ts +853 -0
  89. package/src/lib/components/Shape.ts +322 -0
  90. package/src/lib/components/Spline.ts +318 -0
  91. package/src/lib/components/Txt.test.tsx +81 -0
  92. package/src/lib/components/Txt.ts +204 -0
  93. package/src/lib/components/TxtLeaf.ts +210 -0
  94. package/src/lib/components/Video.ts +368 -0
  95. package/src/lib/components/View2D.ts +85 -0
  96. package/src/lib/components/__logs__/image-without-source.ts +18 -0
  97. package/src/lib/components/__logs__/line-without-points.ts +31 -0
  98. package/src/lib/components/__logs__/reactive-playback-rate.ts +22 -0
  99. package/src/lib/components/__logs__/spline-with-insufficient-knots.ts +25 -0
  100. package/src/lib/components/__tests__/Camera.test.tsx +73 -0
  101. package/src/lib/components/__tests__/children.test.tsx +142 -0
  102. package/src/lib/components/__tests__/clone.test.tsx +126 -0
  103. package/src/lib/components/__tests__/fontInheritance.test.tsx +102 -0
  104. package/src/lib/components/__tests__/generatorTest.ts +27 -0
  105. package/src/lib/components/__tests__/mockScene2D.ts +50 -0
  106. package/src/lib/components/__tests__/query.test.tsx +122 -0
  107. package/src/lib/components/__tests__/state.test.tsx +60 -0
  108. package/src/lib/components/index.ts +26 -0
  109. package/src/lib/components/types.ts +35 -0
  110. package/src/lib/curves/ArcSegment.ts +169 -0
  111. package/src/lib/curves/CircleSegment.ts +99 -0
  112. package/src/lib/curves/CubicBezierSegment.ts +80 -0
  113. package/src/lib/curves/CurveDrawingInfo.ts +11 -0
  114. package/src/lib/curves/CurvePoint.ts +15 -0
  115. package/src/lib/curves/CurveProfile.ts +28 -0
  116. package/src/lib/curves/KnotInfo.ts +10 -0
  117. package/src/lib/curves/LineSegment.ts +75 -0
  118. package/src/lib/curves/Polynomial.ts +355 -0
  119. package/src/lib/curves/Polynomial2D.ts +62 -0
  120. package/src/lib/curves/PolynomialSegment.ts +151 -0
  121. package/src/lib/curves/QuadBezierSegment.ts +66 -0
  122. package/src/lib/curves/Segment.ts +31 -0
  123. package/src/lib/curves/UniformPolynomialCurveSampler.ts +93 -0
  124. package/src/lib/curves/createCurveProfileLerp.ts +471 -0
  125. package/src/lib/curves/getBezierSplineProfile.ts +227 -0
  126. package/src/lib/curves/getCircleProfile.ts +86 -0
  127. package/src/lib/curves/getPathProfile.ts +177 -0
  128. package/src/lib/curves/getPointAtDistance.ts +21 -0
  129. package/src/lib/curves/getPolylineProfile.test.ts +21 -0
  130. package/src/lib/curves/getPolylineProfile.ts +88 -0
  131. package/src/lib/curves/getRectProfile.ts +138 -0
  132. package/src/lib/curves/index.ts +16 -0
  133. package/src/lib/decorators/canvasStyleSignal.ts +15 -0
  134. package/src/lib/decorators/colorSignal.ts +9 -0
  135. package/src/lib/decorators/compound.ts +85 -0
  136. package/src/lib/decorators/computed.ts +18 -0
  137. package/src/lib/decorators/defaultStyle.ts +15 -0
  138. package/src/lib/decorators/filtersSignal.ts +133 -0
  139. package/src/lib/decorators/index.ts +10 -0
  140. package/src/lib/decorators/initializers.ts +32 -0
  141. package/src/lib/decorators/nodeName.ts +13 -0
  142. package/src/lib/decorators/signal.test.ts +89 -0
  143. package/src/lib/decorators/signal.ts +348 -0
  144. package/src/lib/decorators/spacingSignal.ts +15 -0
  145. package/src/lib/decorators/transformSignals.test.ts +858 -0
  146. package/src/lib/decorators/transformSignals.ts +1633 -0
  147. package/src/lib/decorators/vector2Signal.ts +35 -0
  148. package/src/lib/globals.d.ts +2 -0
  149. package/src/lib/index.ts +9 -0
  150. package/src/lib/jsx-dev-runtime.ts +2 -0
  151. package/src/lib/jsx-runtime.ts +45 -0
  152. package/src/lib/morphers/PathMorpher.ts +8 -0
  153. package/src/lib/morphers/defaultMorpher.ts +43 -0
  154. package/src/lib/morphers/index.ts +4 -0
  155. package/src/lib/morphers/manimMorpher.ts +658 -0
  156. package/src/lib/parse-svg-path.d.ts +14 -0
  157. package/src/lib/partials/Filter.ts +185 -0
  158. package/src/lib/partials/Gradient.ts +103 -0
  159. package/src/lib/partials/Pattern.ts +35 -0
  160. package/src/lib/partials/RoughConfig.ts +180 -0
  161. package/src/lib/partials/ShaderConfig.ts +122 -0
  162. package/src/lib/partials/index.ts +5 -0
  163. package/src/lib/partials/types.ts +58 -0
  164. package/src/lib/scenes/Scene2D.ts +167 -0
  165. package/src/lib/scenes/index.ts +3 -0
  166. package/src/lib/scenes/makeScene2D.ts +19 -0
  167. package/src/lib/scenes/useScene2D.ts +6 -0
  168. package/src/lib/tsconfig.build.json +5 -0
  169. package/src/lib/tsconfig.json +11 -0
  170. package/src/lib/tsdoc.json +4 -0
  171. package/src/lib/utils/CanvasUtils.ts +304 -0
  172. package/src/lib/utils/PathDataBuilder.ts +320 -0
  173. package/src/lib/utils/diff.test.ts +453 -0
  174. package/src/lib/utils/diff.ts +148 -0
  175. package/src/lib/utils/index.ts +5 -0
  176. package/src/lib/utils/is.ts +11 -0
  177. package/src/lib/utils/makeSignalExtensions.ts +29 -0
  178. package/src/lib/utils/rough.ts +513 -0
  179. package/src/lib/utils/withDefaults.tsx +26 -0
  180. package/src/tsconfig.base.json +18 -0
  181. package/src/tsconfig.build.json +8 -0
  182. package/src/tsconfig.json +5 -0
  183. package/tsconfig.project.json +7 -0
@@ -0,0 +1,513 @@
1
+ import {BBox, Spacing, Vector2} from '@canvas-commons/core';
2
+ import rough from 'roughjs';
3
+ import type {RoughCanvas} from 'roughjs/bin/canvas';
4
+ import type {Drawable, Options} from 'roughjs/bin/core';
5
+ import {RoughConfig, RoughFillStyle} from '../partials';
6
+ import {PossibleCanvasStyle} from '../partials/types';
7
+ import {
8
+ adjustRectRadius,
9
+ canvasStyleParser,
10
+ resolveCanvasStyle,
11
+ } from './CanvasUtils';
12
+
13
+ // Export Drawable type for use in other modules
14
+ export type {Drawable};
15
+
16
+ /**
17
+ * Cache for RoughCanvas instances per canvas element.
18
+ *
19
+ * @remarks
20
+ * We cache RoughCanvas instances to avoid recreating them for each draw call.
21
+ */
22
+ const RoughCanvasCache = new WeakMap<HTMLCanvasElement, RoughCanvas>();
23
+
24
+ /**
25
+ * Get or create a RoughCanvas instance for the given canvas context.
26
+ *
27
+ * @param context - The 2D rendering context
28
+ * @returns A RoughCanvas instance for drawing rough shapes
29
+ */
30
+ function getRoughCanvas(context: CanvasRenderingContext2D): RoughCanvas {
31
+ const canvas = context.canvas;
32
+ let rc = RoughCanvasCache.get(canvas);
33
+
34
+ if (!rc) {
35
+ rc = rough.canvas(canvas);
36
+ RoughCanvasCache.set(canvas, rc);
37
+ }
38
+
39
+ return rc;
40
+ }
41
+
42
+ /**
43
+ * Convert Canvas Commons fill style to a color string for Rough.js.
44
+ *
45
+ * @param style - The fill style (color, gradient, or pattern)
46
+ * @param context - The rendering context
47
+ * @returns A color string or undefined
48
+ */
49
+ function styleToColor(
50
+ style: PossibleCanvasStyle | null,
51
+ context: CanvasRenderingContext2D,
52
+ ): string | undefined {
53
+ if (style === null) {
54
+ return undefined;
55
+ }
56
+
57
+ // Parse the style to CanvasStyle
58
+ const parsedStyle = canvasStyleParser(style);
59
+
60
+ if (parsedStyle === null) {
61
+ return undefined;
62
+ }
63
+
64
+ // Resolve to canvas-compatible format
65
+ const resolvedStyle = resolveCanvasStyle(parsedStyle, context);
66
+
67
+ // Rough.js only accepts string colors, not gradients or patterns
68
+ // For gradients and patterns, return undefined (rough.js will use default)
69
+ if (typeof resolvedStyle === 'string') {
70
+ return resolvedStyle;
71
+ }
72
+
73
+ return undefined;
74
+ }
75
+
76
+ /**
77
+ * Convert Canvas Commons rough config to Rough.js options.
78
+ *
79
+ * @param config - Canvas Commons rough configuration
80
+ * @param fill - Fill style from shape
81
+ * @param stroke - Stroke style from shape
82
+ * @param strokeWidth - Line width from shape
83
+ * @param context - The rendering context
84
+ * @returns Rough.js options object
85
+ */
86
+ function configToRoughOptions(
87
+ config: Partial<RoughConfig>,
88
+ fill: PossibleCanvasStyle | null,
89
+ stroke: PossibleCanvasStyle | null,
90
+ strokeWidth: number,
91
+ context: CanvasRenderingContext2D,
92
+ ): Options {
93
+ const options: Options = {
94
+ roughness: config.roughness ?? 1,
95
+ bowing: config.bowing ?? 1,
96
+ seed: config.seed,
97
+ stroke: styleToColor(stroke, context),
98
+ strokeWidth: strokeWidth,
99
+ fill: styleToColor(fill, context),
100
+ fillStyle: config.fillStyle ?? 'hachure',
101
+ fillWeight: config.fillWeight,
102
+ hachureAngle: config.hachureAngle ?? -41,
103
+ hachureGap: config.hachureGap ?? strokeWidth * 4,
104
+ curveStepCount: config.curveStepCount,
105
+ simplification: config.simplification,
106
+ disableMultiStroke: config.disableMultiStroke,
107
+ disableMultiStrokeFill: config.disableMultiStrokeFill,
108
+ };
109
+
110
+ return options;
111
+ }
112
+
113
+ /**
114
+ * Convert a rounded rectangle to SVG path data.
115
+ *
116
+ * @param box - The bounding box of the rectangle
117
+ * @param radius - Corner radius values
118
+ * @param smoothCorners - Whether to use smooth corners (bezier curves)
119
+ * @param cornerSharpness - Sharpness of smooth corners
120
+ * @returns SVG path data string
121
+ */
122
+ export function roundedRectToSVGPath(
123
+ box: BBox,
124
+ radius: Spacing,
125
+ smoothCorners: boolean,
126
+ cornerSharpness: number,
127
+ ): string {
128
+ const topLeft = adjustRectRadius(radius.top, radius.right, radius.left, box);
129
+ const topRight = adjustRectRadius(
130
+ radius.right,
131
+ radius.top,
132
+ radius.bottom,
133
+ box,
134
+ );
135
+ const bottomRight = adjustRectRadius(
136
+ radius.bottom,
137
+ radius.left,
138
+ radius.right,
139
+ box,
140
+ );
141
+ const bottomLeft = adjustRectRadius(
142
+ radius.left,
143
+ radius.bottom,
144
+ radius.top,
145
+ box,
146
+ );
147
+
148
+ if (smoothCorners) {
149
+ const sharpness = (r: number): number => {
150
+ const val = r * cornerSharpness;
151
+ return r - val;
152
+ };
153
+
154
+ // Build SVG path with bezier curves for smooth corners
155
+ return [
156
+ `M ${box.left + topLeft} ${box.top}`,
157
+ `L ${box.right - topRight} ${box.top}`,
158
+ `C ${box.right - sharpness(topRight)} ${box.top} ${box.right} ${box.top + sharpness(topRight)} ${box.right} ${box.top + topRight}`,
159
+ `L ${box.right} ${box.bottom - bottomRight}`,
160
+ `C ${box.right} ${box.bottom - sharpness(bottomRight)} ${box.right - sharpness(bottomRight)} ${box.bottom} ${box.right - bottomRight} ${box.bottom}`,
161
+ `L ${box.left + bottomLeft} ${box.bottom}`,
162
+ `C ${box.left + sharpness(bottomLeft)} ${box.bottom} ${box.left} ${box.bottom - sharpness(bottomLeft)} ${box.left} ${box.bottom - bottomLeft}`,
163
+ `L ${box.left} ${box.top + topLeft}`,
164
+ `C ${box.left} ${box.top + sharpness(topLeft)} ${box.left + sharpness(topLeft)} ${box.top} ${box.left + topLeft} ${box.top}`,
165
+ 'Z',
166
+ ].join(' ');
167
+ }
168
+
169
+ // For regular rounded corners, we need to use arcs
170
+ // SVG arc command: A rx ry x-axis-rotation large-arc-flag sweep-flag x y
171
+ // Canvas arcTo draws a 90-degree arc, so we use: A r r 0 0 1 x y
172
+ const pathParts: string[] = [];
173
+
174
+ // Start at top-left corner (after the radius)
175
+ pathParts.push(`M ${box.left + topLeft} ${box.top}`);
176
+
177
+ // Top edge to top-right corner
178
+ pathParts.push(`L ${box.right - topRight} ${box.top}`);
179
+ if (topRight > 0) {
180
+ pathParts.push(
181
+ `A ${topRight} ${topRight} 0 0 1 ${box.right} ${box.top + topRight}`,
182
+ );
183
+ }
184
+
185
+ // Right edge to bottom-right corner
186
+ pathParts.push(`L ${box.right} ${box.bottom - bottomRight}`);
187
+ if (bottomRight > 0) {
188
+ pathParts.push(
189
+ `A ${bottomRight} ${bottomRight} 0 0 1 ${box.right - bottomRight} ${box.bottom}`,
190
+ );
191
+ }
192
+
193
+ // Bottom edge to bottom-left corner
194
+ pathParts.push(`L ${box.left + bottomLeft} ${box.bottom}`);
195
+ if (bottomLeft > 0) {
196
+ pathParts.push(
197
+ `A ${bottomLeft} ${bottomLeft} 0 0 1 ${box.left} ${box.bottom - bottomLeft}`,
198
+ );
199
+ }
200
+
201
+ // Left edge to top-left corner
202
+ pathParts.push(`L ${box.left} ${box.top + topLeft}`);
203
+ if (topLeft > 0) {
204
+ pathParts.push(
205
+ `A ${topLeft} ${topLeft} 0 0 1 ${box.left + topLeft} ${box.top}`,
206
+ );
207
+ }
208
+
209
+ // Close the path
210
+ pathParts.push('Z');
211
+
212
+ return pathParts.join(' ');
213
+ }
214
+
215
+ /**
216
+ * Generate a rough rectangle drawable.
217
+ *
218
+ * @param context - The 2D rendering context
219
+ * @param box - The bounding box of the rectangle
220
+ * @param config - Rough configuration
221
+ * @param fill - Fill style
222
+ * @param stroke - Stroke style
223
+ * @param strokeWidth - Line width
224
+ * @returns A Drawable object that can be cached and drawn
225
+ */
226
+ export function generateRoughRect(
227
+ context: CanvasRenderingContext2D,
228
+ box: BBox,
229
+ config: Partial<RoughConfig>,
230
+ fill: PossibleCanvasStyle | null,
231
+ stroke: PossibleCanvasStyle | null,
232
+ strokeWidth: number,
233
+ ): Drawable {
234
+ const rc = getRoughCanvas(context);
235
+ const options = configToRoughOptions(
236
+ config,
237
+ fill,
238
+ stroke,
239
+ strokeWidth,
240
+ context,
241
+ );
242
+
243
+ // Rough.js draws from top-left, canvas-commons uses center origin
244
+ const x = box.x;
245
+ const y = box.y;
246
+ const width = box.width;
247
+ const height = box.height;
248
+
249
+ return rc.generator.rectangle(x, y, width, height, options);
250
+ }
251
+
252
+ /**
253
+ * Draw a rough rectangle.
254
+ *
255
+ * @param context - The 2D rendering context
256
+ * @param box - The bounding box of the rectangle
257
+ * @param config - Rough configuration
258
+ * @param fill - Fill style
259
+ * @param stroke - Stroke style
260
+ * @param strokeWidth - Line width
261
+ */
262
+ export function drawRoughRect(
263
+ context: CanvasRenderingContext2D,
264
+ box: BBox,
265
+ config: Partial<RoughConfig>,
266
+ fill: PossibleCanvasStyle | null,
267
+ stroke: PossibleCanvasStyle | null,
268
+ strokeWidth: number,
269
+ ): void {
270
+ const drawable = generateRoughRect(
271
+ context,
272
+ box,
273
+ config,
274
+ fill,
275
+ stroke,
276
+ strokeWidth,
277
+ );
278
+ const rc = getRoughCanvas(context);
279
+ rc.draw(drawable);
280
+ }
281
+
282
+ /**
283
+ * Draw a cached rough drawable.
284
+ *
285
+ * @param context - The 2D rendering context
286
+ * @param drawable - The cached drawable to render
287
+ */
288
+ export function drawRoughDrawable(
289
+ context: CanvasRenderingContext2D,
290
+ drawable: Drawable,
291
+ ): void {
292
+ const rc = getRoughCanvas(context);
293
+ rc.draw(drawable);
294
+ }
295
+
296
+ /**
297
+ * Generate a rough rounded rectangle drawable.
298
+ *
299
+ * @param context - The 2D rendering context
300
+ * @param box - The bounding box of the rectangle
301
+ * @param radius - Corner radius values
302
+ * @param smoothCorners - Whether to use smooth corners
303
+ * @param cornerSharpness - Sharpness of smooth corners
304
+ * @param config - Rough configuration
305
+ * @param fill - Fill style
306
+ * @param stroke - Stroke style
307
+ * @param strokeWidth - Line width
308
+ * @returns A Drawable object that can be cached and drawn
309
+ */
310
+ export function generateRoughRoundedRect(
311
+ context: CanvasRenderingContext2D,
312
+ box: BBox,
313
+ radius: Spacing,
314
+ smoothCorners: boolean,
315
+ cornerSharpness: number,
316
+ config: Partial<RoughConfig>,
317
+ fill: PossibleCanvasStyle | null,
318
+ stroke: PossibleCanvasStyle | null,
319
+ strokeWidth: number,
320
+ ): Drawable {
321
+ // Convert the rounded rectangle to SVG path data
322
+ const pathData = roundedRectToSVGPath(
323
+ box,
324
+ radius,
325
+ smoothCorners,
326
+ cornerSharpness,
327
+ );
328
+
329
+ // Generate using rough path
330
+ return generateRoughPath(
331
+ context,
332
+ pathData,
333
+ config,
334
+ fill,
335
+ stroke,
336
+ strokeWidth,
337
+ );
338
+ }
339
+
340
+ /**
341
+ * Draw a rough rounded rectangle.
342
+ *
343
+ * @param context - The 2D rendering context
344
+ * @param box - The bounding box of the rectangle
345
+ * @param radius - Corner radius values
346
+ * @param smoothCorners - Whether to use smooth corners
347
+ * @param cornerSharpness - Sharpness of smooth corners
348
+ * @param config - Rough configuration
349
+ * @param fill - Fill style
350
+ * @param stroke - Stroke style
351
+ * @param strokeWidth - Line width
352
+ */
353
+ export function drawRoughRoundedRect(
354
+ context: CanvasRenderingContext2D,
355
+ box: BBox,
356
+ radius: Spacing,
357
+ smoothCorners: boolean,
358
+ cornerSharpness: number,
359
+ config: Partial<RoughConfig>,
360
+ fill: PossibleCanvasStyle | null,
361
+ stroke: PossibleCanvasStyle | null,
362
+ strokeWidth: number,
363
+ ): void {
364
+ const drawable = generateRoughRoundedRect(
365
+ context,
366
+ box,
367
+ radius,
368
+ smoothCorners,
369
+ cornerSharpness,
370
+ config,
371
+ fill,
372
+ stroke,
373
+ strokeWidth,
374
+ );
375
+ drawRoughDrawable(context, drawable);
376
+ }
377
+
378
+ /**
379
+ * Draw a rough circle/ellipse.
380
+ *
381
+ * @param context - The 2D rendering context
382
+ * @param center - Center point of the circle
383
+ * @param size - Size (width and height) of the ellipse
384
+ * @param config - Rough configuration
385
+ * @param fill - Fill style
386
+ * @param stroke - Stroke style
387
+ * @param strokeWidth - Line width
388
+ */
389
+ export function drawRoughCircle(
390
+ context: CanvasRenderingContext2D,
391
+ center: Vector2,
392
+ size: Vector2,
393
+ config: Partial<RoughConfig>,
394
+ fill: PossibleCanvasStyle | null,
395
+ stroke: PossibleCanvasStyle | null,
396
+ strokeWidth: number,
397
+ ): void {
398
+ const rc = getRoughCanvas(context);
399
+ const options = configToRoughOptions(
400
+ config,
401
+ fill,
402
+ stroke,
403
+ strokeWidth,
404
+ context,
405
+ );
406
+
407
+ const drawable = rc.generator.ellipse(
408
+ center.x,
409
+ center.y,
410
+ size.x * 2,
411
+ size.y * 2,
412
+ options,
413
+ );
414
+ rc.draw(drawable);
415
+ }
416
+
417
+ /**
418
+ * Generate a rough path drawable from SVG path data.
419
+ *
420
+ * @param context - The 2D rendering context
421
+ * @param pathData - SVG path string
422
+ * @param config - Rough configuration
423
+ * @param fill - Fill style
424
+ * @param stroke - Stroke style
425
+ * @param strokeWidth - Line width
426
+ * @returns A Drawable object that can be cached and drawn
427
+ */
428
+ export function generateRoughPath(
429
+ context: CanvasRenderingContext2D,
430
+ pathData: string,
431
+ config: Partial<RoughConfig>,
432
+ fill: PossibleCanvasStyle | null,
433
+ stroke: PossibleCanvasStyle | null,
434
+ strokeWidth: number,
435
+ ): Drawable {
436
+ const rc = getRoughCanvas(context);
437
+ const options = configToRoughOptions(
438
+ config,
439
+ fill,
440
+ stroke,
441
+ strokeWidth,
442
+ context,
443
+ );
444
+
445
+ return rc.generator.path(pathData, options);
446
+ }
447
+
448
+ /**
449
+ * Draw a rough path from SVG path data.
450
+ *
451
+ * @param context - The 2D rendering context
452
+ * @param pathData - SVG path string
453
+ * @param config - Rough configuration
454
+ * @param fill - Fill style
455
+ * @param stroke - Stroke style
456
+ * @param strokeWidth - Line width
457
+ */
458
+ export function drawRoughPath(
459
+ context: CanvasRenderingContext2D,
460
+ pathData: string,
461
+ config: Partial<RoughConfig>,
462
+ fill: PossibleCanvasStyle | null,
463
+ stroke: PossibleCanvasStyle | null,
464
+ strokeWidth: number,
465
+ ): void {
466
+ const drawable = generateRoughPath(
467
+ context,
468
+ pathData,
469
+ config,
470
+ fill,
471
+ stroke,
472
+ strokeWidth,
473
+ );
474
+ drawRoughDrawable(context, drawable);
475
+ }
476
+
477
+ /**
478
+ * Helper to create rough config from individual signals.
479
+ *
480
+ * @param roughness - Roughness value
481
+ * @param bowing - Bowing value
482
+ * @param fillStyle - Fill style
483
+ * @param fillWeight - Fill weight
484
+ * @param hachureAngle - Hachure angle
485
+ * @param hachureGap - Hachure gap
486
+ * @param seed - Random seed (always defined, generated from useRandom if not specified)
487
+ * @param disableMultiStroke - Disable multiple strokes for stroke
488
+ * @param disableMultiStrokeFill - Disable multiple strokes for fill
489
+ * @returns Partial rough configuration
490
+ */
491
+ export function createRoughConfig(
492
+ roughness: number,
493
+ bowing: number,
494
+ fillStyle: RoughFillStyle,
495
+ fillWeight: number | undefined,
496
+ hachureAngle: number,
497
+ hachureGap: number,
498
+ seed: number,
499
+ disableMultiStroke: boolean,
500
+ disableMultiStrokeFill: boolean,
501
+ ): Partial<RoughConfig> {
502
+ return {
503
+ roughness,
504
+ bowing,
505
+ fillStyle,
506
+ fillWeight,
507
+ hachureAngle,
508
+ hachureGap,
509
+ seed,
510
+ disableMultiStroke,
511
+ disableMultiStrokeFill,
512
+ };
513
+ }
@@ -0,0 +1,26 @@
1
+ import {FunctionComponent, NodeConstructor, PropsOf} from '../components';
2
+
3
+ /**
4
+ * Create a higher order component with default props.
5
+ *
6
+ * @example
7
+ * ```tsx
8
+ * const MyTxt = withDefaults(Txt, {
9
+ * fill: '#f3303f',
10
+ * });
11
+ *
12
+ * // ...
13
+ *
14
+ * view.add(<MyTxt>Hello, World!</MyTxt>);
15
+ * ```
16
+ *
17
+ * @param component - The base class or function component to wrap.
18
+ * @param defaults - The default props to apply.
19
+ */
20
+ export function withDefaults<T extends FunctionComponent | NodeConstructor>(
21
+ component: T,
22
+ defaults: PropsOf<T>,
23
+ ) {
24
+ const Node = component;
25
+ return (props: PropsOf<T>) => <Node {...defaults} {...props} />;
26
+ }
@@ -0,0 +1,18 @@
1
+ {
2
+ "compilerOptions": {
3
+ "rootDir": ".",
4
+ "outDir": "..",
5
+ "strict": true,
6
+ "noImplicitOverride": true,
7
+ "module": "esnext",
8
+ "target": "es2022",
9
+ "moduleResolution": "bundler",
10
+ "resolveJsonModule": true,
11
+ "declaration": true,
12
+ "declarationMap": true,
13
+ "inlineSourceMap": true,
14
+ "experimentalDecorators": true,
15
+ "skipLibCheck": true,
16
+ "composite": true
17
+ }
18
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "files": [],
3
+ "include": [],
4
+ "references": [
5
+ {"path": "./lib/tsconfig.build.json"},
6
+ {"path": "./editor/tsconfig.build.json"}
7
+ ]
8
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "files": [],
3
+ "include": [],
4
+ "references": [{"path": "./lib"}, {"path": "./editor"}]
5
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "extends": "@canvas-commons/core/tsconfig.project.json",
3
+ "compilerOptions": {
4
+ "jsx": "react-jsx",
5
+ "jsxImportSource": "@canvas-commons/2d"
6
+ }
7
+ }