@mocanvas/editor 4.4.1 → 4.4.3

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/dist/index.js CHANGED
@@ -4,7 +4,7 @@ import { createRecordType, isIndexKey, createMigrationIds, uniqueId, isRecordsDi
4
4
  export { ZERO_INDEX_KEY, createComputedCache, getGraphemeLength, getGraphemes, getIndexAbove, getIndexBelow, getIndexBetween, getIndices, getIndicesAbove, getIndicesBelow, getIndicesBetween, iterateGraphemes, sortByIndex } from '@mocanvas/store';
5
5
  import { PATH_OP, FLAG, GEO_FLAG, EngineBridge, VERTEX_FLOATS, BATCH_WORDS, readClip } from '@mocanvas/wasm';
6
6
  export { EngineBridge, FLAG, GEO_FLAG, GEO_KIND, PATH_OP, getLoadedEngine, loadEngine, loadEngineSync } from '@mocanvas/wasm';
7
- import { createContext, useRef, useLayoutEffect, useEffect, useContext, useMemo, useCallback, useState, Component, useId } from 'react';
7
+ import { createContext, useEffect, useRef, useLayoutEffect, useContext, useMemo, useId, useCallback, useState, Component } from 'react';
8
8
  import { track as track$1, useValue } from '@mocanvas/state/react';
9
9
  export { track, useAtom, useComputed, useQuickReactor, useReactor, useStateTracking, useValue } from '@mocanvas/state/react';
10
10
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
@@ -14432,6 +14432,79 @@ var WebGL2Backend = class {
14432
14432
  function createBackend(canvas) {
14433
14433
  return new WebGL2Backend(canvas);
14434
14434
  }
14435
+ var UNSAFE = /[^a-zA-Z0-9_-]/g;
14436
+ function sanitizeId(id) {
14437
+ return `mc_${id.replace(UNSAFE, "_")}`;
14438
+ }
14439
+ var toSafeId = sanitizeId;
14440
+ function suffixSafeId(id, suffix) {
14441
+ return `${id}_${suffix.replace(UNSAFE, "_")}`;
14442
+ }
14443
+ function useUniqueSafeId(suffix) {
14444
+ const id = toSafeId(useId());
14445
+ return suffix === void 0 ? id : suffixSafeId(id, suffix);
14446
+ }
14447
+ function useSharedSafeId(name) {
14448
+ return toSafeId(name);
14449
+ }
14450
+ function DefaultCanvas() {
14451
+ const editor = useEditor();
14452
+ return /* @__PURE__ */ jsx(Canvas, { editor });
14453
+ }
14454
+ function DefaultBackground() {
14455
+ return /* @__PURE__ */ jsx("div", { className: "mocanvas-background", style: { position: "absolute", inset: 0, background: "var(--mocanvas-canvas, transparent)" } });
14456
+ }
14457
+ function DefaultGrid({ x, y, z, size }) {
14458
+ const id = useSharedSafeId("grid");
14459
+ const step = size * z;
14460
+ const fineOpacity = Math.min(1, Math.max(0, (step - 4) / 12));
14461
+ return /* @__PURE__ */ jsxs("svg", { className: "mocanvas-grid", style: { position: "absolute", inset: 0, width: "100%", height: "100%", pointerEvents: "none" }, "aria-hidden": "true", children: [
14462
+ /* @__PURE__ */ jsxs("defs", { children: [
14463
+ /* @__PURE__ */ jsx("pattern", { id, width: step, height: step, patternUnits: "userSpaceOnUse", patternTransform: `translate(${x * z} ${y * z})`, children: /* @__PURE__ */ jsx("circle", { cx: 0, cy: 0, r: 1, fill: "var(--mocanvas-grid, currentColor)", opacity: fineOpacity * 0.5 }) }),
14464
+ /* @__PURE__ */ jsx("pattern", { id: `${id}_major`, width: step * 5, height: step * 5, patternUnits: "userSpaceOnUse", patternTransform: `translate(${x * z} ${y * z})`, children: /* @__PURE__ */ jsx("circle", { cx: 0, cy: 0, r: 1.5, fill: "var(--mocanvas-grid, currentColor)", opacity: 0.8 }) })
14465
+ ] }),
14466
+ /* @__PURE__ */ jsx("rect", { width: "100%", height: "100%", fill: `url(#${id})` }),
14467
+ /* @__PURE__ */ jsx("rect", { width: "100%", height: "100%", fill: `url(#${id}_major)` })
14468
+ ] });
14469
+ }
14470
+ function DefaultSvgDefs({ children }) {
14471
+ return /* @__PURE__ */ jsx("svg", { className: "mocanvas-svg-defs", style: { position: "absolute", width: 0, height: 0, overflow: "hidden" }, "aria-hidden": "true", children: /* @__PURE__ */ jsx("defs", { children }) });
14472
+ }
14473
+ function DefaultCursor({ rotation, color, name, point }) {
14474
+ if (!point) return null;
14475
+ return /* @__PURE__ */ jsxs(
14476
+ "div",
14477
+ {
14478
+ className: "mocanvas-cursor",
14479
+ style: { position: "absolute", top: 0, left: 0, transform: `translate(${point.x}px, ${point.y}px) rotate(${rotation}rad)`, pointerEvents: "none" },
14480
+ children: [
14481
+ /* @__PURE__ */ jsx("svg", { width: "20", height: "24", viewBox: "0 0 20 24", "aria-hidden": "true", children: /* @__PURE__ */ jsx("path", { d: "M2 2l14 10-6 1.5L7 21z", fill: color ?? "currentColor", stroke: "var(--mocanvas-selection-fg, #fff)", strokeWidth: "1.5", strokeLinejoin: "round" }) }),
14482
+ name ? /* @__PURE__ */ jsx("div", { className: "mocanvas-cursor-name", style: { position: "absolute", left: 14, top: 18, background: color ?? "currentColor", color: "#fff", borderRadius: 4, padding: "1px 5px", font: "11px/1.4 system-ui, sans-serif", whiteSpace: "nowrap" }, children: name }) : null
14483
+ ]
14484
+ }
14485
+ );
14486
+ }
14487
+ function DefaultShapeWrapper({ children }) {
14488
+ return /* @__PURE__ */ jsx(Fragment, { children });
14489
+ }
14490
+ var MenuClickCapture = track$1(function MenuClickCapture2({ onClose }) {
14491
+ const editor = useMaybeEditor();
14492
+ const isOpen = (editor?.menus.getOpenMenus().length ?? 0) > 0;
14493
+ useEffect(() => {
14494
+ if (!isOpen || !editor) return;
14495
+ return () => void editor.menus.clearOpenMenus();
14496
+ }, [isOpen, editor]);
14497
+ if (!isOpen) return null;
14498
+ const style = { position: "absolute", inset: 0, zIndex: 1 };
14499
+ return /* @__PURE__ */ jsx("div", { className: "mocanvas-menu-click-capture", style, onPointerDown: () => onClose?.(), "aria-hidden": "true" });
14500
+ });
14501
+ function useIsCropping(shapeId) {
14502
+ const editor = useMaybeEditor();
14503
+ if (!editor) return false;
14504
+ if (!editor.isInAny("select.crop", "select.crop.idle", "select.crop.pointing_crop_handle", "select.crop.cropping")) return false;
14505
+ if (shapeId === void 0) return true;
14506
+ return editor.getOnlySelectedShape()?.id === shapeId;
14507
+ }
14435
14508
 
14436
14509
  // src/react/translations.ts
14437
14510
  function getLocaleChain(locale) {
@@ -14869,6 +14942,10 @@ function Canvas({ editor, className, style, children, components, indicatorOverl
14869
14942
  const hasChromeContextMenu = useEditorComponents().ContextMenu != null;
14870
14943
  const themeVars = useThemeCssVars(editor);
14871
14944
  const cameraVars = useCameraCssVars(editor);
14945
+ const isGridMode = useValue("isGridMode", () => editor.getInstanceState().isGridMode, [editor]);
14946
+ const camera = useValue("camera", () => editor.getCamera(), [editor]);
14947
+ const gridSize = useValue("gridSize", () => editor.getDocumentSettings().gridSize, [editor]);
14948
+ const Grid = components?.Grid === void 0 ? DefaultGrid : components.Grid;
14872
14949
  const Indicators = components?.Indicators ?? DefaultIndicators;
14873
14950
  const Brush = components?.Brush ?? (hasOverlay(editor, "brush") ? null : DefaultBrush);
14874
14951
  const Background = components?.Background;
@@ -14887,6 +14964,7 @@ function Canvas({ editor, className, style, children, components, indicatorOverl
14887
14964
  "data-testid": "mocanvas-container",
14888
14965
  children: [
14889
14966
  Background ? /* @__PURE__ */ jsx(Background, { editor }) : null,
14967
+ Grid !== null && isGridMode ? /* @__PURE__ */ jsx(Grid, { x: camera.x, y: camera.y, z: camera.z, size: gridSize }) : null,
14890
14968
  /* @__PURE__ */ jsx("canvas", { ref: canvasRef, style: { ...layerStyle, display: "block" } }),
14891
14969
  /* @__PURE__ */ jsx(OverlayLayer, { editor }),
14892
14970
  /* @__PURE__ */ jsx(IndicatorCanvas, { editor, util: indicatorOverlayUtil ?? ShapeIndicatorCompositor }),
@@ -15307,79 +15385,6 @@ function EditorPortal({ container, children }) {
15307
15385
  if (!target) return /* @__PURE__ */ jsx(Fragment, { children });
15308
15386
  return createPortal(children, target);
15309
15387
  }
15310
- var UNSAFE = /[^a-zA-Z0-9_-]/g;
15311
- function sanitizeId(id) {
15312
- return `mc_${id.replace(UNSAFE, "_")}`;
15313
- }
15314
- var toSafeId = sanitizeId;
15315
- function suffixSafeId(id, suffix) {
15316
- return `${id}_${suffix.replace(UNSAFE, "_")}`;
15317
- }
15318
- function useUniqueSafeId(suffix) {
15319
- const id = toSafeId(useId());
15320
- return suffix === void 0 ? id : suffixSafeId(id, suffix);
15321
- }
15322
- function useSharedSafeId(name) {
15323
- return toSafeId(name);
15324
- }
15325
- function DefaultCanvas() {
15326
- const editor = useEditor();
15327
- return /* @__PURE__ */ jsx(Canvas, { editor });
15328
- }
15329
- function DefaultBackground() {
15330
- return /* @__PURE__ */ jsx("div", { className: "mocanvas-background", style: { position: "absolute", inset: 0, background: "var(--mocanvas-canvas, transparent)" } });
15331
- }
15332
- function DefaultGrid({ x, y, z, size }) {
15333
- const id = useSharedSafeId("grid");
15334
- const step = size * z;
15335
- const fineOpacity = Math.min(1, Math.max(0, (step - 4) / 12));
15336
- return /* @__PURE__ */ jsxs("svg", { className: "mocanvas-grid", style: { position: "absolute", inset: 0, width: "100%", height: "100%", pointerEvents: "none" }, "aria-hidden": "true", children: [
15337
- /* @__PURE__ */ jsxs("defs", { children: [
15338
- /* @__PURE__ */ jsx("pattern", { id, width: step, height: step, patternUnits: "userSpaceOnUse", patternTransform: `translate(${x * z} ${y * z})`, children: /* @__PURE__ */ jsx("circle", { cx: 0, cy: 0, r: 1, fill: "var(--mocanvas-grid, currentColor)", opacity: fineOpacity * 0.5 }) }),
15339
- /* @__PURE__ */ jsx("pattern", { id: `${id}_major`, width: step * 5, height: step * 5, patternUnits: "userSpaceOnUse", patternTransform: `translate(${x * z} ${y * z})`, children: /* @__PURE__ */ jsx("circle", { cx: 0, cy: 0, r: 1.5, fill: "var(--mocanvas-grid, currentColor)", opacity: 0.8 }) })
15340
- ] }),
15341
- /* @__PURE__ */ jsx("rect", { width: "100%", height: "100%", fill: `url(#${id})` }),
15342
- /* @__PURE__ */ jsx("rect", { width: "100%", height: "100%", fill: `url(#${id}_major)` })
15343
- ] });
15344
- }
15345
- function DefaultSvgDefs({ children }) {
15346
- return /* @__PURE__ */ jsx("svg", { className: "mocanvas-svg-defs", style: { position: "absolute", width: 0, height: 0, overflow: "hidden" }, "aria-hidden": "true", children: /* @__PURE__ */ jsx("defs", { children }) });
15347
- }
15348
- function DefaultCursor({ rotation, color, name, point }) {
15349
- if (!point) return null;
15350
- return /* @__PURE__ */ jsxs(
15351
- "div",
15352
- {
15353
- className: "mocanvas-cursor",
15354
- style: { position: "absolute", top: 0, left: 0, transform: `translate(${point.x}px, ${point.y}px) rotate(${rotation}rad)`, pointerEvents: "none" },
15355
- children: [
15356
- /* @__PURE__ */ jsx("svg", { width: "20", height: "24", viewBox: "0 0 20 24", "aria-hidden": "true", children: /* @__PURE__ */ jsx("path", { d: "M2 2l14 10-6 1.5L7 21z", fill: color ?? "currentColor", stroke: "var(--mocanvas-selection-fg, #fff)", strokeWidth: "1.5", strokeLinejoin: "round" }) }),
15357
- name ? /* @__PURE__ */ jsx("div", { className: "mocanvas-cursor-name", style: { position: "absolute", left: 14, top: 18, background: color ?? "currentColor", color: "#fff", borderRadius: 4, padding: "1px 5px", font: "11px/1.4 system-ui, sans-serif", whiteSpace: "nowrap" }, children: name }) : null
15358
- ]
15359
- }
15360
- );
15361
- }
15362
- function DefaultShapeWrapper({ children }) {
15363
- return /* @__PURE__ */ jsx(Fragment, { children });
15364
- }
15365
- var MenuClickCapture = track$1(function MenuClickCapture2({ onClose }) {
15366
- const editor = useMaybeEditor();
15367
- const isOpen = (editor?.menus.getOpenMenus().length ?? 0) > 0;
15368
- useEffect(() => {
15369
- if (!isOpen || !editor) return;
15370
- return () => void editor.menus.clearOpenMenus();
15371
- }, [isOpen, editor]);
15372
- if (!isOpen) return null;
15373
- const style = { position: "absolute", inset: 0, zIndex: 1 };
15374
- return /* @__PURE__ */ jsx("div", { className: "mocanvas-menu-click-capture", style, onPointerDown: () => onClose?.(), "aria-hidden": "true" });
15375
- });
15376
- function useIsCropping(shapeId) {
15377
- const editor = useMaybeEditor();
15378
- if (!editor) return false;
15379
- if (!editor.isInAny("select.crop", "select.crop.idle", "select.crop.pointing_crop_handle", "select.crop.cropping")) return false;
15380
- if (shapeId === void 0) return true;
15381
- return editor.getOnlySelectedShape()?.id === shapeId;
15382
- }
15383
15388
  function useTransform(ref, x, y, scale, rotate, additionalOffset) {
15384
15389
  useLayoutEffect(() => {
15385
15390
  const elm = ref.current;