@mocanvas/editor 4.5.1 → 4.6.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/dist/index.d.ts CHANGED
@@ -13138,14 +13138,25 @@ declare function DefaultCanvas(): react.JSX.Element;
13138
13138
  */
13139
13139
  declare function DefaultBackground(): react.JSX.Element;
13140
13140
  /**
13141
- * The grid, drawn in page space with an SVG pattern.
13142
- *
13143
- * Two patterns rather than one: a fine cell at the document's grid step and a
13144
- * heavier one every fifth cell, so the eye can count without the fine grid
13145
- * having to be dark enough to read on its own. Both fade out as the camera
13146
- * zooms away, because a grid finer than a few screen pixels is noise.
13147
- */
13148
- declare function DefaultGrid({ x, y, z, size }: TLGridProps): react.JSX.Element;
13141
+ * The grid: one lattice of dots on the document's own grid step, drawn with an
13142
+ * SVG pattern in page space.
13143
+ *
13144
+ * **The dot scales with the world, and the lattice fades as a whole.** Those
13145
+ * are the two rules, and each fixes a direction the old grid got backwards. A
13146
+ * fixed 1px dot vanishes as you zoom in — the cell grows to 80 screen pixels
13147
+ * and what is left is a speck every 80px, which reads as no grid at all — so
13148
+ * the radius is a fraction of the cell, floored and capped so it never
13149
+ * disappears and never becomes a blob. And a second, heavier lattice every
13150
+ * fifth cell at a fixed opacity is exactly the dense sheen a zoomed-out canvas
13151
+ * must not have: one lattice, one opacity, gone below {@link GRID_GONE_PX}.
13152
+ *
13153
+ * **No re-levelling**, deliberately: the spacing is always the document's step
13154
+ * rather than a power of it chosen per zoom. Dots are then magnets — a corner
13155
+ * on a multiple of the step sits on a dot at *every* zoom — and re-levelling
13156
+ * breaks that on the intermediate steps, which is worse than a grid that
13157
+ * bows out when it gets too dense to mean anything.
13158
+ */
13159
+ declare function DefaultGrid({ x, y, z, size }: TLGridProps): react.JSX.Element | null;
13149
13160
  /**
13150
13161
  * Drawn in place of one shape whose body threw.
13151
13162
  *
package/dist/index.js CHANGED
@@ -276,16 +276,16 @@ var Vec = class _Vec {
276
276
  * The point on the segment `A`→`B` closest to `P`. With `clamp` false the
277
277
  * segment is treated as the infinite line through `A` and `B`.
278
278
  */
279
- static NearestPointOnLineSegment(A, B, P, clamp3 = true) {
279
+ static NearestPointOnLineSegment(A, B, P, clamp4 = true) {
280
280
  const ab = _Vec.Sub(B, A);
281
281
  const l2 = _Vec.Dpr(ab, ab);
282
282
  if (l2 === 0) return _Vec.From(A);
283
283
  let t = _Vec.Dpr(_Vec.Sub(P, A), ab) / l2;
284
- if (clamp3) t = Math.max(0, Math.min(1, t));
284
+ if (clamp4) t = Math.max(0, Math.min(1, t));
285
285
  return _Vec.Add(A, _Vec.Mul(ab, t));
286
286
  }
287
- static DistanceToLineSegment(A, B, P, clamp3 = true) {
288
- return _Vec.Dist(P, _Vec.NearestPointOnLineSegment(A, B, P, clamp3));
287
+ static DistanceToLineSegment(A, B, P, clamp4 = true) {
288
+ return _Vec.Dist(P, _Vec.NearestPointOnLineSegment(A, B, P, clamp4));
289
289
  }
290
290
  /** The point closest to `P` on the infinite line through `A` in direction `u`. */
291
291
  static NearestPointOnLineThroughPoint(A, u, P) {
@@ -14458,19 +14458,24 @@ function DefaultCanvas() {
14458
14458
  function DefaultBackground() {
14459
14459
  return /* @__PURE__ */ jsx("div", { className: "mocanvas-background", style: { position: "absolute", inset: 0, background: "var(--mocanvas-canvas, transparent)" } });
14460
14460
  }
14461
+ function clamp3(v, min, max) {
14462
+ return Math.max(min, Math.min(max, v));
14463
+ }
14464
+ var GRID_SOLID_PX = 12;
14465
+ var GRID_GONE_PX = 6;
14466
+ var GRID_DOT_RATIO = 16;
14467
+ var GRID_DOT_MIN = 0.75;
14468
+ var GRID_DOT_MAX = 5;
14461
14469
  function DefaultGrid({ x, y, z, size }) {
14462
14470
  const id = useSharedSafeId("grid");
14463
- const step = size * z;
14464
- const fineOpacity = Math.min(1, Math.max(0, (step - 4) / 12));
14465
- const FINE = 0.7;
14466
- const MAJOR = 0.9;
14471
+ const cell = size * z;
14472
+ const opacity = clamp3((cell - GRID_GONE_PX) / (GRID_SOLID_PX - GRID_GONE_PX), 0, 1);
14473
+ if (opacity <= 0) return null;
14474
+ const r = clamp3(cell / GRID_DOT_RATIO, GRID_DOT_MIN, GRID_DOT_MAX);
14475
+ const half = cell / 2;
14467
14476
  return /* @__PURE__ */ jsxs("svg", { className: "mocanvas-grid", style: { position: "absolute", inset: 0, width: "100%", height: "100%", pointerEvents: "none" }, "aria-hidden": "true", children: [
14468
- /* @__PURE__ */ jsxs("defs", { children: [
14469
- /* @__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 * FINE }) }),
14470
- /* @__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: MAJOR }) })
14471
- ] }),
14472
- /* @__PURE__ */ jsx("rect", { width: "100%", height: "100%", fill: `url(#${id})` }),
14473
- /* @__PURE__ */ jsx("rect", { width: "100%", height: "100%", fill: `url(#${id}_major)` })
14477
+ /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsx("pattern", { id, width: cell, height: cell, patternUnits: "userSpaceOnUse", patternTransform: `translate(${x * z - half} ${y * z - half})`, children: /* @__PURE__ */ jsx("circle", { cx: half, cy: half, r, fill: "var(--mocanvas-grid, currentColor)" }) }) }),
14478
+ /* @__PURE__ */ jsx("rect", { width: "100%", height: "100%", fill: `url(#${id})`, opacity })
14474
14479
  ] });
14475
14480
  }
14476
14481
  function DefaultShapeErrorFallback({ error }) {