@mocanvas/mocanvas 1.0.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.
@@ -0,0 +1,550 @@
1
+ /*
2
+ * Default UI theme.
3
+ *
4
+ * Everything is driven by custom properties declared on the editor container
5
+ * (`.mocanvas`), so an app can restyle the whole UI — chrome drawn on the
6
+ * canvas included — by overriding a handful of variables. See `docs/UI.md`.
7
+ *
8
+ * Every text/background pair below is at or above 4.5:1 in both palettes, and
9
+ * every icon or canvas-chrome stroke is at or above 3:1 against the surface it
10
+ * sits on.
11
+ */
12
+
13
+ .mocanvas,
14
+ .mocanvas-panel,
15
+ .mocanvas-layer {
16
+ /* surfaces */
17
+ --mocanvas-ui-panel: #ffffff;
18
+ --mocanvas-ui-panel-border: #d6d9e0;
19
+ --mocanvas-ui-control: rgba(16, 24, 40, 0.06);
20
+ --mocanvas-ui-text: #16181d;
21
+ --mocanvas-ui-muted: #5c6070;
22
+ --mocanvas-ui-accent: #2563eb;
23
+ --mocanvas-ui-accent-fg: #ffffff;
24
+ --mocanvas-ui-accent-soft: rgba(37, 99, 235, 0.12);
25
+ --mocanvas-ui-hover: rgba(16, 24, 40, 0.06);
26
+ --mocanvas-ui-active: rgba(16, 24, 40, 0.13);
27
+ --mocanvas-ui-shadow: 0 8px 24px rgba(15, 18, 25, 0.1), 0 1px 3px rgba(15, 18, 25, 0.08);
28
+ --mocanvas-ui-tip-bg: #16181d;
29
+ --mocanvas-ui-tip-fg: #f6f7f9;
30
+ --mocanvas-ui-tip-muted: #a9aeb9;
31
+
32
+ /* metrics */
33
+ --mocanvas-ui-radius: 12px;
34
+ --mocanvas-ui-radius-sm: 8px;
35
+ --mocanvas-ui-btn: 40px;
36
+ --mocanvas-ui-icon: 20px;
37
+ --mocanvas-ui-gap: 2px;
38
+ --mocanvas-ui-pad: 4px;
39
+ --mocanvas-ui-pad-lg: 10px;
40
+ --mocanvas-ui-inset: 12px;
41
+ /*
42
+ * Width the bottom-left and bottom-right docks (zoom bar, stats chip) reserve
43
+ * on either side of the centred toolbar. The toolbar wraps rather than grow
44
+ * into that reservation, so the three can never collide.
45
+ */
46
+ --mocanvas-ui-dock: 300px;
47
+ /* Height the bottom edge occupies; the style panel stops above it. */
48
+ --mocanvas-ui-bottom-dock: 62px;
49
+ --mocanvas-ui-font: system-ui, -apple-system, "Segoe UI", sans-serif;
50
+ --mocanvas-ui-mono: ui-monospace, SFMono-Regular, Menlo, monospace;
51
+
52
+ /*
53
+ * Canvas chrome, read by the editor's indicator layer. These are deliberately
54
+ * NOT redefined for the dark UI: the canvas keeps its own background, which
55
+ * does not follow `prefers-color-scheme`. The values clear 3:1 against both a
56
+ * light (#f9fafb: 4.45 and 3.69) and a dark (#1b1d22: 3.63 and 4.37) canvas,
57
+ * so an app that darkens the canvas only needs to swap `-selection-fg`, the
58
+ * fill behind a solid handle.
59
+ */
60
+ --mocanvas-selection: #2f6fe4;
61
+ --mocanvas-selection-fg: #ffffff;
62
+ --mocanvas-brush-fill: rgba(47, 111, 228, 0.12);
63
+ --mocanvas-snap: #cf3fe0;
64
+ }
65
+
66
+ @media (prefers-color-scheme: dark) {
67
+ .mocanvas,
68
+ .mocanvas-panel,
69
+ .mocanvas-layer {
70
+ --mocanvas-ui-panel: #1b1d22;
71
+ --mocanvas-ui-panel-border: #3c404a;
72
+ --mocanvas-ui-control: rgba(255, 255, 255, 0.08);
73
+ --mocanvas-ui-text: #eceef3;
74
+ --mocanvas-ui-muted: #a4a9b4;
75
+ --mocanvas-ui-accent: #6ea8fe;
76
+ --mocanvas-ui-accent-fg: #0e1116;
77
+ --mocanvas-ui-accent-soft: rgba(110, 168, 254, 0.18);
78
+ --mocanvas-ui-hover: rgba(255, 255, 255, 0.09);
79
+ --mocanvas-ui-active: rgba(255, 255, 255, 0.18);
80
+ --mocanvas-ui-shadow: 0 10px 28px rgba(0, 0, 0, 0.5), 0 1px 2px rgba(0, 0, 0, 0.6);
81
+ --mocanvas-ui-tip-bg: #2b2f37;
82
+ --mocanvas-ui-tip-fg: #f2f4f8;
83
+ --mocanvas-ui-tip-muted: #b9bec9;
84
+ }
85
+ }
86
+
87
+ /* --- surfaces ----------------------------------------------------------- */
88
+
89
+ .mocanvas-panel {
90
+ position: absolute;
91
+ z-index: 10;
92
+ display: flex;
93
+ align-items: center;
94
+ gap: var(--mocanvas-ui-gap);
95
+ box-sizing: border-box;
96
+ padding: var(--mocanvas-ui-pad);
97
+ background: var(--mocanvas-ui-panel);
98
+ border: 1px solid var(--mocanvas-ui-panel-border);
99
+ border-radius: var(--mocanvas-ui-radius);
100
+ box-shadow: var(--mocanvas-ui-shadow);
101
+ color: var(--mocanvas-ui-text);
102
+ font-family: var(--mocanvas-ui-font);
103
+ font-size: 13px;
104
+ pointer-events: auto;
105
+ user-select: none;
106
+ -webkit-user-select: none;
107
+ }
108
+
109
+ /*
110
+ * `left: 50%` alone caps an absolutely positioned box at half the container
111
+ * width (shrink-to-fit uses `container - left`), which made the toolbar wrap on
112
+ * any viewport narrower than twice its own width. Anchoring both edges and
113
+ * letting the margins centre a `max-content` box has no such cap.
114
+ */
115
+ .mocanvas-toolbar {
116
+ left: var(--mocanvas-ui-inset);
117
+ right: var(--mocanvas-ui-inset);
118
+ bottom: var(--mocanvas-ui-inset);
119
+ width: max-content;
120
+ max-width: calc(100% - 2 * (var(--mocanvas-ui-inset) + var(--mocanvas-ui-dock)));
121
+ margin-inline: auto;
122
+ flex-wrap: wrap;
123
+ justify-content: center;
124
+ }
125
+
126
+ .mocanvas-zoombar {
127
+ left: var(--mocanvas-ui-inset);
128
+ bottom: var(--mocanvas-ui-inset);
129
+ }
130
+
131
+ .mocanvas-stylepanel {
132
+ right: var(--mocanvas-ui-inset);
133
+ top: var(--mocanvas-ui-inset);
134
+ /*
135
+ * Sized so the content column still holds two 3-button groups side by side
136
+ * (2 × 124 + 4) with a classic 17px scrollbar taking its share of the width.
137
+ */
138
+ width: 292px;
139
+ max-height: calc(100% - 2 * var(--mocanvas-ui-inset) - var(--mocanvas-ui-bottom-dock));
140
+ overflow-y: auto;
141
+ scrollbar-width: thin;
142
+ overscroll-behavior: contain;
143
+ flex-direction: column;
144
+ align-items: stretch;
145
+ gap: var(--mocanvas-ui-pad-lg);
146
+ padding: var(--mocanvas-ui-pad-lg);
147
+ /*
148
+ * Scroll affordance: two fixed gradients painted against the panel and two
149
+ * scrolling shadows behind them. The shadow only shows while content is
150
+ * clipped in that direction, so a short panel looks flat.
151
+ */
152
+ background-image:
153
+ linear-gradient(var(--mocanvas-ui-panel) 30%, rgba(0, 0, 0, 0)),
154
+ linear-gradient(rgba(0, 0, 0, 0), var(--mocanvas-ui-panel) 70%),
155
+ radial-gradient(farthest-side at 50% 0, rgba(15, 18, 25, 0.22), rgba(0, 0, 0, 0)),
156
+ radial-gradient(farthest-side at 50% 100%, rgba(15, 18, 25, 0.22), rgba(0, 0, 0, 0));
157
+ background-position: 0 0, 0 100%, 0 0, 0 100%;
158
+ background-size: 100% 26px, 100% 26px, 100% 9px, 100% 9px;
159
+ background-repeat: no-repeat;
160
+ background-attachment: local, local, scroll, scroll;
161
+ }
162
+
163
+ .mocanvas-stats {
164
+ right: var(--mocanvas-ui-inset);
165
+ bottom: var(--mocanvas-ui-inset);
166
+ flex-direction: column;
167
+ align-items: flex-start;
168
+ gap: 1px;
169
+ padding: 6px 9px;
170
+ font-family: var(--mocanvas-ui-mono);
171
+ font-size: 10.5px;
172
+ line-height: 1.45;
173
+ color: var(--mocanvas-ui-muted);
174
+ border-radius: var(--mocanvas-ui-radius-sm);
175
+ }
176
+
177
+ .mocanvas-stats b {
178
+ color: var(--mocanvas-ui-text);
179
+ font-weight: 600;
180
+ }
181
+
182
+ .mocanvas-divider {
183
+ flex: 0 0 auto;
184
+ align-self: stretch;
185
+ width: 1px;
186
+ margin: 4px 3px;
187
+ background: var(--mocanvas-ui-panel-border);
188
+ }
189
+
190
+ /*
191
+ * Narrow layouts. The bottom edge holds three panels — zoom bar, toolbar,
192
+ * stats — whose natural widths add up to about 1290px. Below that the toolbar
193
+ * takes a row of its own and stops reserving the docks; below 560px the stats
194
+ * chip moves out of the bottom edge altogether.
195
+ */
196
+ @media (max-width: 1290px) {
197
+ .mocanvas,
198
+ .mocanvas-panel {
199
+ /* the toolbar now has a row of its own above the zoom bar */
200
+ --mocanvas-ui-bottom-dock: 124px;
201
+ }
202
+
203
+ .mocanvas-toolbar {
204
+ --mocanvas-ui-dock: 0px;
205
+ bottom: calc(2 * var(--mocanvas-ui-inset) + 50px);
206
+ }
207
+ }
208
+
209
+ /*
210
+ * Phone-width: the bottom edge cannot hold the zoom bar and the stats chip side
211
+ * by side, so each takes a row of its own and the style panel keeps the top,
212
+ * spanning the width and capped at a share of the height.
213
+ */
214
+ @media (max-width: 560px) {
215
+ .mocanvas-stats {
216
+ bottom: calc(2 * var(--mocanvas-ui-inset) + 50px);
217
+ }
218
+
219
+ .mocanvas-toolbar {
220
+ bottom: calc(3 * var(--mocanvas-ui-inset) + 112px);
221
+ }
222
+
223
+ .mocanvas-stylepanel {
224
+ left: var(--mocanvas-ui-inset);
225
+ right: var(--mocanvas-ui-inset);
226
+ width: auto;
227
+ max-height: 42%;
228
+ }
229
+ }
230
+
231
+ /* --- buttons ------------------------------------------------------------ */
232
+
233
+ .mocanvas-btn {
234
+ position: relative;
235
+ flex: 0 0 auto;
236
+ display: inline-flex;
237
+ align-items: center;
238
+ justify-content: center;
239
+ gap: 2px;
240
+ box-sizing: border-box;
241
+ width: var(--mocanvas-ui-btn);
242
+ height: var(--mocanvas-ui-btn);
243
+ min-width: var(--mocanvas-ui-btn);
244
+ padding: 0;
245
+ margin: 0;
246
+ border: none;
247
+ border-radius: var(--mocanvas-ui-radius-sm);
248
+ background: transparent;
249
+ color: var(--mocanvas-ui-text);
250
+ font: inherit;
251
+ font-weight: 600;
252
+ line-height: 1;
253
+ cursor: pointer;
254
+ transition: background-color 0.12s ease, color 0.12s ease, transform 0.08s ease;
255
+ }
256
+
257
+ .mocanvas-btn--wide {
258
+ width: auto;
259
+ min-width: 56px;
260
+ padding: 0 10px;
261
+ font-variant-numeric: tabular-nums;
262
+ }
263
+
264
+ .mocanvas-btn:hover:not(:disabled) {
265
+ background: var(--mocanvas-ui-hover);
266
+ }
267
+
268
+ .mocanvas-btn:active:not(:disabled) {
269
+ background: var(--mocanvas-ui-active);
270
+ transform: scale(0.94);
271
+ }
272
+
273
+ .mocanvas-btn[aria-pressed="true"],
274
+ .mocanvas-btn[aria-checked="true"] {
275
+ background: var(--mocanvas-ui-accent);
276
+ color: var(--mocanvas-ui-accent-fg);
277
+ }
278
+
279
+ .mocanvas-btn[aria-pressed="true"]:hover,
280
+ .mocanvas-btn[aria-checked="true"]:hover,
281
+ .mocanvas-btn[aria-pressed="true"]:active,
282
+ .mocanvas-btn[aria-checked="true"]:active {
283
+ background: var(--mocanvas-ui-accent);
284
+ /* The accent already reads as "on"; darkening it would break its contrast
285
+ with the label, so pressed buttons signal hover with the ring instead. */
286
+ box-shadow: inset 0 0 0 2px var(--mocanvas-ui-panel), inset 0 0 0 3px var(--mocanvas-ui-accent);
287
+ }
288
+
289
+ /* The tint carries the "open" signal on its own; tinting the icon as well
290
+ would drop it to 4.37:1 against that tint in the light palette. */
291
+ .mocanvas-btn[aria-expanded="true"]:not([aria-pressed="true"]):not([aria-checked="true"]) {
292
+ background: var(--mocanvas-ui-accent-soft);
293
+ }
294
+
295
+ .mocanvas-btn:disabled {
296
+ opacity: 0.35;
297
+ cursor: default;
298
+ }
299
+
300
+ .mocanvas-btn:focus,
301
+ .mocanvas-swatch:focus {
302
+ outline: none;
303
+ }
304
+
305
+ /* The 2px offset keeps a ring of panel colour between an accent-filled button
306
+ and its accent ring, so focus stays visible on a pressed control. */
307
+ .mocanvas-btn:focus-visible,
308
+ .mocanvas-swatch:focus-visible,
309
+ .mocanvas-slider:focus-visible {
310
+ outline: 2px solid var(--mocanvas-ui-accent);
311
+ outline-offset: 2px;
312
+ z-index: 1;
313
+ }
314
+
315
+ /* Buttons take their icon size from the token; icons used as inline marks
316
+ (the "mixed" badge, the picker chevron) keep the size they ask for. */
317
+ .mocanvas-btn > .mocanvas-icon {
318
+ width: var(--mocanvas-ui-icon);
319
+ height: var(--mocanvas-ui-icon);
320
+ }
321
+
322
+ /* --- style panel groups ------------------------------------------------- */
323
+
324
+ .mocanvas-group {
325
+ display: flex;
326
+ flex-direction: column;
327
+ gap: 8px;
328
+ }
329
+
330
+ .mocanvas-group + .mocanvas-group {
331
+ padding-top: var(--mocanvas-ui-pad-lg);
332
+ border-top: 1px solid var(--mocanvas-ui-panel-border);
333
+ }
334
+
335
+ .mocanvas-seg {
336
+ display: flex;
337
+ flex-wrap: wrap;
338
+ gap: var(--mocanvas-ui-gap);
339
+ }
340
+
341
+ .mocanvas-seg .mocanvas-btn:not([aria-checked="true"]):not([aria-pressed="true"]) {
342
+ background: var(--mocanvas-ui-control);
343
+ }
344
+
345
+ .mocanvas-seg .mocanvas-btn:hover:not([aria-checked="true"]):not([aria-pressed="true"]) {
346
+ background: var(--mocanvas-ui-accent-soft);
347
+ }
348
+
349
+ .mocanvas-seg--split {
350
+ flex-wrap: nowrap;
351
+ justify-content: space-between;
352
+ gap: 4px;
353
+ }
354
+
355
+ .mocanvas-row-label {
356
+ display: flex;
357
+ align-items: center;
358
+ justify-content: space-between;
359
+ gap: 6px;
360
+ margin-bottom: 4px;
361
+ color: var(--mocanvas-ui-muted);
362
+ font-size: 10px;
363
+ font-weight: 600;
364
+ letter-spacing: 0.5px;
365
+ text-transform: uppercase;
366
+ }
367
+
368
+ .mocanvas-mixed {
369
+ display: inline-flex;
370
+ align-items: center;
371
+ gap: 3px;
372
+ color: var(--mocanvas-ui-muted);
373
+ font-size: 9.5px;
374
+ font-weight: 500;
375
+ letter-spacing: 0;
376
+ text-transform: none;
377
+ }
378
+
379
+ /* --- the shape picker --------------------------------------------------- */
380
+
381
+ .mocanvas-picker {
382
+ display: flex;
383
+ align-items: center;
384
+ justify-content: space-between;
385
+ box-sizing: border-box;
386
+ width: 100%;
387
+ height: var(--mocanvas-ui-btn);
388
+ padding: 0 8px 0 10px;
389
+ border: none;
390
+ border-radius: var(--mocanvas-ui-radius-sm);
391
+ background: var(--mocanvas-ui-control);
392
+ color: var(--mocanvas-ui-text);
393
+ font: inherit;
394
+ font-size: 12px;
395
+ cursor: pointer;
396
+ transition: background-color 0.12s ease;
397
+ }
398
+
399
+ .mocanvas-picker:hover {
400
+ background: var(--mocanvas-ui-accent-soft);
401
+ }
402
+
403
+ .mocanvas-picker:active {
404
+ background: var(--mocanvas-ui-active);
405
+ }
406
+
407
+ .mocanvas-picker:focus {
408
+ outline: none;
409
+ }
410
+
411
+ .mocanvas-picker:focus-visible {
412
+ outline: 2px solid var(--mocanvas-ui-accent);
413
+ outline-offset: 2px;
414
+ }
415
+
416
+ .mocanvas-picker > span {
417
+ display: inline-flex;
418
+ align-items: center;
419
+ gap: 8px;
420
+ }
421
+
422
+ .mocanvas-picker .mocanvas-icon:last-child {
423
+ color: var(--mocanvas-ui-muted);
424
+ }
425
+
426
+ /* --- swatches ----------------------------------------------------------- */
427
+
428
+ /* The button is a full 40×40 target; the disc inside it is the visual mark. */
429
+ .mocanvas-swatch {
430
+ display: inline-flex;
431
+ align-items: center;
432
+ justify-content: center;
433
+ box-sizing: border-box;
434
+ width: var(--mocanvas-ui-btn);
435
+ height: var(--mocanvas-ui-btn);
436
+ padding: 0;
437
+ border: none;
438
+ border-radius: var(--mocanvas-ui-radius-sm);
439
+ background: transparent;
440
+ cursor: pointer;
441
+ transition: background-color 0.12s ease, transform 0.08s ease;
442
+ }
443
+
444
+ .mocanvas-swatch > span {
445
+ display: block;
446
+ width: 22px;
447
+ height: 22px;
448
+ border-radius: 50%;
449
+ background: var(--mocanvas-swatch-color, currentColor);
450
+ box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.18);
451
+ transition: box-shadow 0.12s ease;
452
+ }
453
+
454
+ .mocanvas-swatch:hover {
455
+ background: var(--mocanvas-ui-hover);
456
+ }
457
+
458
+ .mocanvas-swatch:active {
459
+ transform: scale(0.92);
460
+ background: var(--mocanvas-ui-active);
461
+ }
462
+
463
+ .mocanvas-swatch[aria-checked="true"] > span {
464
+ box-shadow: 0 0 0 2px var(--mocanvas-ui-panel), 0 0 0 4px var(--mocanvas-ui-accent), inset 0 0 0 1px rgba(0, 0, 0, 0.18);
465
+ }
466
+
467
+ .mocanvas-swatches {
468
+ display: grid;
469
+ grid-template-columns: repeat(6, minmax(var(--mocanvas-ui-btn), 1fr));
470
+ gap: var(--mocanvas-ui-gap);
471
+ }
472
+
473
+ /* --- slider ------------------------------------------------------------- */
474
+
475
+ .mocanvas-slider {
476
+ width: 100%;
477
+ height: 24px;
478
+ margin: 0;
479
+ accent-color: var(--mocanvas-ui-accent);
480
+ cursor: pointer;
481
+ }
482
+
483
+ /* --- popovers ----------------------------------------------------------- */
484
+
485
+ /*
486
+ * Fixed, not absolute: a popover anchored inside `.mocanvas-stylepanel` would
487
+ * otherwise be clipped by that panel's own scroll container. Placement is
488
+ * computed against the viewport in `overlays.tsx`.
489
+ */
490
+ .mocanvas-popover {
491
+ position: fixed;
492
+ z-index: 30;
493
+ display: grid;
494
+ grid-template-columns: repeat(var(--mocanvas-popover-cols, 5), var(--mocanvas-ui-btn));
495
+ gap: var(--mocanvas-ui-gap);
496
+ padding: 6px;
497
+ background: var(--mocanvas-ui-panel);
498
+ border: 1px solid var(--mocanvas-ui-panel-border);
499
+ border-radius: var(--mocanvas-ui-radius);
500
+ box-shadow: var(--mocanvas-ui-shadow);
501
+ color: var(--mocanvas-ui-text);
502
+ font-family: var(--mocanvas-ui-font);
503
+ pointer-events: auto;
504
+ }
505
+
506
+ /* --- tooltip ------------------------------------------------------------ */
507
+
508
+ /*
509
+ * One shared, viewport-clamped tooltip. A CSS-only `::after` version cannot
510
+ * avoid the viewport edge, and is clipped outright inside a scrolling panel.
511
+ */
512
+ .mocanvas-tooltip {
513
+ position: fixed;
514
+ z-index: 40;
515
+ display: flex;
516
+ align-items: center;
517
+ height: 22px;
518
+ padding: 0 9px;
519
+ gap: 6px;
520
+ border-radius: 6px;
521
+ background: var(--mocanvas-ui-tip-bg);
522
+ color: var(--mocanvas-ui-tip-fg);
523
+ font-family: var(--mocanvas-ui-font);
524
+ font-size: 11px;
525
+ font-weight: 500;
526
+ letter-spacing: 0.1px;
527
+ line-height: 22px;
528
+ white-space: nowrap;
529
+ pointer-events: none;
530
+ }
531
+
532
+ .mocanvas-tooltip kbd {
533
+ color: var(--mocanvas-ui-tip-muted);
534
+ font: inherit;
535
+ }
536
+
537
+ @media (prefers-reduced-motion: reduce) {
538
+ .mocanvas-btn,
539
+ .mocanvas-swatch,
540
+ .mocanvas-swatch > span,
541
+ .mocanvas-picker {
542
+ transition: none;
543
+ }
544
+ }
545
+
546
+ .mocanvas-more {
547
+ position: relative;
548
+ display: inline-flex;
549
+ flex: 0 0 auto;
550
+ }
package/package.json ADDED
@@ -0,0 +1,77 @@
1
+ {
2
+ "name": "@mocanvas/mocanvas",
3
+ "version": "1.0.0",
4
+ "description": "An infinite-canvas SDK for the web: React component, default shapes, tools and UI, on a Rust/WebAssembly engine.",
5
+ "license": "MIT",
6
+ "author": "Symbio Digital",
7
+ "homepage": "https://github.com/SYMBIO/mocanvas/tree/main/packages/mocanvas#readme",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/SYMBIO/mocanvas.git",
11
+ "directory": "packages/mocanvas"
12
+ },
13
+ "bugs": {
14
+ "url": "https://github.com/SYMBIO/mocanvas/issues"
15
+ },
16
+ "keywords": [
17
+ "canvas",
18
+ "infinite-canvas",
19
+ "whiteboard",
20
+ "webgl",
21
+ "webassembly",
22
+ "wasm",
23
+ "rust",
24
+ "editor",
25
+ "tldraw",
26
+ "react",
27
+ "sdk",
28
+ "drawing",
29
+ "diagram"
30
+ ],
31
+ "type": "module",
32
+ "engines": {
33
+ "node": ">=20"
34
+ },
35
+ "files": [
36
+ "dist",
37
+ "README.md",
38
+ "LICENSE"
39
+ ],
40
+ "sideEffects": [
41
+ "*.css",
42
+ "./src/install.ts",
43
+ "./dist/index.js"
44
+ ],
45
+ "main": "./dist/index.js",
46
+ "types": "./dist/index.d.ts",
47
+ "exports": {
48
+ ".": {
49
+ "types": "./dist/index.d.ts",
50
+ "import": "./dist/index.js"
51
+ },
52
+ "./package.json": "./package.json"
53
+ },
54
+ "publishConfig": {
55
+ "access": "public"
56
+ },
57
+ "dependencies": {
58
+ "@mocanvas/editor": "1.0.0",
59
+ "@mocanvas/store": "1.0.0",
60
+ "@mocanvas/state": "1.0.0"
61
+ },
62
+ "devDependencies": {
63
+ "@types/react": "^19.1.0",
64
+ "@types/react-dom": "^19.1.0",
65
+ "react": "^19.1.0",
66
+ "react-dom": "^19.1.0"
67
+ },
68
+ "peerDependencies": {
69
+ "react": ">=18",
70
+ "react-dom": ">=18"
71
+ },
72
+ "scripts": {
73
+ "build": "tsup",
74
+ "test": "vitest run",
75
+ "typecheck": "tsc --noEmit"
76
+ }
77
+ }