@griddle/vue 0.1.0 → 0.1.1

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.
@@ -1 +1 @@
1
- {"version":3,"file":"GriddleGrid.vue.d.ts","sourceRoot":"","sources":["../src/GriddleGrid.vue"],"names":[],"mappings":"AAwuBA,OAAO,KAAK,EAAE,WAAW,EAAU,IAAI,EAAE,MAAM,eAAe,CAAC;AAc/D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAElD,KAAK,WAAW,GAAG;IACjB,GAAG,EAAE,UAAU,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,4DAA4D;IAC5D,SAAS,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CACzB,CAAC;AAowBF,QAAA,IAAI,QAAQ;;;CAAW,EAAE,QAAQ;;;CAAY,CAAE;AAC/C,KAAK,WAAW,GAAG,EAAE,GACnB;IAAE,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,QAAQ,KAAK,GAAG,CAAA;CAAE,GAC1C;IAAE,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,QAAQ,KAAK,GAAG,CAAA;CAAE,CAAC;AA8C7C,QAAA,MAAM,eAAe;;;;;;;;aAhzBY,MAAM;aAAO,MAAM;WAAK,MAAM;WAAK,MAAM;;;;;;;;;;aAAzC,MAAM;aAAO,MAAM;WAAK,MAAM;WAAK,MAAM;;kFAuzBxE,CAAC;wBACkB,eAAe,CAAC,OAAO,eAAe,EAAE,WAAW,CAAC;AAAzE,wBAA0E;AAQ1E,KAAK,eAAe,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG;IAChC,QAAO;QACN,MAAM,EAAE,CAAC,CAAC;KAEV,CAAA;CACD,CAAC"}
1
+ {"version":3,"file":"GriddleGrid.vue.d.ts","sourceRoot":"","sources":["../src/GriddleGrid.vue"],"names":[],"mappings":"AAivBA,OAAO,KAAK,EAAE,WAAW,EAAU,IAAI,EAAE,MAAM,eAAe,CAAC;AAc/D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAElD,KAAK,WAAW,GAAG;IACjB,GAAG,EAAE,UAAU,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,4DAA4D;IAC5D,SAAS,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CACzB,CAAC;AA6wBF,QAAA,IAAI,QAAQ;;;CAAW,EAAE,QAAQ;;;CAAY,CAAE;AAC/C,KAAK,WAAW,GAAG,EAAE,GACnB;IAAE,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,QAAQ,KAAK,GAAG,CAAA;CAAE,GAC1C;IAAE,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,QAAQ,KAAK,GAAG,CAAA;CAAE,CAAC;AA8C7C,QAAA,MAAM,eAAe;;;;;;;;aAzzBY,MAAM;aAAO,MAAM;WAAK,MAAM;WAAK,MAAM;;;;;;;;;;aAAzC,MAAM;aAAO,MAAM;WAAK,MAAM;WAAK,MAAM;;kFAg0BxE,CAAC;wBACkB,eAAe,CAAC,OAAO,eAAe,EAAE,WAAW,CAAC;AAAzE,wBAA0E;AAQ1E,KAAK,eAAe,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG;IAChC,QAAO;QACN,MAAM,EAAE,CAAC,CAAC;KAEV,CAAA;CACD,CAAC"}
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
- import { defineComponent as De, ref as k, computed as w, watch as He, onMounted as Te, onBeforeUnmount as Me, nextTick as Le, openBlock as P, createElementBlock as H, normalizeStyle as $, normalizeClass as be, createElementVNode as Ge, createCommentVNode as oe, Fragment as we, renderList as Ce, renderSlot as ze, createBlock as Ne, withCtx as Ae, normalizeProps as Fe, guardReactiveProps as Oe, toDisplayString as _e, shallowRef as Xe } from "vue";
1
+ import { defineComponent as Te, ref as k, computed as w, watch as He, onMounted as De, onBeforeUnmount as Me, nextTick as Le, openBlock as P, createElementBlock as H, normalizeStyle as $, normalizeClass as be, createElementVNode as Ge, createCommentVNode as oe, Fragment as we, renderList as Ce, renderSlot as ze, createBlock as Ne, withCtx as Ae, normalizeProps as Fe, guardReactiveProps as Oe, toDisplayString as _e, shallowRef as Xe } from "vue";
2
2
  import { resolveLoop as Be, loopPeriod as Ke, PanController as Ue, loopInstances as Ve, DragController as $e, visibleRange as qe, visibleTiles as Je, gridContentSize as je, GroupDragController as Qe, computeTileLayout as We, resolveStickyStacking as Ze, isOutOfFlow as et, pixelsToPin as tt, Grid as nt } from "@griddle/core";
3
- const ot = ["data-griddle-tile", "data-griddle-instance", "data-griddle-ghost", "aria-hidden", "onPointerdown"], it = ["data-griddle-handle", "onPointerdown"], at = ["data-griddle-tile"], Ye = "a, button, input, textarea, select, [contenteditable]", lt = 4, rt = /* @__PURE__ */ De({
3
+ const ot = ["data-griddle-tile", "data-griddle-instance", "data-griddle-ghost", "aria-hidden", "onPointerdown"], it = ["data-griddle-handle", "onPointerdown"], at = ["data-griddle-tile"], Ye = "a, button, input, textarea, select, [contenteditable]", lt = 4, rt = /* @__PURE__ */ Te({
4
4
  __name: "LoopGrid",
5
5
  props: {
6
6
  api: {},
@@ -55,7 +55,7 @@ const ot = ["data-griddle-tile", "data-griddle-instance", "data-griddle-ghost",
55
55
  function re(t) {
56
56
  R && (R = !1, t.preventDefault(), t.stopPropagation());
57
57
  }
58
- const Y = k(/* @__PURE__ */ new Set()), D = w(() => s.selection ?? Y.value);
58
+ const Y = k(/* @__PURE__ */ new Set()), T = w(() => s.selection ?? Y.value);
59
59
  function S(t) {
60
60
  s.selection || (Y.value = t), f("selectionChange", t);
61
61
  }
@@ -65,21 +65,21 @@ const ot = ["data-griddle-tile", "data-griddle-instance", "data-griddle-ghost",
65
65
  function Z() {
66
66
  s.api.tiles.value = s.api.grid.tiles, s.api.version.value++;
67
67
  }
68
- function T(t) {
68
+ function D(t) {
69
69
  return t.kx === 0 && t.ky === 0;
70
70
  }
71
71
  function ee(t) {
72
- return h.value && !T(t);
72
+ return h.value && !D(t);
73
73
  }
74
74
  function xe(t, e) {
75
- if (!h.value || !T(e)) return;
75
+ if (!h.value || !D(e)) return;
76
76
  const o = e.tile;
77
77
  if (o.draggable === !1 || t.target.dataset.griddleHandle) return;
78
78
  const a = v.value.dragIgnoreFrom ?? Ye;
79
79
  if (!(a && t.target.closest(a))) {
80
80
  if (t.metaKey || t.ctrlKey) {
81
81
  t.preventDefault();
82
- const r = new Set(D.value);
82
+ const r = new Set(T.value);
83
83
  r.has(o.id) ? r.delete(o.id) : r.add(o.id), S(r), t.stopPropagation();
84
84
  return;
85
85
  }
@@ -173,7 +173,7 @@ const ot = ["data-griddle-tile", "data-griddle-instance", "data-griddle-ghost",
173
173
  function me(t) {
174
174
  t.key === "Escape" && h.value && S(/* @__PURE__ */ new Set());
175
175
  }
176
- Te(() => {
176
+ De(() => {
177
177
  const t = K.value;
178
178
  if (t) {
179
179
  t.addEventListener("wheel", j, { passive: !1 });
@@ -243,7 +243,7 @@ const ot = ["data-griddle-tile", "data-griddle-instance", "data-griddle-ghost",
243
243
  const e = _.value, o = (e == null ? void 0 : e.instanceKey) === t.key;
244
244
  let a = t.left, r = t.top, p = t.width, g = t.height;
245
245
  o && e && (a = e.previewCol * x.value + y.value + e.instanceDx, r = e.previewRow * W.value + y.value + e.instanceDy, p = e.previewW * v.value.unitWidth + (e.previewW - 1) * m.value, g = e.previewH * v.value.unitHeight + (e.previewH - 1) * m.value);
246
- const M = ee(t), E = h.value && T(t) && D.value.has(t.tile.id);
246
+ const M = ee(t), E = h.value && D(t) && T.value.has(t.tile.id);
247
247
  return {
248
248
  position: "absolute",
249
249
  left: a + "px",
@@ -251,7 +251,7 @@ const ot = ["data-griddle-tile", "data-griddle-instance", "data-griddle-ghost",
251
251
  width: p + "px",
252
252
  height: g + "px",
253
253
  boxSizing: "border-box",
254
- cursor: h.value && T(t) ? "grab" : void 0,
254
+ cursor: h.value && D(t) ? "grab" : void 0,
255
255
  userSelect: "none",
256
256
  // Ghosts are display-only: pointer-transparent (so the gesture falls
257
257
  // through to drag-pan) and dimmed to mark the editable copy.
@@ -350,10 +350,10 @@ const ot = ["data-griddle-tile", "data-griddle-instance", "data-griddle-ghost",
350
350
  "data-griddle-tile": o.tile.id,
351
351
  "data-griddle-instance": o.key,
352
352
  "data-griddle-ghost": ee(o) ? "" : void 0,
353
- "aria-hidden": T(o) ? void 0 : !0,
353
+ "aria-hidden": D(o) ? void 0 : !0,
354
354
  class: be(["griddle-tile", {
355
355
  "griddle-resizing": ((a = _.value) == null ? void 0 : a.instanceKey) === o.key,
356
- "griddle-selected": h.value && T(o) && D.value.has(o.tile.id)
356
+ "griddle-selected": h.value && D(o) && T.value.has(o.tile.id)
357
357
  }]),
358
358
  style: $(Re(o)),
359
359
  ref_for: !0,
@@ -362,9 +362,9 @@ const ot = ["data-griddle-tile", "data-griddle-instance", "data-griddle-ghost",
362
362
  }, [
363
363
  ze(t.$slots, "tile", {
364
364
  tile: o.tile,
365
- selected: h.value && T(o) && D.value.has(o.tile.id)
365
+ selected: h.value && D(o) && T.value.has(o.tile.id)
366
366
  }),
367
- h.value && T(o) && o.tile.resizable !== !1 ? (P(!0), H(we, { key: 0 }, Ce(l(o.tile), (r) => (P(), H("div", {
367
+ h.value && D(o) && o.tile.resizable !== !1 ? (P(!0), H(we, { key: 0 }, Ce(l(o.tile), (r) => (P(), H("div", {
368
368
  key: r,
369
369
  "data-griddle-handle": r,
370
370
  style: $(c(r)),
@@ -381,13 +381,13 @@ const ot = ["data-griddle-tile", "data-griddle-instance", "data-griddle-ghost",
381
381
  }, [
382
382
  ze(t.$slots, "tile", {
383
383
  tile: J.value,
384
- selected: D.value.has(J.value.id)
384
+ selected: T.value.has(J.value.id)
385
385
  })
386
386
  ], 12, at)) : oe("", !0)
387
387
  ], 4)
388
388
  ], 38));
389
389
  }
390
- }), st = ["data-griddle-tile", "onPointerdown"], dt = ["data-griddle-handle", "onPointerdown"], ut = "a, button, input, textarea, select, [contenteditable]", pt = /* @__PURE__ */ De({
390
+ }), st = ["data-griddle-tile", "onPointerdown"], dt = ["data-griddle-handle", "onPointerdown"], ut = "a, button, input, textarea, select, [contenteditable]", pt = /* @__PURE__ */ Te({
391
391
  __name: "GriddleGrid",
392
392
  props: {
393
393
  api: {},
@@ -401,12 +401,14 @@ const ot = ["data-griddle-tile", "data-griddle-instance", "data-griddle-ghost",
401
401
  const s = B, f = z, K = w(() => {
402
402
  var n;
403
403
  return ((n = s.api.config.value.loop) == null ? void 0 : n.enabled) === !0;
404
- }), N = k(null), v = k({ scrollX: 0, scrollY: 0, width: 1e3, height: 800 }), u = w(() => s.api.config.value), h = w(() => u.value.gap ?? 0), m = w(() => h.value / 2), y = w(() => u.value.unitWidth + h.value), x = w(() => u.value.unitHeight + h.value), W = w(() => qe(u.value, v.value, 4)), ue = w(() => Je(s.api.tiles.value, W.value)), F = w(() => je(u.value, s.api.tiles.value)), O = w(() => ({
405
- position: "relative",
406
- overflow: "auto",
407
- height: s.height ?? "100%",
408
- touchAction: "none"
409
- })), U = w(() => {
404
+ }), N = k(null), v = k({ scrollX: 0, scrollY: 0, width: 1e3, height: 800 }), u = w(() => s.api.config.value), h = w(() => u.value.gap ?? 0), m = w(() => h.value / 2), y = w(() => u.value.unitWidth + h.value), x = w(() => u.value.unitHeight + h.value), W = w(() => qe(u.value, v.value, 4)), ue = w(() => Je(s.api.tiles.value, W.value)), F = w(() => je(u.value, s.api.tiles.value)), O = w(() => {
405
+ const n = u.value.scroll !== "none", i = {
406
+ position: "relative",
407
+ overflow: n ? "auto" : "visible",
408
+ height: n ? s.height ?? "100%" : s.height ?? "auto"
409
+ };
410
+ return n && (i.touchAction = "none"), i;
411
+ }), U = w(() => {
410
412
  const i = s.showGrid !== !1 ? {
411
413
  backgroundImage: "linear-gradient(to right, rgba(0,0,0,0.08) 1px, transparent 1px), linear-gradient(to bottom, rgba(0,0,0,0.08) 1px, transparent 1px)",
412
414
  backgroundSize: `${y.value}px ${x.value}px`
@@ -430,7 +432,7 @@ const ot = ["data-griddle-tile", "data-griddle-instance", "data-griddle-ghost",
430
432
  }
431
433
  const ae = new $e(s.api.grid), C = new Qe(s.api.grid), R = k(null);
432
434
  let le = 0, re = 0;
433
- const Y = k(null), D = k(null), S = k(null), G = k(null);
435
+ const Y = k(null), T = k(null), S = k(null), G = k(null);
434
436
  function I(n, i) {
435
437
  if (i.draggable === !1 || n.target.dataset.griddleHandle) return;
436
438
  const l = u.value.dragIgnoreFrom ?? ut;
@@ -446,7 +448,7 @@ const ot = ["data-griddle-tile", "data-griddle-instance", "data-griddle-ghost",
446
448
  viewportWidth: v.value.width,
447
449
  viewportHeight: v.value.height
448
450
  }), o = i.position === "fixed" ? { x: e.left - v.value.scrollX, y: e.top - v.value.scrollY } : { x: e.left, y: e.top };
449
- D.value = {
451
+ T.value = {
450
452
  tileId: i.id,
451
453
  startPinPx: o,
452
454
  startPointerX: n.clientX,
@@ -486,7 +488,8 @@ const ot = ["data-griddle-tile", "data-griddle-instance", "data-griddle-ghost",
486
488
  }, f("dragStart", i.id), n.stopPropagation());
487
489
  }
488
490
  function he(n) {
489
- if (n.target.closest("[data-griddle-tile]")) return;
491
+ var o;
492
+ if (n.target.closest("[data-griddle-tile]") || ((o = u.value.interactive) == null ? void 0 : o.drawToCreate) === !1) return;
490
493
  Q(/* @__PURE__ */ new Set());
491
494
  const i = N.value;
492
495
  if (!i) return;
@@ -519,7 +522,7 @@ const ot = ["data-griddle-tile", "data-griddle-instance", "data-griddle-ghost",
519
522
  }
520
523
  return;
521
524
  }
522
- const i = D.value, l = Y.value, c = R.value, d = S.value;
525
+ const i = T.value, l = Y.value, c = R.value, d = S.value;
523
526
  if (i) {
524
527
  const o = n.clientX - i.startPointerX, a = n.clientY - i.startPointerY, r = { x: i.startPinPx.x + o, y: i.startPinPx.y + a }, p = tt(r, u.value);
525
528
  s.api.grid.setTilePinned(i.tileId, p);
@@ -556,15 +559,15 @@ const ot = ["data-griddle-tile", "data-griddle-instance", "data-griddle-ghost",
556
559
  function Z() {
557
560
  s.api.tiles.value = s.api.grid.tiles, s.api.version.value++;
558
561
  }
559
- function T() {
562
+ function D() {
560
563
  if (G.value) {
561
564
  const i = G.value, l = Math.min(i.anchorCol, i.currentCol), c = Math.min(i.anchorRow, i.currentRow), d = Math.max(1, Math.abs(i.currentCol - i.anchorCol) + 1), t = Math.max(1, Math.abs(i.currentRow - i.anchorRow) + 1);
562
565
  G.value = null, f("drawCreate", { col: l, row: c, w: d, h: t });
563
566
  return;
564
567
  }
565
- if (D.value) {
566
- const i = D.value.tileId;
567
- D.value = null, f("dragEnd", i, !0);
568
+ if (T.value) {
569
+ const i = T.value.tileId;
570
+ T.value = null, f("dragEnd", i, !0);
568
571
  }
569
572
  if (Y.value) {
570
573
  const i = Y.value.tileIds, { committed: l } = C.end();
@@ -596,13 +599,13 @@ const ot = ["data-griddle-tile", "data-griddle-instance", "data-griddle-ghost",
596
599
  n.key === "Escape" && Q(/* @__PURE__ */ new Set());
597
600
  }
598
601
  let te = null;
599
- Te(() => {
602
+ De(() => {
600
603
  ee();
601
604
  const n = N.value;
602
- n && (n.addEventListener("scroll", ee, { passive: !0 }), te = new ResizeObserver(ee), te.observe(n)), window.addEventListener("pointermove", _), window.addEventListener("pointerup", T), window.addEventListener("pointercancel", T), window.addEventListener("keydown", xe);
605
+ n && (n.addEventListener("scroll", ee, { passive: !0 }), te = new ResizeObserver(ee), te.observe(n)), window.addEventListener("pointermove", _), window.addEventListener("pointerup", D), window.addEventListener("pointercancel", D), window.addEventListener("keydown", xe);
603
606
  }), Me(() => {
604
607
  const n = N.value;
605
- n && n.removeEventListener("scroll", ee), te == null || te.disconnect(), window.removeEventListener("pointermove", _), window.removeEventListener("pointerup", T), window.removeEventListener("pointercancel", T), window.removeEventListener("keydown", xe);
608
+ n && n.removeEventListener("scroll", ee), te == null || te.disconnect(), window.removeEventListener("pointermove", _), window.removeEventListener("pointerup", D), window.removeEventListener("pointercancel", D), window.removeEventListener("keydown", xe);
606
609
  });
607
610
  const se = /* @__PURE__ */ new Map(), V = /* @__PURE__ */ new Map();
608
611
  function me(n, i) {
@@ -680,7 +683,7 @@ const ot = ["data-griddle-tile", "data-griddle-instance", "data-griddle-ghost",
680
683
  });
681
684
  function de(n) {
682
685
  var a, r, p;
683
- const i = ((a = R.value) == null ? void 0 : a.tileId) === n.id, l = j.value.has(n.id) && Y.value !== null, c = ((r = D.value) == null ? void 0 : r.tileId) === n.id, d = ((p = S.value) == null ? void 0 : p.tileId) === n.id, t = L.value.has(n.id), e = ce.value.get(n.id) ?? {
686
+ const i = ((a = R.value) == null ? void 0 : a.tileId) === n.id, l = j.value.has(n.id) && Y.value !== null, c = ((r = T.value) == null ? void 0 : r.tileId) === n.id, d = ((p = S.value) == null ? void 0 : p.tileId) === n.id, t = L.value.has(n.id), e = ce.value.get(n.id) ?? {
684
687
  left: 0,
685
688
  top: 0,
686
689
  width: 0,
@@ -821,7 +824,7 @@ const ot = ["data-griddle-tile", "data-griddle-instance", "data-griddle-ghost",
821
824
  key: l.id,
822
825
  "data-griddle-tile": l.id,
823
826
  class: be(["griddle-tile", {
824
- "griddle-dragging": ((c = R.value) == null ? void 0 : c.tileId) === l.id || ((d = D.value) == null ? void 0 : d.tileId) === l.id || Y.value !== null && j.value.has(l.id),
827
+ "griddle-dragging": ((c = R.value) == null ? void 0 : c.tileId) === l.id || ((d = T.value) == null ? void 0 : d.tileId) === l.id || Y.value !== null && j.value.has(l.id),
825
828
  "griddle-resizing": ((t = S.value) == null ? void 0 : t.tileId) === l.id,
826
829
  "griddle-selected": L.value.has(l.id)
827
830
  }]),
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/LoopGrid.vue","../src/GriddleGrid.vue","../src/useGriddle.ts"],"sourcesContent":["<template>\n <div\n ref=\"viewportEl\"\n :class=\"className\"\n :style=\"viewportStyle\"\n @pointerdown=\"onContainerPointerDown\"\n @click.capture=\"onClickCapture\"\n >\n <div ref=\"planeEl\" :style=\"planeStyle\">\n <div\n v-if=\"indicatorRect\"\n class=\"griddle-drop-indicator\"\n :style=\"{\n position: 'absolute',\n left: indicatorRect.left + 'px',\n top: indicatorRect.top + 'px',\n width: indicatorRect.width + 'px',\n height: indicatorRect.height + 'px',\n boxSizing: 'border-box',\n border: '2px dashed rgba(59, 91, 219, 0.55)',\n background: 'rgba(59, 91, 219, 0.08)',\n borderRadius: (config.tileRadius ?? 4) + 'px',\n pointerEvents: 'none',\n zIndex: 5,\n }\"\n ></div>\n <template v-for=\"inst in instances\" :key=\"inst.key\">\n <div\n v-if=\"!(drag && inst.tile.id === drag.tileId)\"\n :data-griddle-tile=\"inst.tile.id\"\n :data-griddle-instance=\"inst.key\"\n :data-griddle-ghost=\"isGhost(inst) ? '' : undefined\"\n :aria-hidden=\"isBase(inst) ? undefined : true\"\n :class=\"['griddle-tile', {\n 'griddle-resizing': resize?.instanceKey === inst.key,\n 'griddle-selected': editable && isBase(inst) && selection.has(inst.tile.id),\n }]\"\n :style=\"instanceStyle(inst)\"\n :ref=\"(el) => registerNode(inst.key, el as HTMLDivElement | null)\"\n @pointerdown=\"(e) => onTilePointerDown(e, inst)\"\n >\n <slot name=\"tile\" :tile=\"inst.tile\" :selected=\"editable && isBase(inst) && selection.has(inst.tile.id)\" />\n <template v-if=\"editable && isBase(inst) && inst.tile.resizable !== false\">\n <div\n v-for=\"c in tileHandles(inst.tile)\"\n :key=\"c\"\n :data-griddle-handle=\"c\"\n :style=\"handleStyle(c)\"\n @pointerdown=\"(e) => onResizeHandleDown(e, inst, c)\"\n ></div>\n </template>\n </div>\n </template>\n <div\n v-if=\"drag && draggedTile\"\n :data-griddle-tile=\"draggedTile.id\"\n class=\"griddle-tile griddle-dragging\"\n :style=\"dragOverlayStyle\"\n >\n <slot name=\"tile\" :tile=\"draggedTile\" :selected=\"selection.has(draggedTile.id)\" />\n </div>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\n// Loop-mode renderer (\"object looping\") — see @griddle/core loop.ts for the\n// coordinate model. Mirrors the React GriddleLoopGrid: an overflow-hidden\n// viewport, a transform-translated plane driven by an unbounded camera, and\n// NO native scrolling (wheel deltas feed the camera directly).\nimport { computed, onBeforeUnmount, onMounted, ref, watch, nextTick } from 'vue';\nimport type { CameraState, CellPos, Corner, Tile } from '@griddle/core';\nimport {\n DragController,\n PanController,\n loopInstances,\n loopPeriod,\n resolveLoop,\n} from '@griddle/core';\nimport type { LoopTileInstance } from '@griddle/core';\nimport type { GriddleApi } from './useGriddle.js';\n\nconst props = defineProps<{\n api: GriddleApi;\n className?: string;\n height?: number | string;\n showGrid?: boolean;\n selection?: Set<string>;\n}>();\n\nconst emit = defineEmits<{\n (e: 'selectionChange', selection: Set<string>): void;\n (e: 'dragStart', tileId: string): void;\n (e: 'dragEnd', tileId: string, committed: boolean): void;\n (e: 'resizeStart', tileId: string): void;\n (e: 'resizeEnd', tileId: string, committed: boolean): void;\n (e: 'cameraChange', camera: CameraState): void;\n}>();\n\nconst DEFAULT_DRAG_IGNORE = 'a, button, input, textarea, select, [contenteditable]';\nconst PAN_THRESHOLD_PX = 4;\n\nconst viewportEl = ref<HTMLDivElement | null>(null);\nconst planeEl = ref<HTMLDivElement | null>(null);\n\nconst config = computed(() => props.api.config.value);\nconst loop = computed(() => resolveLoop(config.value));\nconst editable = computed(() => loop.value?.interaction === 'edit');\nconst gap = computed(() => config.value.gap ?? 0);\nconst halfGap = computed(() => gap.value / 2);\nconst colSize = computed(() => config.value.unitWidth + gap.value);\nconst rowSize = computed(() => config.value.unitHeight + gap.value);\nconst period = computed(() => loopPeriod(config.value, props.api.tiles.value));\n\n// ---- camera plumbing ------------------------------------------------------\nconst pan = new PanController();\nwatch(loop, (l) => {\n if (l) pan.setPhysics({ friction: l.friction, ease: l.ease, maxVelocity: l.maxVelocity });\n}, { immediate: true });\n\nconst view = ref({ cxCell: 0, cyCell: 0, vw: 1000, vh: 800 });\nlet lastCam: CameraState | null = null;\nlet raf = 0;\nlet resizeObserver: ResizeObserver | null = null;\n\nfunction onWheel(e: WheelEvent) {\n e.preventDefault();\n const k = e.deltaMode === 1 ? 16 : e.deltaMode === 2 ? 100 : 1;\n pan.scrollBy(e.deltaX * k, e.deltaY * k);\n}\n\nfunction frame(now: number) {\n raf = requestAnimationFrame(frame);\n const st = pan.tick(now);\n\n const plane = planeEl.value;\n if (plane) {\n plane.style.transform = `translate3d(${-st.x}px, ${-st.y}px, 0)`;\n }\n const el = viewportEl.value;\n if (el && props.showGrid !== false) {\n el.style.backgroundPosition = `${-st.x % colSize.value}px ${-st.y % rowSize.value}px`;\n }\n\n const cxCell = Math.floor(st.x / colSize.value);\n const cyCell = Math.floor(st.y / rowSize.value);\n const cur = view.value;\n if (cxCell !== cur.cxCell || cyCell !== cur.cyCell) {\n view.value = { ...cur, cxCell, cyCell };\n }\n\n if (\n !lastCam || lastCam.x !== st.x || lastCam.y !== st.y ||\n lastCam.isMoving !== st.isMoving || lastCam.isDragging !== st.isDragging\n ) {\n lastCam = st;\n emit('cameraChange', st);\n }\n}\n\nconst instances = computed(() => {\n void props.api.version.value; // re-run on grid changes\n const bufX = 2 * colSize.value;\n const bufY = 2 * rowSize.value;\n return loopInstances(config.value, props.api.tiles.value, {\n x: view.value.cxCell * colSize.value - bufX,\n y: view.value.cyCell * rowSize.value - bufY,\n width: view.value.vw + colSize.value + 2 * bufX,\n height: view.value.vh + rowSize.value + 2 * bufY,\n });\n});\n\n// ---- pan gesture ----------------------------------------------------------\nlet panGesture: { pointerId: number; startX: number; startY: number; moved: boolean } | null = null;\nlet suppressClick = false;\n\nfunction onContainerPointerDown(e: PointerEvent) {\n const onTile = !!(e.target as HTMLElement).closest('[data-griddle-tile]');\n if (editable.value && !onTile) setSelection(new Set());\n // Tiles that start drags stopPropagation, so reaching here from a tile\n // means it was not draggable — panning is the right fallback.\n if (!loop.value?.dragPan || e.button !== 0) return;\n const ignoreSelector = config.value.dragIgnoreFrom ?? DEFAULT_DRAG_IGNORE;\n if (ignoreSelector && (e.target as HTMLElement).closest(ignoreSelector)) return;\n panGesture = { pointerId: e.pointerId, startX: e.clientX, startY: e.clientY, moved: false };\n}\n\nfunction onClickCapture(e: MouseEvent) {\n if (suppressClick) {\n suppressClick = false;\n e.preventDefault();\n e.stopPropagation();\n }\n}\n\n// ---- selection ('edit' interaction) ---------------------------------------\nconst internalSelection = ref<Set<string>>(new Set());\nconst selection = computed(() => props.selection ?? internalSelection.value);\nfunction setSelection(next: Set<string>) {\n if (!props.selection) internalSelection.value = next;\n emit('selectionChange', next);\n}\n\n// ---- tile drag / resize ('edit' interaction) ------------------------------\nconst dragController = new DragController(props.api.grid);\n\ninterface LoopDragVisual {\n tileId: string;\n instanceLeft: number;\n instanceTop: number;\n pickupCol: number;\n pickupRow: number;\n deltaX: number;\n deltaY: number;\n indicatorCol: number | null;\n indicatorRow: number | null;\n}\nconst drag = ref<LoopDragVisual | null>(null);\nlet dragStartPointerX = 0;\nlet dragStartPointerY = 0;\n\ninterface LoopResizeState {\n tileId: string;\n instanceKey: string;\n instanceDx: number;\n instanceDy: number;\n corner: Corner;\n startPointerX: number;\n startPointerY: number;\n startW: number;\n startH: number;\n startCol: number;\n startRow: number;\n previewW: number;\n previewH: number;\n previewCol: number;\n previewRow: number;\n}\nconst resize = ref<LoopResizeState | null>(null);\n\nfunction syncTiles() {\n props.api.tiles.value = props.api.grid.tiles;\n props.api.version.value++;\n}\n\nfunction isBase(inst: LoopTileInstance): boolean {\n return inst.kx === 0 && inst.ky === 0;\n}\nfunction isGhost(inst: LoopTileInstance): boolean {\n return editable.value && !isBase(inst);\n}\n\nfunction onTilePointerDown(e: PointerEvent, inst: LoopTileInstance) {\n if (!editable.value) return; // pan mode: container pan handler takes it\n if (!isBase(inst)) return; // ghosts are display-only\n const tile = inst.tile;\n if (tile.draggable === false) return;\n if ((e.target as HTMLElement).dataset.griddleHandle) return;\n const ignoreSelector = config.value.dragIgnoreFrom ?? DEFAULT_DRAG_IGNORE;\n if (ignoreSelector && (e.target as HTMLElement).closest(ignoreSelector)) return;\n\n if (e.metaKey || e.ctrlKey) {\n e.preventDefault();\n const next = new Set(selection.value);\n if (next.has(tile.id)) next.delete(tile.id);\n else next.add(tile.id);\n setSelection(next);\n e.stopPropagation();\n return;\n }\n setSelection(new Set([tile.id]));\n\n // No pointer capture: the grabbed instance unmounts (drag renders as an\n // overlay), which would release the capture mid-gesture.\n if (!dragController.start(tile.id)) return;\n dragStartPointerX = e.clientX;\n dragStartPointerY = e.clientY;\n drag.value = {\n tileId: tile.id,\n instanceLeft: inst.left,\n instanceTop: inst.top,\n pickupCol: tile.col,\n pickupRow: tile.row,\n deltaX: 0,\n deltaY: 0,\n indicatorCol: tile.col,\n indicatorRow: tile.row,\n };\n emit('dragStart', tile.id);\n e.stopPropagation();\n}\n\nfunction onResizeHandleDown(e: PointerEvent, inst: LoopTileInstance, c: Corner) {\n if (!editable.value) return;\n const tile = inst.tile;\n if (tile.resizable === false) return;\n (e.currentTarget as HTMLDivElement).setPointerCapture(e.pointerId);\n const baseLeft = tile.col * colSize.value + halfGap.value;\n const baseTop = tile.row * rowSize.value + halfGap.value;\n resize.value = {\n tileId: tile.id,\n instanceKey: inst.key,\n instanceDx: inst.left - baseLeft,\n instanceDy: inst.top - baseTop,\n corner: c,\n startPointerX: e.clientX,\n startPointerY: e.clientY,\n startW: tile.w,\n startH: tile.h,\n startCol: tile.col,\n startRow: tile.row,\n previewW: tile.w,\n previewH: tile.h,\n previewCol: tile.col,\n previewRow: tile.row,\n };\n emit('resizeStart', tile.id);\n e.stopPropagation();\n}\n\nfunction onPointerMove(e: PointerEvent) {\n if (panGesture && e.pointerId === panGesture.pointerId) {\n const now = performance.now();\n if (!panGesture.moved) {\n const dist = Math.hypot(e.clientX - panGesture.startX, e.clientY - panGesture.startY);\n if (dist >= PAN_THRESHOLD_PX) {\n panGesture.moved = true;\n pan.dragStart(panGesture.startX, panGesture.startY, now);\n pan.dragMove(e.clientX, e.clientY, now);\n }\n } else {\n pan.dragMove(e.clientX, e.clientY, now);\n }\n return;\n }\n\n const d = drag.value;\n if (d) {\n // Ghost edit: plain grid semantics in the base copy — no wrapping.\n const dx = e.clientX - dragStartPointerX;\n const dy = e.clientY - dragStartPointerY;\n const candidate: CellPos = {\n col: d.pickupCol + Math.round(dx / colSize.value),\n row: d.pickupRow + Math.round(dy / rowSize.value),\n };\n const result = dragController.update(candidate);\n drag.value = {\n ...d,\n deltaX: dx,\n deltaY: dy,\n indicatorCol: result.indicatorCell ? result.indicatorCell.col : null,\n indicatorRow: result.indicatorCell ? result.indicatorCell.row : null,\n };\n if (result.changed) syncTiles();\n }\n\n const r = resize.value;\n if (r) {\n const dx = e.clientX - r.startPointerX;\n const dy = e.clientY - r.startPointerY;\n let dw = 0, dh = 0, dcol = 0, drow = 0;\n const stepsX = Math.round(dx / colSize.value);\n const stepsY = Math.round(dy / rowSize.value);\n if (r.corner === 'se' || r.corner === 'ne') dw = stepsX;\n if (r.corner === 'se' || r.corner === 'sw') dh = stepsY;\n if (r.corner === 'sw' || r.corner === 'nw') { dw = -stepsX; dcol = stepsX; }\n if (r.corner === 'ne' || r.corner === 'nw') { dh = -stepsY; drow = stepsY; }\n const tile = props.api.grid.getTile(r.tileId);\n const minW = tile?.minW ?? 1;\n const minH = tile?.minH ?? 1;\n const maxW = Math.min(tile?.maxW ?? Infinity, config.value.cols);\n const maxH = Math.min(tile?.maxH ?? Infinity, config.value.rows);\n const nW = Math.min(maxW, Math.max(minW, r.startW + dw));\n const nH = Math.min(maxH, Math.max(minH, r.startH + dh));\n const nC = r.startCol + dcol;\n const nR = r.startRow + drow;\n if (nW !== r.previewW || nH !== r.previewH || nC !== r.previewCol || nR !== r.previewRow) {\n resize.value = { ...r, previewW: nW, previewH: nH, previewCol: nC, previewRow: nR };\n }\n }\n}\n\nfunction onPointerUp(e: PointerEvent) {\n if (panGesture && e.pointerId === panGesture.pointerId) {\n if (panGesture.moved) {\n pan.dragEnd(performance.now());\n suppressClick = true;\n }\n panGesture = null;\n return;\n }\n\n if (drag.value) {\n const tileId = drag.value.tileId;\n const { committed } = dragController.end();\n drag.value = null;\n syncTiles();\n emit('dragEnd', tileId, committed);\n }\n const r = resize.value;\n if (r) {\n const t = props.api.grid.getTile(r.tileId);\n let committed = false;\n if (t) {\n const target = { col: r.previewCol, row: r.previewRow };\n if (target.col !== t.col || target.row !== t.row) {\n props.api.moveTile(r.tileId, target);\n }\n if (r.previewW !== t.w || r.previewH !== t.h) {\n committed = props.api.resizeTile(r.tileId, { w: r.previewW, h: r.previewH });\n } else {\n committed = r.previewCol !== r.startCol || r.previewRow !== r.startRow\n || r.previewW !== r.startW || r.previewH !== r.startH;\n }\n }\n resize.value = null;\n emit('resizeEnd', r.tileId, committed);\n }\n}\n\nfunction onKeyDown(e: KeyboardEvent) {\n if (e.key === 'Escape' && editable.value) setSelection(new Set());\n}\n\nonMounted(() => {\n const el = viewportEl.value;\n if (el) {\n el.addEventListener('wheel', onWheel, { passive: false });\n const measure = () => {\n const cur = view.value;\n if (el.clientWidth !== cur.vw || el.clientHeight !== cur.vh) {\n view.value = { ...cur, vw: el.clientWidth, vh: el.clientHeight };\n }\n };\n measure();\n resizeObserver = new ResizeObserver(measure);\n resizeObserver.observe(el);\n }\n raf = requestAnimationFrame(frame);\n window.addEventListener('pointermove', onPointerMove);\n window.addEventListener('pointerup', onPointerUp);\n window.addEventListener('pointercancel', onPointerUp);\n window.addEventListener('keydown', onKeyDown);\n});\nonBeforeUnmount(() => {\n cancelAnimationFrame(raf);\n viewportEl.value?.removeEventListener('wheel', onWheel);\n resizeObserver?.disconnect();\n window.removeEventListener('pointermove', onPointerMove);\n window.removeEventListener('pointerup', onPointerUp);\n window.removeEventListener('pointercancel', onPointerUp);\n window.removeEventListener('keydown', onKeyDown);\n});\n\n// ---- FLIP for edit-mode repacks (keyed by world key) ----------------------\nconst tileNodes = new Map<string, HTMLDivElement>();\nconst prevRects = new Map<string, { x: number; y: number }>();\nfunction registerNode(key: string, el: HTMLDivElement | null) {\n if (el) tileNodes.set(key, el);\n else tileNodes.delete(key);\n}\n\nwatch(() => props.api.version.value, async () => {\n await nextTick();\n const draggerId = drag.value?.tileId ?? null;\n const seen = new Set<string>();\n for (const inst of instances.value) {\n const key = inst.key;\n seen.add(key);\n const x = inst.left;\n const y = inst.top;\n if (editable.value && inst.tile.id !== draggerId) {\n const p = prevRects.get(key);\n const node = tileNodes.get(key);\n if (p && node) {\n const dx = p.x - x;\n const dy = p.y - y;\n if (\n (dx !== 0 || dy !== 0) &&\n Math.abs(dx) < period.value.width / 2 &&\n Math.abs(dy) < period.value.height / 2\n ) {\n node.style.transition = 'none';\n node.style.transform = `translate(${dx}px, ${dy}px)`;\n requestAnimationFrame(() => {\n node.style.transition = 'transform 220ms cubic-bezier(.2,.7,.2,1)';\n node.style.transform = 'translate(0,0)';\n });\n }\n }\n }\n prevRects.set(key, { x, y });\n }\n for (const key of prevRects.keys()) {\n if (!seen.has(key)) prevRects.delete(key);\n }\n});\n\n// ---- styles ----------------------------------------------------------------\nconst viewportStyle = computed(() => {\n const showGrid = props.showGrid !== false;\n const bg = showGrid\n ? {\n backgroundImage: `linear-gradient(to right, rgba(0,0,0,0.08) 1px, transparent 1px), linear-gradient(to bottom, rgba(0,0,0,0.08) 1px, transparent 1px)`,\n backgroundSize: `${colSize.value}px ${rowSize.value}px`,\n backgroundPosition: '0 0',\n }\n : {};\n return {\n position: 'relative' as const,\n overflow: 'hidden' as const,\n height: typeof props.height === 'number' ? props.height + 'px' : (props.height ?? '100%'),\n touchAction: 'none' as const,\n userSelect: 'none' as const,\n cursor: !editable.value && loop.value?.dragPan ? 'grab' : undefined,\n ['--griddle-tile-radius' as string]: (config.value.tileRadius ?? 4) + 'px',\n ...bg,\n };\n});\n\nconst planeStyle = computed(() => ({\n position: 'absolute' as const,\n top: '0',\n left: '0',\n width: '0',\n height: '0',\n willChange: 'transform',\n}));\n\nfunction instanceStyle(inst: LoopTileInstance) {\n const r = resize.value;\n const isResizingInst = r?.instanceKey === inst.key;\n let left = inst.left;\n let top = inst.top;\n let width = inst.width;\n let heightPx = inst.height;\n if (isResizingInst && r) {\n left = r.previewCol * colSize.value + halfGap.value + r.instanceDx;\n top = r.previewRow * rowSize.value + halfGap.value + r.instanceDy;\n width = r.previewW * config.value.unitWidth + (r.previewW - 1) * gap.value;\n heightPx = r.previewH * config.value.unitHeight + (r.previewH - 1) * gap.value;\n }\n const ghost = isGhost(inst);\n const isSelected = editable.value && isBase(inst) && selection.value.has(inst.tile.id);\n return {\n position: 'absolute' as const,\n left: left + 'px',\n top: top + 'px',\n width: width + 'px',\n height: heightPx + 'px',\n boxSizing: 'border-box' as const,\n cursor: editable.value && isBase(inst) ? 'grab' : undefined,\n userSelect: 'none' as const,\n // Ghosts are display-only: pointer-transparent (so the gesture falls\n // through to drag-pan) and dimmed to mark the editable copy.\n pointerEvents: ghost ? ('none' as const) : undefined,\n zIndex: isResizingInst ? 10 : 1,\n opacity: isResizingInst ? 0.85 : ghost ? 0.55 : 1,\n boxShadow: isSelected\n ? '0 0 0 3px rgba(59, 91, 219, 0.85), inset 0 0 0 1px rgba(59, 91, 219, 0.3)'\n : '',\n borderRadius: (config.value.tileRadius ?? 4) + 'px',\n };\n}\n\nconst draggedTile = computed<Tile | null>(() =>\n drag.value ? props.api.grid.getTile(drag.value.tileId) ?? null : null,\n);\n\nconst dragOverlayStyle = computed(() => {\n const d = drag.value;\n const t = draggedTile.value;\n if (!d || !t) return {};\n return {\n position: 'absolute' as const,\n left: d.instanceLeft + 'px',\n top: d.instanceTop + 'px',\n width: t.w * config.value.unitWidth + (t.w - 1) * gap.value + 'px',\n height: t.h * config.value.unitHeight + (t.h - 1) * gap.value + 'px',\n boxSizing: 'border-box' as const,\n cursor: 'grabbing',\n userSelect: 'none' as const,\n zIndex: 20,\n opacity: 0.85,\n transform: `translate(${d.deltaX}px, ${d.deltaY}px)`,\n filter: 'drop-shadow(0 8px 16px rgba(0,0,0,0.18))',\n borderRadius: (config.value.tileRadius ?? 4) + 'px',\n pointerEvents: 'none' as const,\n };\n});\n\n// Drop indicator: rendered in the base copy (ghost edit is plain-grid).\nconst indicatorRect = computed(() => {\n const d = drag.value;\n if (!d || d.indicatorCol === null || d.indicatorRow === null) return null;\n const t = props.api.grid.getTile(d.tileId);\n if (!t) return null;\n return {\n left: d.indicatorCol * colSize.value + halfGap.value,\n top: d.indicatorRow * rowSize.value + halfGap.value,\n width: t.w * config.value.unitWidth + (t.w - 1) * gap.value,\n height: t.h * config.value.unitHeight + (t.h - 1) * gap.value,\n };\n});\n\nfunction tileHandles(tile: Tile): Corner[] {\n return tile.resizeHandles ?? config.value.resizeHandles ?? ['se'];\n}\n\nfunction handleStyle(c: Corner) {\n const size = 12;\n const base = {\n position: 'absolute' as const,\n width: size + 'px',\n height: size + 'px',\n background: 'rgba(60,60,60,0.7)',\n border: '2px solid white',\n borderRadius: '3px',\n cursor: `${c}-resize`,\n touchAction: 'none' as const,\n } as Record<string, unknown>;\n if (c === 'nw') return { ...base, top: -size / 2 + 'px', left: -size / 2 + 'px' };\n if (c === 'ne') return { ...base, top: -size / 2 + 'px', right: -size / 2 + 'px' };\n if (c === 'sw') return { ...base, bottom: -size / 2 + 'px', left: -size / 2 + 'px' };\n return { ...base, bottom: -size / 2 + 'px', right: -size / 2 + 'px' };\n}\n\nconst className = computed(() => props.className ?? '');\n</script>\n","<template>\n <GriddleLoopGrid\n v-if=\"loopOn\"\n :api=\"api\"\n :class-name=\"className\"\n :height=\"height\"\n :show-grid=\"showGrid\"\n :selection=\"props.selection\"\n @selection-change=\"(s) => emit('selectionChange', s)\"\n @drag-start=\"(id) => emit('dragStart', id)\"\n @drag-end=\"(id, c) => emit('dragEnd', id, c)\"\n @resize-start=\"(id) => emit('resizeStart', id)\"\n @resize-end=\"(id, c) => emit('resizeEnd', id, c)\"\n @camera-change=\"(cam) => emit('cameraChange', cam)\"\n >\n <template #tile=\"slotProps\">\n <slot name=\"tile\" v-bind=\"slotProps\" />\n </template>\n </GriddleLoopGrid>\n <div\n v-else\n ref=\"scrollEl\"\n :class=\"className\"\n :style=\"scrollStyle\"\n @pointerdown=\"onBackgroundPointerDown\"\n >\n <div :style=\"contentStyle\">\n <div\n v-if=\"indicatorRect\"\n class=\"griddle-drop-indicator\"\n :style=\"{\n position: 'absolute',\n left: indicatorRect.left + 'px',\n top: indicatorRect.top + 'px',\n width: indicatorRect.width + 'px',\n height: indicatorRect.height + 'px',\n boxSizing: 'border-box',\n border: '2px dashed rgba(59, 91, 219, 0.55)',\n background: 'rgba(59, 91, 219, 0.08)',\n borderRadius: (config.tileRadius ?? 4) + 'px',\n pointerEvents: 'none',\n zIndex: 5,\n }\"\n ></div>\n <div\n v-if=\"drawGhostRect\"\n class=\"griddle-draw-ghost\"\n :style=\"{\n position: 'absolute',\n left: drawGhostRect.left + 'px',\n top: drawGhostRect.top + 'px',\n width: drawGhostRect.width + 'px',\n height: drawGhostRect.height + 'px',\n boxSizing: 'border-box',\n border: '2px dashed rgba(59, 91, 219, 0.55)',\n background: 'rgba(59, 91, 219, 0.08)',\n borderRadius: (config.tileRadius ?? 4) + 'px',\n pointerEvents: 'none',\n zIndex: 5,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n fontSize: '14px',\n fontWeight: '600',\n color: 'rgba(59, 91, 219, 0.8)',\n userSelect: 'none',\n }\"\n >{{ drawGhostRect.label }}</div>\n <div\n v-for=\"tile in rendered\"\n :key=\"tile.id\"\n :data-griddle-tile=\"tile.id\"\n :class=\"['griddle-tile', {\n 'griddle-dragging': drag?.tileId === tile.id || pinDrag?.tileId === tile.id || (groupDrag !== null && groupDragSet.has(tile.id)),\n 'griddle-resizing': resize?.tileId === tile.id,\n 'griddle-selected': selection.has(tile.id),\n }]\"\n :style=\"tileStyle(tile)\"\n @pointerdown=\"(e) => onTilePointerDown(e, tile)\"\n :ref=\"(el) => registerNode(tile.id, el as HTMLDivElement | null)\"\n >\n <slot name=\"tile\" :tile=\"tile\" :selected=\"selection.has(tile.id)\" />\n <template v-if=\"tile.resizable !== false\">\n <div\n v-for=\"c in tileHandles(tile)\"\n :key=\"c\"\n :data-griddle-handle=\"c\"\n :style=\"handleStyle(c)\"\n @pointerdown=\"(e) => onResizeHandleDown(e, tile, c)\"\n ></div>\n </template>\n </div>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, onBeforeUnmount, onMounted, ref, watch, nextTick } from 'vue';\nimport type { CameraState, Corner, Tile } from '@griddle/core';\nimport GriddleLoopGrid from './LoopGrid.vue';\nimport {\n visibleRange,\n visibleTiles,\n gridContentSize,\n DragController,\n GroupDragController,\n computeTileLayout,\n resolveStickyStacking,\n isOutOfFlow,\n pixelsToPin,\n} from '@griddle/core';\nimport type { TileLayout } from '@griddle/core';\nimport type { GriddleApi } from './useGriddle.js';\n\nconst props = defineProps<{\n api: GriddleApi;\n className?: string;\n height?: number | string;\n showGrid?: boolean;\n /** Controlled selection. If omitted, managed internally. */\n selection?: Set<string>;\n}>();\n\nconst emit = defineEmits<{\n (e: 'selectionChange', selection: Set<string>): void;\n (e: 'drawCreate', rect: { col: number; row: number; w: number; h: number }): void;\n (e: 'dragStart', tileId: string): void;\n (e: 'dragEnd', tileId: string, committed: boolean): void;\n (e: 'resizeStart', tileId: string): void;\n (e: 'resizeEnd', tileId: string, committed: boolean): void;\n (e: 'cameraChange', camera: CameraState): void;\n}>();\n\n/** Loop mode delegates rendering to GriddleLoopGrid. */\nconst loopOn = computed(() => props.api.config.value.loop?.enabled === true);\n\nconst scrollEl = ref<HTMLDivElement | null>(null);\nconst viewport = ref({ scrollX: 0, scrollY: 0, width: 1000, height: 800 });\n\nconst config = computed(() => props.api.config.value);\nconst gap = computed(() => config.value.gap ?? 0);\nconst halfGap = computed(() => gap.value / 2);\nconst colSize = computed(() => config.value.unitWidth + gap.value);\nconst rowSize = computed(() => config.value.unitHeight + gap.value);\n\nconst range = computed(() => visibleRange(config.value, viewport.value, 4));\nconst rendered = computed(() => visibleTiles(props.api.tiles.value, range.value));\nconst contentSize = computed(() => gridContentSize(config.value, props.api.tiles.value));\n\nconst scrollStyle = computed(() => ({\n position: 'relative' as const,\n overflow: 'auto' as const,\n height: props.height ?? '100%',\n touchAction: 'none' as const,\n}));\n\nconst contentStyle = computed(() => {\n const showGrid = props.showGrid !== false;\n const bg = showGrid\n ? {\n backgroundImage: `linear-gradient(to right, rgba(0,0,0,0.08) 1px, transparent 1px), linear-gradient(to bottom, rgba(0,0,0,0.08) 1px, transparent 1px)`,\n backgroundSize: `${colSize.value}px ${rowSize.value}px`,\n }\n : {};\n return {\n position: 'relative' as const,\n width: contentSize.value.width || '100%',\n height: contentSize.value.height || '100%',\n minWidth: '100%',\n minHeight: '100%',\n // Expose tile radius as a CSS variable so user tile content can pick it up.\n ['--griddle-tile-radius' as string]: (config.value.tileRadius ?? 4) + 'px',\n ...bg,\n };\n});\n\n// Selection state\nconst internalSelection = ref<Set<string>>(new Set());\nconst selection = computed(() => props.selection ?? internalSelection.value);\nconst groupDragSet = computed(() => new Set(groupDrag.value?.tileIds ?? []));\nfunction setSelection(next: Set<string>) {\n if (!props.selection) internalSelection.value = next;\n emit('selectionChange', next);\n}\n\nconst DEFAULT_DRAG_IGNORE = 'a, button, input, textarea, select, [contenteditable]';\n\nconst dragController = new DragController(props.api.grid);\nconst groupDragController = new GroupDragController(props.api.grid);\n\ninterface DragVisual {\n tileId: string;\n pickupCol: number;\n pickupRow: number;\n deltaX: number;\n deltaY: number;\n indicatorCol: number | null;\n indicatorRow: number | null;\n}\nconst drag = ref<DragVisual | null>(null);\nlet dragStartPointerX = 0;\nlet dragStartPointerY = 0;\n\ninterface GroupDragVisual {\n tileIds: string[];\n deltaX: number;\n deltaY: number;\n committedDcol: number;\n committedDrow: number;\n}\nconst groupDrag = ref<GroupDragVisual | null>(null);\n\ninterface PinDragState {\n tileId: string;\n startPinPx: { x: number; y: number };\n startPointerX: number;\n startPointerY: number;\n}\nconst pinDrag = ref<PinDragState | null>(null);\n\ninterface ResizeState {\n tileId: string;\n corner: Corner;\n startPointerX: number;\n startPointerY: number;\n startW: number;\n startH: number;\n startCol: number;\n startRow: number;\n previewW: number;\n previewH: number;\n previewCol: number;\n previewRow: number;\n}\nconst resize = ref<ResizeState | null>(null);\n\ninterface DrawState {\n anchorCol: number;\n anchorRow: number;\n currentCol: number;\n currentRow: number;\n}\nconst drawState = ref<DrawState | null>(null);\n\nfunction onTilePointerDown(e: PointerEvent, tile: Tile) {\n if (tile.draggable === false) return;\n if ((e.target as HTMLElement).dataset.griddleHandle) return;\n\n const ignoreSelector = config.value.dragIgnoreFrom ?? DEFAULT_DRAG_IGNORE;\n if (ignoreSelector && (e.target as HTMLElement).closest(ignoreSelector)) return;\n\n const metaKey = e.metaKey || e.ctrlKey;\n\n // Out-of-flow tiles get free-pixel drag (no selection).\n if (config.value.enablePositioning && isOutOfFlow(tile)) {\n (e.currentTarget as HTMLDivElement).setPointerCapture(e.pointerId);\n const layout = computeTileLayout({\n tile,\n config: config.value,\n scrollX: viewport.value.scrollX,\n scrollY: viewport.value.scrollY,\n viewportWidth: viewport.value.width,\n viewportHeight: viewport.value.height,\n });\n const startPinPx =\n tile.position === 'fixed'\n ? { x: layout.left - viewport.value.scrollX, y: layout.top - viewport.value.scrollY }\n : { x: layout.left, y: layout.top };\n pinDrag.value = {\n tileId: tile.id,\n startPinPx,\n startPointerX: e.clientX,\n startPointerY: e.clientY,\n };\n emit('dragStart', tile.id);\n e.stopPropagation();\n return;\n }\n\n // Cmd/Ctrl+click toggles selection without starting a drag.\n if (metaKey) {\n e.preventDefault();\n const next = new Set(selection.value);\n if (next.has(tile.id)) {\n next.delete(tile.id);\n } else {\n next.add(tile.id);\n }\n setSelection(next);\n e.stopPropagation();\n return;\n }\n\n const tileIsSelected = selection.value.has(tile.id);\n\n if (!tileIsSelected) {\n setSelection(new Set([tile.id]));\n }\n\n // Capture pointer only when starting a drag.\n (e.currentTarget as HTMLDivElement).setPointerCapture(e.pointerId);\n\n // Group drag if 2+ tiles selected including this one.\n const effectiveSelection = tileIsSelected ? selection.value : new Set([tile.id]);\n if (effectiveSelection.size > 1) {\n const ids = Array.from(effectiveSelection);\n if (!groupDragController.start(ids)) return;\n dragStartPointerX = e.clientX;\n dragStartPointerY = e.clientY;\n groupDrag.value = {\n tileIds: ids,\n deltaX: 0,\n deltaY: 0,\n committedDcol: 0,\n committedDrow: 0,\n };\n emit('dragStart', tile.id);\n e.stopPropagation();\n return;\n }\n\n // Single tile drag.\n if (!dragController.start(tile.id)) return;\n dragStartPointerX = e.clientX;\n dragStartPointerY = e.clientY;\n drag.value = {\n tileId: tile.id,\n pickupCol: tile.col,\n pickupRow: tile.row,\n deltaX: 0,\n deltaY: 0,\n indicatorCol: tile.col,\n indicatorRow: tile.row,\n };\n emit('dragStart', tile.id);\n e.stopPropagation();\n}\n\nfunction onBackgroundPointerDown(e: PointerEvent) {\n if ((e.target as HTMLElement).closest('[data-griddle-tile]')) return;\n setSelection(new Set());\n\n const el = scrollEl.value;\n if (!el) return;\n const rect = el.getBoundingClientRect();\n const x = e.clientX - rect.left + el.scrollLeft;\n const y = e.clientY - rect.top + el.scrollTop;\n const col = Math.floor(x / colSize.value);\n const row = Math.floor(y / rowSize.value);\n drawState.value = { anchorCol: col, anchorRow: row, currentCol: col, currentRow: row };\n (el as HTMLDivElement).setPointerCapture(e.pointerId);\n}\n\nfunction onResizeHandleDown(e: PointerEvent, tile: Tile, c: Corner) {\n if (tile.resizable === false) return;\n (e.currentTarget as HTMLDivElement).setPointerCapture(e.pointerId);\n resize.value = {\n tileId: tile.id,\n corner: c,\n startPointerX: e.clientX,\n startPointerY: e.clientY,\n startW: tile.w,\n startH: tile.h,\n startCol: tile.col,\n startRow: tile.row,\n previewW: tile.w,\n previewH: tile.h,\n previewCol: tile.col,\n previewRow: tile.row,\n };\n emit('resizeStart', tile.id);\n e.stopPropagation();\n}\n\nfunction onPointerMove(e: PointerEvent) {\n if (drawState.value) {\n const el = scrollEl.value;\n if (el) {\n const rect = el.getBoundingClientRect();\n const x = e.clientX - rect.left + el.scrollLeft;\n const y = e.clientY - rect.top + el.scrollTop;\n const col = Math.max(0, Math.floor(x / colSize.value));\n const row = Math.max(0, Math.floor(y / rowSize.value));\n drawState.value = { ...drawState.value, currentCol: col, currentRow: row };\n }\n return;\n }\n const pd = pinDrag.value;\n const gd = groupDrag.value;\n const d = drag.value;\n const r = resize.value;\n if (pd) {\n const dx = e.clientX - pd.startPointerX;\n const dy = e.clientY - pd.startPointerY;\n const newPinPx = { x: pd.startPinPx.x + dx, y: pd.startPinPx.y + dy };\n const newPin = pixelsToPin(newPinPx, config.value);\n props.api.grid.setTilePinned(pd.tileId, newPin);\n }\n if (gd) {\n const dx = e.clientX - dragStartPointerX;\n const dy = e.clientY - dragStartPointerY;\n const dcol = Math.round(dx / colSize.value);\n const drow = Math.round(dy / rowSize.value);\n const result = groupDragController.update({ dcol, drow });\n groupDrag.value = {\n ...gd,\n deltaX: dx,\n deltaY: dy,\n committedDcol: result.indicatorDelta?.dcol ?? gd.committedDcol,\n committedDrow: result.indicatorDelta?.drow ?? gd.committedDrow,\n };\n if (result.changed) syncTiles();\n }\n if (d) {\n const dx = e.clientX - dragStartPointerX;\n const dy = e.clientY - dragStartPointerY;\n const candidateCol = d.pickupCol + Math.round(dx / colSize.value);\n const candidateRow = d.pickupRow + Math.round(dy / rowSize.value);\n const result = dragController.update({ col: candidateCol, row: candidateRow });\n drag.value = {\n ...d,\n deltaX: dx,\n deltaY: dy,\n indicatorCol: result.indicatorCell ? result.indicatorCell.col : null,\n indicatorRow: result.indicatorCell ? result.indicatorCell.row : null,\n };\n // DragController.restoreTiles() doesn't emit change events, so when the\n // candidate cell changes (especially returning to pickup), force-sync the\n // reactive tiles ref so the FLIP animation picks up displaced tile resets.\n if (result.changed) syncTiles();\n }\n if (r) {\n const dx = e.clientX - r.startPointerX;\n const dy = e.clientY - r.startPointerY;\n let dw = 0, dh = 0, dcol = 0, drow = 0;\n const stepsX = Math.round(dx / colSize.value);\n const stepsY = Math.round(dy / rowSize.value);\n if (r.corner === 'se' || r.corner === 'ne') dw = stepsX;\n if (r.corner === 'se' || r.corner === 'sw') dh = stepsY;\n if (r.corner === 'sw' || r.corner === 'nw') { dw = -stepsX; dcol = stepsX; }\n if (r.corner === 'ne' || r.corner === 'nw') { dh = -stepsY; drow = stepsY; }\n const tile = props.api.grid.getTile(r.tileId);\n const minW = tile?.minW ?? 1;\n const minH = tile?.minH ?? 1;\n const maxW = tile?.maxW ?? Infinity;\n const maxH = tile?.maxH ?? Infinity;\n const nW = Math.min(maxW, Math.max(minW, r.startW + dw));\n const nH = Math.min(maxH, Math.max(minH, r.startH + dh));\n const nC = r.startCol + dcol;\n const nR = r.startRow + drow;\n if (nW !== r.previewW || nH !== r.previewH || nC !== r.previewCol || nR !== r.previewRow) {\n resize.value = { ...r, previewW: nW, previewH: nH, previewCol: nC, previewRow: nR };\n }\n }\n}\n\nfunction syncTiles() {\n // DragController/GroupDragController may restore grid snapshots without\n // emitting change events. Force-sync the reactive tiles ref so the UI\n // reflects the grid's true state after a drag ends.\n props.api.tiles.value = props.api.grid.tiles;\n props.api.version.value++;\n}\n\nfunction onPointerUp() {\n if (drawState.value) {\n const ds = drawState.value;\n const col = Math.min(ds.anchorCol, ds.currentCol);\n const row = Math.min(ds.anchorRow, ds.currentRow);\n const w = Math.max(1, Math.abs(ds.currentCol - ds.anchorCol) + 1);\n const h = Math.max(1, Math.abs(ds.currentRow - ds.anchorRow) + 1);\n drawState.value = null;\n emit('drawCreate', { col, row, w, h });\n return;\n }\n if (pinDrag.value) {\n const tileId = pinDrag.value.tileId;\n pinDrag.value = null;\n emit('dragEnd', tileId, true);\n }\n if (groupDrag.value) {\n const tileIds = groupDrag.value.tileIds;\n const { committed } = groupDragController.end();\n groupDrag.value = null;\n syncTiles();\n const firstId = tileIds[0];\n if (firstId !== undefined) emit('dragEnd', firstId, committed);\n }\n if (drag.value) {\n const tileId = drag.value.tileId;\n const { committed } = dragController.end();\n drag.value = null;\n syncTiles();\n emit('dragEnd', tileId, committed);\n }\n const r = resize.value;\n if (r) {\n const t = props.api.grid.getTile(r.tileId);\n let committed = false;\n if (t) {\n if (r.previewCol !== t.col || r.previewRow !== t.row) {\n props.api.moveTile(r.tileId, { col: r.previewCol, row: r.previewRow });\n }\n if (r.previewW !== t.w || r.previewH !== t.h) {\n committed = props.api.resizeTile(r.tileId, { w: r.previewW, h: r.previewH });\n } else {\n committed = r.previewCol !== r.startCol || r.previewRow !== r.startRow\n || r.previewW !== r.startW || r.previewH !== r.startH;\n }\n }\n resize.value = null;\n emit('resizeEnd', r.tileId, committed);\n }\n}\n\nfunction updateViewport() {\n const el = scrollEl.value;\n if (!el) return;\n viewport.value = {\n scrollX: el.scrollLeft,\n scrollY: el.scrollTop,\n width: el.clientWidth,\n height: el.clientHeight,\n };\n}\n\nfunction onKeyDown(e: KeyboardEvent) {\n if (e.key === 'Escape') setSelection(new Set());\n}\n\nlet ro: ResizeObserver | null = null;\nonMounted(() => {\n updateViewport();\n // scrollEl is absent while loop mode delegates to GriddleLoopGrid.\n const el = scrollEl.value;\n if (el) {\n el.addEventListener('scroll', updateViewport, { passive: true });\n ro = new ResizeObserver(updateViewport);\n ro.observe(el);\n }\n window.addEventListener('pointermove', onPointerMove);\n window.addEventListener('pointerup', onPointerUp);\n window.addEventListener('pointercancel', onPointerUp);\n window.addEventListener('keydown', onKeyDown);\n});\nonBeforeUnmount(() => {\n const el = scrollEl.value;\n if (el) el.removeEventListener('scroll', updateViewport);\n ro?.disconnect();\n window.removeEventListener('pointermove', onPointerMove);\n window.removeEventListener('pointerup', onPointerUp);\n window.removeEventListener('pointercancel', onPointerUp);\n window.removeEventListener('keydown', onKeyDown);\n});\n\nconst tileNodes = new Map<string, HTMLDivElement>();\nconst prevRects = new Map<string, { x: number; y: number }>();\nfunction registerNode(id: string, el: HTMLDivElement | null) {\n if (el) tileNodes.set(id, el);\n else tileNodes.delete(id);\n}\n\nwatch(() => props.api.version.value, async () => {\n await nextTick();\n const draggerId = drag.value?.tileId ?? null;\n const gdSet = groupDragSet.value;\n for (const t of props.api.tiles.value) {\n const x = t.col * colSize.value + halfGap.value;\n const y = t.row * rowSize.value + halfGap.value;\n if (t.id === draggerId || gdSet.has(t.id)) {\n prevRects.set(t.id, { x, y });\n continue;\n }\n const p = prevRects.get(t.id);\n const node = tileNodes.get(t.id);\n if (p && node) {\n const dx = p.x - x;\n const dy = p.y - y;\n if (dx !== 0 || dy !== 0) {\n node.style.transition = 'none';\n node.style.transform = `translate(${dx}px, ${dy}px)`;\n requestAnimationFrame(() => {\n node.style.transition = 'transform 220ms cubic-bezier(.2,.7,.2,1)';\n node.style.transform = 'translate(0,0)';\n });\n }\n }\n prevRects.set(t.id, { x, y });\n }\n});\n\n// Compute layouts for all rendered tiles in one pass so resolveStickyStacking\n// can see every sticky tile and adjust them as a group. Recomputes whenever\n// rendered, config, viewport, drag, resize, or pinDrag change.\nconst tileLayouts = computed(() => {\n const out = new Map<string, TileLayout>();\n const stickyEntries: { tile: Tile; layout: TileLayout }[] = [];\n const gd = groupDrag.value;\n const gdIds = groupDragSet.value;\n for (const tile of rendered.value) {\n let layout: TileLayout;\n if (resize.value?.tileId === tile.id) {\n const w = resize.value.previewW;\n const h = resize.value.previewH;\n layout = {\n left: resize.value.previewCol * colSize.value + halfGap.value,\n top: resize.value.previewRow * rowSize.value + halfGap.value,\n width: w * config.value.unitWidth + (w - 1) * gap.value,\n height: h * config.value.unitHeight + (h - 1) * gap.value,\n zIndex: 10,\n effective: 'static',\n };\n } else if (drag.value?.tileId === tile.id) {\n const d = drag.value;\n layout = {\n left: d.pickupCol * colSize.value + halfGap.value,\n top: d.pickupRow * rowSize.value + halfGap.value,\n width: tile.w * config.value.unitWidth + (tile.w - 1) * gap.value,\n height: tile.h * config.value.unitHeight + (tile.h - 1) * gap.value,\n transform: `translate(${d.deltaX}px, ${d.deltaY}px)`,\n zIndex: 20,\n effective: 'static',\n };\n } else if (gd && gdIds.has(tile.id)) {\n const pickup = groupDragController.pickupCell(tile.id);\n const left = (pickup ? pickup.col * colSize.value : tile.col * colSize.value) + halfGap.value;\n const top = (pickup ? pickup.row * rowSize.value : tile.row * rowSize.value) + halfGap.value;\n layout = {\n left,\n top,\n width: tile.w * config.value.unitWidth + (tile.w - 1) * gap.value,\n height: tile.h * config.value.unitHeight + (tile.h - 1) * gap.value,\n transform: `translate(${gd.deltaX}px, ${gd.deltaY}px)`,\n zIndex: 20,\n effective: 'static',\n };\n } else {\n layout = computeTileLayout({\n tile,\n config: config.value,\n scrollX: viewport.value.scrollX,\n scrollY: viewport.value.scrollY,\n viewportWidth: viewport.value.width,\n viewportHeight: viewport.value.height,\n });\n if (layout.effective === 'sticky') {\n stickyEntries.push({ tile, layout });\n }\n }\n out.set(tile.id, layout);\n }\n if (stickyEntries.length > 1) resolveStickyStacking(stickyEntries);\n return out;\n});\n\nfunction tileStyle(tile: Tile) {\n const isDragging = drag.value?.tileId === tile.id;\n const isGroupDragging = groupDragSet.value.has(tile.id) && groupDrag.value !== null;\n const isPinDragging = pinDrag.value?.tileId === tile.id;\n const isResizing = resize.value?.tileId === tile.id;\n const isSelected = selection.value.has(tile.id);\n const layout = tileLayouts.value.get(tile.id) ?? {\n left: 0, top: 0, width: 0, height: 0, zIndex: 1, effective: 'static' as const,\n };\n const lifted = isDragging || isPinDragging || isGroupDragging;\n return {\n position: 'absolute' as const,\n left: layout.left + 'px',\n top: layout.top + 'px',\n width: layout.width + 'px',\n height: layout.height + 'px',\n boxSizing: 'border-box' as const,\n cursor: lifted ? 'grabbing' : 'grab',\n userSelect: 'none' as const,\n zIndex: layout.zIndex,\n opacity: lifted || isResizing ? 0.85 : 1,\n willChange: 'transform',\n transform: layout.transform ?? '',\n filter: lifted ? 'drop-shadow(0 8px 16px rgba(0,0,0,0.18))' : '',\n transition: lifted ? 'filter 120ms ease-out, opacity 120ms ease-out' : '',\n boxShadow: isSelected\n ? '0 0 0 3px rgba(59, 91, 219, 0.85), inset 0 0 0 1px rgba(59, 91, 219, 0.3)'\n : '',\n borderRadius: (config.value.tileRadius ?? 4) + 'px',\n };\n}\n\n\nconst indicatorRect = computed(() => {\n const d = drag.value;\n if (!d || d.indicatorCol === null || d.indicatorRow === null) return null;\n const t = props.api.grid.getTile(d.tileId);\n if (!t) return null;\n return {\n left: d.indicatorCol * colSize.value + halfGap.value,\n top: d.indicatorRow * rowSize.value + halfGap.value,\n width: t.w * config.value.unitWidth + (t.w - 1) * gap.value,\n height: t.h * config.value.unitHeight + (t.h - 1) * gap.value,\n };\n});\n\nconst drawGhostRect = computed(() => {\n const ds = drawState.value;\n if (!ds) return null;\n const col = Math.min(ds.anchorCol, ds.currentCol);\n const row = Math.min(ds.anchorRow, ds.currentRow);\n const w = Math.max(1, Math.abs(ds.currentCol - ds.anchorCol) + 1);\n const h = Math.max(1, Math.abs(ds.currentRow - ds.anchorRow) + 1);\n return {\n left: col * colSize.value + halfGap.value,\n top: row * rowSize.value + halfGap.value,\n width: w * config.value.unitWidth + (w - 1) * gap.value,\n height: h * config.value.unitHeight + (h - 1) * gap.value,\n label: `${w}×${h}`,\n };\n});\n\nfunction tileHandles(tile: Tile): Corner[] {\n return tile.resizeHandles ?? config.value.resizeHandles ?? ['se'];\n}\n\nfunction handleStyle(c: Corner) {\n const size = 12;\n const base = {\n position: 'absolute' as const,\n width: size + 'px',\n height: size + 'px',\n background: 'rgba(60,60,60,0.7)',\n border: '2px solid white',\n borderRadius: '3px',\n cursor: `${c}-resize`,\n touchAction: 'none' as const,\n } as Record<string, unknown>;\n if (c === 'nw') return { ...base, top: -size / 2 + 'px', left: -size / 2 + 'px' };\n if (c === 'ne') return { ...base, top: -size / 2 + 'px', right: -size / 2 + 'px' };\n if (c === 'sw') return { ...base, bottom: -size / 2 + 'px', left: -size / 2 + 'px' };\n return { ...base, bottom: -size / 2 + 'px', right: -size / 2 + 'px' };\n}\n\nconst className = computed(() => props.className ?? '');\n</script>\n","// Vue composable that wraps a Grid instance with reactive state.\n\nimport { onBeforeUnmount, reactive, ref, shallowRef } from 'vue';\nimport { Grid } from '@griddle/core';\nimport type { GridConfig, Tile, GridSnapshot } from '@griddle/core';\n\nexport interface UseGriddleInit {\n config: GridConfig;\n tiles?: Tile[];\n}\n\nexport function useGriddle(init: UseGriddleInit) {\n const grid = new Grid(init.config, init.tiles ?? []);\n\n // Reactive mirrors of tiles and config. We re-assign on changes.\n const tiles = shallowRef<Tile[]>(grid.tiles);\n const config = shallowRef<GridConfig>(grid.config);\n const version = ref(0);\n\n const off = grid.changes.on(() => {\n tiles.value = grid.tiles;\n config.value = grid.config;\n version.value++;\n });\n onBeforeUnmount(off);\n\n const api = {\n grid,\n tiles,\n config,\n version,\n moveTile: (id: string, target: { col: number; row: number }) => grid.moveTile(id, target),\n resizeTile: (id: string, size: { w: number; h: number }) => grid.resizeTile(id, size),\n addTile: (t: Tile) => grid.addTile(t),\n removeTile: (id: string) => grid.removeTile(id),\n updateConfig: (patch: Partial<GridConfig>) => grid.updateConfig(patch),\n toJSON: () => grid.toJSON(),\n loadJSON: (snap: GridSnapshot) => grid.loadJSON(snap),\n };\n return api;\n}\n\nexport type GriddleApi = ReturnType<typeof useGriddle>;\n"],"names":["DEFAULT_DRAG_IGNORE","PAN_THRESHOLD_PX","props","__props","emit","__emit","viewportEl","ref","planeEl","config","computed","loop","resolveLoop","editable","_a","gap","halfGap","colSize","rowSize","period","loopPeriod","pan","PanController","watch","l","view","lastCam","raf","resizeObserver","onWheel","e","k","frame","now","st","plane","el","cxCell","cyCell","cur","instances","bufX","bufY","loopInstances","panGesture","suppressClick","onContainerPointerDown","onTile","setSelection","ignoreSelector","onClickCapture","internalSelection","selection","next","dragController","DragController","drag","dragStartPointerX","dragStartPointerY","resize","syncTiles","isBase","inst","isGhost","onTilePointerDown","tile","onResizeHandleDown","c","baseLeft","baseTop","onPointerMove","d","dx","dy","candidate","result","r","dw","dh","dcol","drow","stepsX","stepsY","minW","minH","maxW","maxH","nW","nH","nC","nR","onPointerUp","tileId","committed","t","target","onKeyDown","onMounted","measure","onBeforeUnmount","tileNodes","prevRects","registerNode","key","nextTick","draggerId","seen","x","y","p","node","viewportStyle","bg","planeStyle","instanceStyle","isResizingInst","left","top","width","heightPx","ghost","isSelected","draggedTile","dragOverlayStyle","indicatorRect","tileHandles","handleStyle","base","className","_createElementBlock","_createElementVNode","_normalizeStyle","_Fragment","_renderList","_normalizeClass","_renderSlot","_ctx","_openBlock","loopOn","scrollEl","viewport","range","visibleRange","rendered","visibleTiles","contentSize","gridContentSize","scrollStyle","contentStyle","groupDragSet","groupDrag","groupDragController","GroupDragController","pinDrag","drawState","metaKey","isOutOfFlow","layout","computeTileLayout","startPinPx","tileIsSelected","effectiveSelection","ids","onBackgroundPointerDown","rect","col","row","pd","gd","newPinPx","newPin","pixelsToPin","_b","candidateCol","candidateRow","ds","w","h","tileIds","firstId","updateViewport","ro","id","gdSet","tileLayouts","out","stickyEntries","gdIds","pickup","resolveStickyStacking","tileStyle","isDragging","isGroupDragging","isPinDragging","isResizing","_c","lifted","drawGhostRect","_createBlock","GriddleLoopGrid","_cache","s","cam","_withCtx","slotProps","_toDisplayString","useGriddle","init","grid","Grid","tiles","shallowRef","version","off","size","patch","snap"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../src/LoopGrid.vue","../src/GriddleGrid.vue","../src/useGriddle.ts"],"sourcesContent":["<template>\n <div\n ref=\"viewportEl\"\n :class=\"className\"\n :style=\"viewportStyle\"\n @pointerdown=\"onContainerPointerDown\"\n @click.capture=\"onClickCapture\"\n >\n <div ref=\"planeEl\" :style=\"planeStyle\">\n <div\n v-if=\"indicatorRect\"\n class=\"griddle-drop-indicator\"\n :style=\"{\n position: 'absolute',\n left: indicatorRect.left + 'px',\n top: indicatorRect.top + 'px',\n width: indicatorRect.width + 'px',\n height: indicatorRect.height + 'px',\n boxSizing: 'border-box',\n border: '2px dashed rgba(59, 91, 219, 0.55)',\n background: 'rgba(59, 91, 219, 0.08)',\n borderRadius: (config.tileRadius ?? 4) + 'px',\n pointerEvents: 'none',\n zIndex: 5,\n }\"\n ></div>\n <template v-for=\"inst in instances\" :key=\"inst.key\">\n <div\n v-if=\"!(drag && inst.tile.id === drag.tileId)\"\n :data-griddle-tile=\"inst.tile.id\"\n :data-griddle-instance=\"inst.key\"\n :data-griddle-ghost=\"isGhost(inst) ? '' : undefined\"\n :aria-hidden=\"isBase(inst) ? undefined : true\"\n :class=\"['griddle-tile', {\n 'griddle-resizing': resize?.instanceKey === inst.key,\n 'griddle-selected': editable && isBase(inst) && selection.has(inst.tile.id),\n }]\"\n :style=\"instanceStyle(inst)\"\n :ref=\"(el) => registerNode(inst.key, el as HTMLDivElement | null)\"\n @pointerdown=\"(e) => onTilePointerDown(e, inst)\"\n >\n <slot name=\"tile\" :tile=\"inst.tile\" :selected=\"editable && isBase(inst) && selection.has(inst.tile.id)\" />\n <template v-if=\"editable && isBase(inst) && inst.tile.resizable !== false\">\n <div\n v-for=\"c in tileHandles(inst.tile)\"\n :key=\"c\"\n :data-griddle-handle=\"c\"\n :style=\"handleStyle(c)\"\n @pointerdown=\"(e) => onResizeHandleDown(e, inst, c)\"\n ></div>\n </template>\n </div>\n </template>\n <div\n v-if=\"drag && draggedTile\"\n :data-griddle-tile=\"draggedTile.id\"\n class=\"griddle-tile griddle-dragging\"\n :style=\"dragOverlayStyle\"\n >\n <slot name=\"tile\" :tile=\"draggedTile\" :selected=\"selection.has(draggedTile.id)\" />\n </div>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\n// Loop-mode renderer (\"object looping\") — see @griddle/core loop.ts for the\n// coordinate model. Mirrors the React GriddleLoopGrid: an overflow-hidden\n// viewport, a transform-translated plane driven by an unbounded camera, and\n// NO native scrolling (wheel deltas feed the camera directly).\nimport { computed, onBeforeUnmount, onMounted, ref, watch, nextTick } from 'vue';\nimport type { CameraState, CellPos, Corner, Tile } from '@griddle/core';\nimport {\n DragController,\n PanController,\n loopInstances,\n loopPeriod,\n resolveLoop,\n} from '@griddle/core';\nimport type { LoopTileInstance } from '@griddle/core';\nimport type { GriddleApi } from './useGriddle.js';\n\nconst props = defineProps<{\n api: GriddleApi;\n className?: string;\n height?: number | string;\n showGrid?: boolean;\n selection?: Set<string>;\n}>();\n\nconst emit = defineEmits<{\n (e: 'selectionChange', selection: Set<string>): void;\n (e: 'dragStart', tileId: string): void;\n (e: 'dragEnd', tileId: string, committed: boolean): void;\n (e: 'resizeStart', tileId: string): void;\n (e: 'resizeEnd', tileId: string, committed: boolean): void;\n (e: 'cameraChange', camera: CameraState): void;\n}>();\n\nconst DEFAULT_DRAG_IGNORE = 'a, button, input, textarea, select, [contenteditable]';\nconst PAN_THRESHOLD_PX = 4;\n\nconst viewportEl = ref<HTMLDivElement | null>(null);\nconst planeEl = ref<HTMLDivElement | null>(null);\n\nconst config = computed(() => props.api.config.value);\nconst loop = computed(() => resolveLoop(config.value));\nconst editable = computed(() => loop.value?.interaction === 'edit');\nconst gap = computed(() => config.value.gap ?? 0);\nconst halfGap = computed(() => gap.value / 2);\nconst colSize = computed(() => config.value.unitWidth + gap.value);\nconst rowSize = computed(() => config.value.unitHeight + gap.value);\nconst period = computed(() => loopPeriod(config.value, props.api.tiles.value));\n\n// ---- camera plumbing ------------------------------------------------------\nconst pan = new PanController();\nwatch(loop, (l) => {\n if (l) pan.setPhysics({ friction: l.friction, ease: l.ease, maxVelocity: l.maxVelocity });\n}, { immediate: true });\n\nconst view = ref({ cxCell: 0, cyCell: 0, vw: 1000, vh: 800 });\nlet lastCam: CameraState | null = null;\nlet raf = 0;\nlet resizeObserver: ResizeObserver | null = null;\n\nfunction onWheel(e: WheelEvent) {\n e.preventDefault();\n const k = e.deltaMode === 1 ? 16 : e.deltaMode === 2 ? 100 : 1;\n pan.scrollBy(e.deltaX * k, e.deltaY * k);\n}\n\nfunction frame(now: number) {\n raf = requestAnimationFrame(frame);\n const st = pan.tick(now);\n\n const plane = planeEl.value;\n if (plane) {\n plane.style.transform = `translate3d(${-st.x}px, ${-st.y}px, 0)`;\n }\n const el = viewportEl.value;\n if (el && props.showGrid !== false) {\n el.style.backgroundPosition = `${-st.x % colSize.value}px ${-st.y % rowSize.value}px`;\n }\n\n const cxCell = Math.floor(st.x / colSize.value);\n const cyCell = Math.floor(st.y / rowSize.value);\n const cur = view.value;\n if (cxCell !== cur.cxCell || cyCell !== cur.cyCell) {\n view.value = { ...cur, cxCell, cyCell };\n }\n\n if (\n !lastCam || lastCam.x !== st.x || lastCam.y !== st.y ||\n lastCam.isMoving !== st.isMoving || lastCam.isDragging !== st.isDragging\n ) {\n lastCam = st;\n emit('cameraChange', st);\n }\n}\n\nconst instances = computed(() => {\n void props.api.version.value; // re-run on grid changes\n const bufX = 2 * colSize.value;\n const bufY = 2 * rowSize.value;\n return loopInstances(config.value, props.api.tiles.value, {\n x: view.value.cxCell * colSize.value - bufX,\n y: view.value.cyCell * rowSize.value - bufY,\n width: view.value.vw + colSize.value + 2 * bufX,\n height: view.value.vh + rowSize.value + 2 * bufY,\n });\n});\n\n// ---- pan gesture ----------------------------------------------------------\nlet panGesture: { pointerId: number; startX: number; startY: number; moved: boolean } | null = null;\nlet suppressClick = false;\n\nfunction onContainerPointerDown(e: PointerEvent) {\n const onTile = !!(e.target as HTMLElement).closest('[data-griddle-tile]');\n if (editable.value && !onTile) setSelection(new Set());\n // Tiles that start drags stopPropagation, so reaching here from a tile\n // means it was not draggable — panning is the right fallback.\n if (!loop.value?.dragPan || e.button !== 0) return;\n const ignoreSelector = config.value.dragIgnoreFrom ?? DEFAULT_DRAG_IGNORE;\n if (ignoreSelector && (e.target as HTMLElement).closest(ignoreSelector)) return;\n panGesture = { pointerId: e.pointerId, startX: e.clientX, startY: e.clientY, moved: false };\n}\n\nfunction onClickCapture(e: MouseEvent) {\n if (suppressClick) {\n suppressClick = false;\n e.preventDefault();\n e.stopPropagation();\n }\n}\n\n// ---- selection ('edit' interaction) ---------------------------------------\nconst internalSelection = ref<Set<string>>(new Set());\nconst selection = computed(() => props.selection ?? internalSelection.value);\nfunction setSelection(next: Set<string>) {\n if (!props.selection) internalSelection.value = next;\n emit('selectionChange', next);\n}\n\n// ---- tile drag / resize ('edit' interaction) ------------------------------\nconst dragController = new DragController(props.api.grid);\n\ninterface LoopDragVisual {\n tileId: string;\n instanceLeft: number;\n instanceTop: number;\n pickupCol: number;\n pickupRow: number;\n deltaX: number;\n deltaY: number;\n indicatorCol: number | null;\n indicatorRow: number | null;\n}\nconst drag = ref<LoopDragVisual | null>(null);\nlet dragStartPointerX = 0;\nlet dragStartPointerY = 0;\n\ninterface LoopResizeState {\n tileId: string;\n instanceKey: string;\n instanceDx: number;\n instanceDy: number;\n corner: Corner;\n startPointerX: number;\n startPointerY: number;\n startW: number;\n startH: number;\n startCol: number;\n startRow: number;\n previewW: number;\n previewH: number;\n previewCol: number;\n previewRow: number;\n}\nconst resize = ref<LoopResizeState | null>(null);\n\nfunction syncTiles() {\n props.api.tiles.value = props.api.grid.tiles;\n props.api.version.value++;\n}\n\nfunction isBase(inst: LoopTileInstance): boolean {\n return inst.kx === 0 && inst.ky === 0;\n}\nfunction isGhost(inst: LoopTileInstance): boolean {\n return editable.value && !isBase(inst);\n}\n\nfunction onTilePointerDown(e: PointerEvent, inst: LoopTileInstance) {\n if (!editable.value) return; // pan mode: container pan handler takes it\n if (!isBase(inst)) return; // ghosts are display-only\n const tile = inst.tile;\n if (tile.draggable === false) return;\n if ((e.target as HTMLElement).dataset.griddleHandle) return;\n const ignoreSelector = config.value.dragIgnoreFrom ?? DEFAULT_DRAG_IGNORE;\n if (ignoreSelector && (e.target as HTMLElement).closest(ignoreSelector)) return;\n\n if (e.metaKey || e.ctrlKey) {\n e.preventDefault();\n const next = new Set(selection.value);\n if (next.has(tile.id)) next.delete(tile.id);\n else next.add(tile.id);\n setSelection(next);\n e.stopPropagation();\n return;\n }\n setSelection(new Set([tile.id]));\n\n // No pointer capture: the grabbed instance unmounts (drag renders as an\n // overlay), which would release the capture mid-gesture.\n if (!dragController.start(tile.id)) return;\n dragStartPointerX = e.clientX;\n dragStartPointerY = e.clientY;\n drag.value = {\n tileId: tile.id,\n instanceLeft: inst.left,\n instanceTop: inst.top,\n pickupCol: tile.col,\n pickupRow: tile.row,\n deltaX: 0,\n deltaY: 0,\n indicatorCol: tile.col,\n indicatorRow: tile.row,\n };\n emit('dragStart', tile.id);\n e.stopPropagation();\n}\n\nfunction onResizeHandleDown(e: PointerEvent, inst: LoopTileInstance, c: Corner) {\n if (!editable.value) return;\n const tile = inst.tile;\n if (tile.resizable === false) return;\n (e.currentTarget as HTMLDivElement).setPointerCapture(e.pointerId);\n const baseLeft = tile.col * colSize.value + halfGap.value;\n const baseTop = tile.row * rowSize.value + halfGap.value;\n resize.value = {\n tileId: tile.id,\n instanceKey: inst.key,\n instanceDx: inst.left - baseLeft,\n instanceDy: inst.top - baseTop,\n corner: c,\n startPointerX: e.clientX,\n startPointerY: e.clientY,\n startW: tile.w,\n startH: tile.h,\n startCol: tile.col,\n startRow: tile.row,\n previewW: tile.w,\n previewH: tile.h,\n previewCol: tile.col,\n previewRow: tile.row,\n };\n emit('resizeStart', tile.id);\n e.stopPropagation();\n}\n\nfunction onPointerMove(e: PointerEvent) {\n if (panGesture && e.pointerId === panGesture.pointerId) {\n const now = performance.now();\n if (!panGesture.moved) {\n const dist = Math.hypot(e.clientX - panGesture.startX, e.clientY - panGesture.startY);\n if (dist >= PAN_THRESHOLD_PX) {\n panGesture.moved = true;\n pan.dragStart(panGesture.startX, panGesture.startY, now);\n pan.dragMove(e.clientX, e.clientY, now);\n }\n } else {\n pan.dragMove(e.clientX, e.clientY, now);\n }\n return;\n }\n\n const d = drag.value;\n if (d) {\n // Ghost edit: plain grid semantics in the base copy — no wrapping.\n const dx = e.clientX - dragStartPointerX;\n const dy = e.clientY - dragStartPointerY;\n const candidate: CellPos = {\n col: d.pickupCol + Math.round(dx / colSize.value),\n row: d.pickupRow + Math.round(dy / rowSize.value),\n };\n const result = dragController.update(candidate);\n drag.value = {\n ...d,\n deltaX: dx,\n deltaY: dy,\n indicatorCol: result.indicatorCell ? result.indicatorCell.col : null,\n indicatorRow: result.indicatorCell ? result.indicatorCell.row : null,\n };\n if (result.changed) syncTiles();\n }\n\n const r = resize.value;\n if (r) {\n const dx = e.clientX - r.startPointerX;\n const dy = e.clientY - r.startPointerY;\n let dw = 0, dh = 0, dcol = 0, drow = 0;\n const stepsX = Math.round(dx / colSize.value);\n const stepsY = Math.round(dy / rowSize.value);\n if (r.corner === 'se' || r.corner === 'ne') dw = stepsX;\n if (r.corner === 'se' || r.corner === 'sw') dh = stepsY;\n if (r.corner === 'sw' || r.corner === 'nw') { dw = -stepsX; dcol = stepsX; }\n if (r.corner === 'ne' || r.corner === 'nw') { dh = -stepsY; drow = stepsY; }\n const tile = props.api.grid.getTile(r.tileId);\n const minW = tile?.minW ?? 1;\n const minH = tile?.minH ?? 1;\n const maxW = Math.min(tile?.maxW ?? Infinity, config.value.cols);\n const maxH = Math.min(tile?.maxH ?? Infinity, config.value.rows);\n const nW = Math.min(maxW, Math.max(minW, r.startW + dw));\n const nH = Math.min(maxH, Math.max(minH, r.startH + dh));\n const nC = r.startCol + dcol;\n const nR = r.startRow + drow;\n if (nW !== r.previewW || nH !== r.previewH || nC !== r.previewCol || nR !== r.previewRow) {\n resize.value = { ...r, previewW: nW, previewH: nH, previewCol: nC, previewRow: nR };\n }\n }\n}\n\nfunction onPointerUp(e: PointerEvent) {\n if (panGesture && e.pointerId === panGesture.pointerId) {\n if (panGesture.moved) {\n pan.dragEnd(performance.now());\n suppressClick = true;\n }\n panGesture = null;\n return;\n }\n\n if (drag.value) {\n const tileId = drag.value.tileId;\n const { committed } = dragController.end();\n drag.value = null;\n syncTiles();\n emit('dragEnd', tileId, committed);\n }\n const r = resize.value;\n if (r) {\n const t = props.api.grid.getTile(r.tileId);\n let committed = false;\n if (t) {\n const target = { col: r.previewCol, row: r.previewRow };\n if (target.col !== t.col || target.row !== t.row) {\n props.api.moveTile(r.tileId, target);\n }\n if (r.previewW !== t.w || r.previewH !== t.h) {\n committed = props.api.resizeTile(r.tileId, { w: r.previewW, h: r.previewH });\n } else {\n committed = r.previewCol !== r.startCol || r.previewRow !== r.startRow\n || r.previewW !== r.startW || r.previewH !== r.startH;\n }\n }\n resize.value = null;\n emit('resizeEnd', r.tileId, committed);\n }\n}\n\nfunction onKeyDown(e: KeyboardEvent) {\n if (e.key === 'Escape' && editable.value) setSelection(new Set());\n}\n\nonMounted(() => {\n const el = viewportEl.value;\n if (el) {\n el.addEventListener('wheel', onWheel, { passive: false });\n const measure = () => {\n const cur = view.value;\n if (el.clientWidth !== cur.vw || el.clientHeight !== cur.vh) {\n view.value = { ...cur, vw: el.clientWidth, vh: el.clientHeight };\n }\n };\n measure();\n resizeObserver = new ResizeObserver(measure);\n resizeObserver.observe(el);\n }\n raf = requestAnimationFrame(frame);\n window.addEventListener('pointermove', onPointerMove);\n window.addEventListener('pointerup', onPointerUp);\n window.addEventListener('pointercancel', onPointerUp);\n window.addEventListener('keydown', onKeyDown);\n});\nonBeforeUnmount(() => {\n cancelAnimationFrame(raf);\n viewportEl.value?.removeEventListener('wheel', onWheel);\n resizeObserver?.disconnect();\n window.removeEventListener('pointermove', onPointerMove);\n window.removeEventListener('pointerup', onPointerUp);\n window.removeEventListener('pointercancel', onPointerUp);\n window.removeEventListener('keydown', onKeyDown);\n});\n\n// ---- FLIP for edit-mode repacks (keyed by world key) ----------------------\nconst tileNodes = new Map<string, HTMLDivElement>();\nconst prevRects = new Map<string, { x: number; y: number }>();\nfunction registerNode(key: string, el: HTMLDivElement | null) {\n if (el) tileNodes.set(key, el);\n else tileNodes.delete(key);\n}\n\nwatch(() => props.api.version.value, async () => {\n await nextTick();\n const draggerId = drag.value?.tileId ?? null;\n const seen = new Set<string>();\n for (const inst of instances.value) {\n const key = inst.key;\n seen.add(key);\n const x = inst.left;\n const y = inst.top;\n if (editable.value && inst.tile.id !== draggerId) {\n const p = prevRects.get(key);\n const node = tileNodes.get(key);\n if (p && node) {\n const dx = p.x - x;\n const dy = p.y - y;\n if (\n (dx !== 0 || dy !== 0) &&\n Math.abs(dx) < period.value.width / 2 &&\n Math.abs(dy) < period.value.height / 2\n ) {\n node.style.transition = 'none';\n node.style.transform = `translate(${dx}px, ${dy}px)`;\n requestAnimationFrame(() => {\n node.style.transition = 'transform 220ms cubic-bezier(.2,.7,.2,1)';\n node.style.transform = 'translate(0,0)';\n });\n }\n }\n }\n prevRects.set(key, { x, y });\n }\n for (const key of prevRects.keys()) {\n if (!seen.has(key)) prevRects.delete(key);\n }\n});\n\n// ---- styles ----------------------------------------------------------------\nconst viewportStyle = computed(() => {\n const showGrid = props.showGrid !== false;\n const bg = showGrid\n ? {\n backgroundImage: `linear-gradient(to right, rgba(0,0,0,0.08) 1px, transparent 1px), linear-gradient(to bottom, rgba(0,0,0,0.08) 1px, transparent 1px)`,\n backgroundSize: `${colSize.value}px ${rowSize.value}px`,\n backgroundPosition: '0 0',\n }\n : {};\n return {\n position: 'relative' as const,\n overflow: 'hidden' as const,\n height: typeof props.height === 'number' ? props.height + 'px' : (props.height ?? '100%'),\n touchAction: 'none' as const,\n userSelect: 'none' as const,\n cursor: !editable.value && loop.value?.dragPan ? 'grab' : undefined,\n ['--griddle-tile-radius' as string]: (config.value.tileRadius ?? 4) + 'px',\n ...bg,\n };\n});\n\nconst planeStyle = computed(() => ({\n position: 'absolute' as const,\n top: '0',\n left: '0',\n width: '0',\n height: '0',\n willChange: 'transform',\n}));\n\nfunction instanceStyle(inst: LoopTileInstance) {\n const r = resize.value;\n const isResizingInst = r?.instanceKey === inst.key;\n let left = inst.left;\n let top = inst.top;\n let width = inst.width;\n let heightPx = inst.height;\n if (isResizingInst && r) {\n left = r.previewCol * colSize.value + halfGap.value + r.instanceDx;\n top = r.previewRow * rowSize.value + halfGap.value + r.instanceDy;\n width = r.previewW * config.value.unitWidth + (r.previewW - 1) * gap.value;\n heightPx = r.previewH * config.value.unitHeight + (r.previewH - 1) * gap.value;\n }\n const ghost = isGhost(inst);\n const isSelected = editable.value && isBase(inst) && selection.value.has(inst.tile.id);\n return {\n position: 'absolute' as const,\n left: left + 'px',\n top: top + 'px',\n width: width + 'px',\n height: heightPx + 'px',\n boxSizing: 'border-box' as const,\n cursor: editable.value && isBase(inst) ? 'grab' : undefined,\n userSelect: 'none' as const,\n // Ghosts are display-only: pointer-transparent (so the gesture falls\n // through to drag-pan) and dimmed to mark the editable copy.\n pointerEvents: ghost ? ('none' as const) : undefined,\n zIndex: isResizingInst ? 10 : 1,\n opacity: isResizingInst ? 0.85 : ghost ? 0.55 : 1,\n boxShadow: isSelected\n ? '0 0 0 3px rgba(59, 91, 219, 0.85), inset 0 0 0 1px rgba(59, 91, 219, 0.3)'\n : '',\n borderRadius: (config.value.tileRadius ?? 4) + 'px',\n };\n}\n\nconst draggedTile = computed<Tile | null>(() =>\n drag.value ? props.api.grid.getTile(drag.value.tileId) ?? null : null,\n);\n\nconst dragOverlayStyle = computed(() => {\n const d = drag.value;\n const t = draggedTile.value;\n if (!d || !t) return {};\n return {\n position: 'absolute' as const,\n left: d.instanceLeft + 'px',\n top: d.instanceTop + 'px',\n width: t.w * config.value.unitWidth + (t.w - 1) * gap.value + 'px',\n height: t.h * config.value.unitHeight + (t.h - 1) * gap.value + 'px',\n boxSizing: 'border-box' as const,\n cursor: 'grabbing',\n userSelect: 'none' as const,\n zIndex: 20,\n opacity: 0.85,\n transform: `translate(${d.deltaX}px, ${d.deltaY}px)`,\n filter: 'drop-shadow(0 8px 16px rgba(0,0,0,0.18))',\n borderRadius: (config.value.tileRadius ?? 4) + 'px',\n pointerEvents: 'none' as const,\n };\n});\n\n// Drop indicator: rendered in the base copy (ghost edit is plain-grid).\nconst indicatorRect = computed(() => {\n const d = drag.value;\n if (!d || d.indicatorCol === null || d.indicatorRow === null) return null;\n const t = props.api.grid.getTile(d.tileId);\n if (!t) return null;\n return {\n left: d.indicatorCol * colSize.value + halfGap.value,\n top: d.indicatorRow * rowSize.value + halfGap.value,\n width: t.w * config.value.unitWidth + (t.w - 1) * gap.value,\n height: t.h * config.value.unitHeight + (t.h - 1) * gap.value,\n };\n});\n\nfunction tileHandles(tile: Tile): Corner[] {\n return tile.resizeHandles ?? config.value.resizeHandles ?? ['se'];\n}\n\nfunction handleStyle(c: Corner) {\n const size = 12;\n const base = {\n position: 'absolute' as const,\n width: size + 'px',\n height: size + 'px',\n background: 'rgba(60,60,60,0.7)',\n border: '2px solid white',\n borderRadius: '3px',\n cursor: `${c}-resize`,\n touchAction: 'none' as const,\n } as Record<string, unknown>;\n if (c === 'nw') return { ...base, top: -size / 2 + 'px', left: -size / 2 + 'px' };\n if (c === 'ne') return { ...base, top: -size / 2 + 'px', right: -size / 2 + 'px' };\n if (c === 'sw') return { ...base, bottom: -size / 2 + 'px', left: -size / 2 + 'px' };\n return { ...base, bottom: -size / 2 + 'px', right: -size / 2 + 'px' };\n}\n\nconst className = computed(() => props.className ?? '');\n</script>\n","<template>\n <GriddleLoopGrid\n v-if=\"loopOn\"\n :api=\"api\"\n :class-name=\"className\"\n :height=\"height\"\n :show-grid=\"showGrid\"\n :selection=\"props.selection\"\n @selection-change=\"(s) => emit('selectionChange', s)\"\n @drag-start=\"(id) => emit('dragStart', id)\"\n @drag-end=\"(id, c) => emit('dragEnd', id, c)\"\n @resize-start=\"(id) => emit('resizeStart', id)\"\n @resize-end=\"(id, c) => emit('resizeEnd', id, c)\"\n @camera-change=\"(cam) => emit('cameraChange', cam)\"\n >\n <template #tile=\"slotProps\">\n <slot name=\"tile\" v-bind=\"slotProps\" />\n </template>\n </GriddleLoopGrid>\n <div\n v-else\n ref=\"scrollEl\"\n :class=\"className\"\n :style=\"scrollStyle\"\n @pointerdown=\"onBackgroundPointerDown\"\n >\n <div :style=\"contentStyle\">\n <div\n v-if=\"indicatorRect\"\n class=\"griddle-drop-indicator\"\n :style=\"{\n position: 'absolute',\n left: indicatorRect.left + 'px',\n top: indicatorRect.top + 'px',\n width: indicatorRect.width + 'px',\n height: indicatorRect.height + 'px',\n boxSizing: 'border-box',\n border: '2px dashed rgba(59, 91, 219, 0.55)',\n background: 'rgba(59, 91, 219, 0.08)',\n borderRadius: (config.tileRadius ?? 4) + 'px',\n pointerEvents: 'none',\n zIndex: 5,\n }\"\n ></div>\n <div\n v-if=\"drawGhostRect\"\n class=\"griddle-draw-ghost\"\n :style=\"{\n position: 'absolute',\n left: drawGhostRect.left + 'px',\n top: drawGhostRect.top + 'px',\n width: drawGhostRect.width + 'px',\n height: drawGhostRect.height + 'px',\n boxSizing: 'border-box',\n border: '2px dashed rgba(59, 91, 219, 0.55)',\n background: 'rgba(59, 91, 219, 0.08)',\n borderRadius: (config.tileRadius ?? 4) + 'px',\n pointerEvents: 'none',\n zIndex: 5,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n fontSize: '14px',\n fontWeight: '600',\n color: 'rgba(59, 91, 219, 0.8)',\n userSelect: 'none',\n }\"\n >{{ drawGhostRect.label }}</div>\n <div\n v-for=\"tile in rendered\"\n :key=\"tile.id\"\n :data-griddle-tile=\"tile.id\"\n :class=\"['griddle-tile', {\n 'griddle-dragging': drag?.tileId === tile.id || pinDrag?.tileId === tile.id || (groupDrag !== null && groupDragSet.has(tile.id)),\n 'griddle-resizing': resize?.tileId === tile.id,\n 'griddle-selected': selection.has(tile.id),\n }]\"\n :style=\"tileStyle(tile)\"\n @pointerdown=\"(e) => onTilePointerDown(e, tile)\"\n :ref=\"(el) => registerNode(tile.id, el as HTMLDivElement | null)\"\n >\n <slot name=\"tile\" :tile=\"tile\" :selected=\"selection.has(tile.id)\" />\n <template v-if=\"tile.resizable !== false\">\n <div\n v-for=\"c in tileHandles(tile)\"\n :key=\"c\"\n :data-griddle-handle=\"c\"\n :style=\"handleStyle(c)\"\n @pointerdown=\"(e) => onResizeHandleDown(e, tile, c)\"\n ></div>\n </template>\n </div>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, onBeforeUnmount, onMounted, ref, watch, nextTick } from 'vue';\nimport type { CameraState, Corner, Tile } from '@griddle/core';\nimport GriddleLoopGrid from './LoopGrid.vue';\nimport {\n visibleRange,\n visibleTiles,\n gridContentSize,\n DragController,\n GroupDragController,\n computeTileLayout,\n resolveStickyStacking,\n isOutOfFlow,\n pixelsToPin,\n} from '@griddle/core';\nimport type { TileLayout } from '@griddle/core';\nimport type { GriddleApi } from './useGriddle.js';\n\nconst props = defineProps<{\n api: GriddleApi;\n className?: string;\n height?: number | string;\n showGrid?: boolean;\n /** Controlled selection. If omitted, managed internally. */\n selection?: Set<string>;\n}>();\n\nconst emit = defineEmits<{\n (e: 'selectionChange', selection: Set<string>): void;\n (e: 'drawCreate', rect: { col: number; row: number; w: number; h: number }): void;\n (e: 'dragStart', tileId: string): void;\n (e: 'dragEnd', tileId: string, committed: boolean): void;\n (e: 'resizeStart', tileId: string): void;\n (e: 'resizeEnd', tileId: string, committed: boolean): void;\n (e: 'cameraChange', camera: CameraState): void;\n}>();\n\n/** Loop mode delegates rendering to GriddleLoopGrid. */\nconst loopOn = computed(() => props.api.config.value.loop?.enabled === true);\n\nconst scrollEl = ref<HTMLDivElement | null>(null);\nconst viewport = ref({ scrollX: 0, scrollY: 0, width: 1000, height: 800 });\n\nconst config = computed(() => props.api.config.value);\nconst gap = computed(() => config.value.gap ?? 0);\nconst halfGap = computed(() => gap.value / 2);\nconst colSize = computed(() => config.value.unitWidth + gap.value);\nconst rowSize = computed(() => config.value.unitHeight + gap.value);\n\nconst range = computed(() => visibleRange(config.value, viewport.value, 4));\nconst rendered = computed(() => visibleTiles(props.api.tiles.value, range.value));\nconst contentSize = computed(() => gridContentSize(config.value, props.api.tiles.value));\n\nconst scrollStyle = computed(() => {\n // 'none' scroll mode: the grid sizes to content and lets the host page own\n // scrolling/panning — no internal scroll box, no touch-action lock.\n const contained = config.value.scroll !== 'none';\n const style: Record<string, string | number> = {\n position: 'relative',\n overflow: contained ? 'auto' : 'visible',\n height: contained ? (props.height ?? '100%') : (props.height ?? 'auto'),\n };\n if (contained) style.touchAction = 'none';\n return style;\n});\n\nconst contentStyle = computed(() => {\n const showGrid = props.showGrid !== false;\n const bg = showGrid\n ? {\n backgroundImage: `linear-gradient(to right, rgba(0,0,0,0.08) 1px, transparent 1px), linear-gradient(to bottom, rgba(0,0,0,0.08) 1px, transparent 1px)`,\n backgroundSize: `${colSize.value}px ${rowSize.value}px`,\n }\n : {};\n return {\n position: 'relative' as const,\n width: contentSize.value.width || '100%',\n height: contentSize.value.height || '100%',\n minWidth: '100%',\n minHeight: '100%',\n // Expose tile radius as a CSS variable so user tile content can pick it up.\n ['--griddle-tile-radius' as string]: (config.value.tileRadius ?? 4) + 'px',\n ...bg,\n };\n});\n\n// Selection state\nconst internalSelection = ref<Set<string>>(new Set());\nconst selection = computed(() => props.selection ?? internalSelection.value);\nconst groupDragSet = computed(() => new Set(groupDrag.value?.tileIds ?? []));\nfunction setSelection(next: Set<string>) {\n if (!props.selection) internalSelection.value = next;\n emit('selectionChange', next);\n}\n\nconst DEFAULT_DRAG_IGNORE = 'a, button, input, textarea, select, [contenteditable]';\n\nconst dragController = new DragController(props.api.grid);\nconst groupDragController = new GroupDragController(props.api.grid);\n\ninterface DragVisual {\n tileId: string;\n pickupCol: number;\n pickupRow: number;\n deltaX: number;\n deltaY: number;\n indicatorCol: number | null;\n indicatorRow: number | null;\n}\nconst drag = ref<DragVisual | null>(null);\nlet dragStartPointerX = 0;\nlet dragStartPointerY = 0;\n\ninterface GroupDragVisual {\n tileIds: string[];\n deltaX: number;\n deltaY: number;\n committedDcol: number;\n committedDrow: number;\n}\nconst groupDrag = ref<GroupDragVisual | null>(null);\n\ninterface PinDragState {\n tileId: string;\n startPinPx: { x: number; y: number };\n startPointerX: number;\n startPointerY: number;\n}\nconst pinDrag = ref<PinDragState | null>(null);\n\ninterface ResizeState {\n tileId: string;\n corner: Corner;\n startPointerX: number;\n startPointerY: number;\n startW: number;\n startH: number;\n startCol: number;\n startRow: number;\n previewW: number;\n previewH: number;\n previewCol: number;\n previewRow: number;\n}\nconst resize = ref<ResizeState | null>(null);\n\ninterface DrawState {\n anchorCol: number;\n anchorRow: number;\n currentCol: number;\n currentRow: number;\n}\nconst drawState = ref<DrawState | null>(null);\n\nfunction onTilePointerDown(e: PointerEvent, tile: Tile) {\n if (tile.draggable === false) return;\n if ((e.target as HTMLElement).dataset.griddleHandle) return;\n\n const ignoreSelector = config.value.dragIgnoreFrom ?? DEFAULT_DRAG_IGNORE;\n if (ignoreSelector && (e.target as HTMLElement).closest(ignoreSelector)) return;\n\n const metaKey = e.metaKey || e.ctrlKey;\n\n // Out-of-flow tiles get free-pixel drag (no selection).\n if (config.value.enablePositioning && isOutOfFlow(tile)) {\n (e.currentTarget as HTMLDivElement).setPointerCapture(e.pointerId);\n const layout = computeTileLayout({\n tile,\n config: config.value,\n scrollX: viewport.value.scrollX,\n scrollY: viewport.value.scrollY,\n viewportWidth: viewport.value.width,\n viewportHeight: viewport.value.height,\n });\n const startPinPx =\n tile.position === 'fixed'\n ? { x: layout.left - viewport.value.scrollX, y: layout.top - viewport.value.scrollY }\n : { x: layout.left, y: layout.top };\n pinDrag.value = {\n tileId: tile.id,\n startPinPx,\n startPointerX: e.clientX,\n startPointerY: e.clientY,\n };\n emit('dragStart', tile.id);\n e.stopPropagation();\n return;\n }\n\n // Cmd/Ctrl+click toggles selection without starting a drag.\n if (metaKey) {\n e.preventDefault();\n const next = new Set(selection.value);\n if (next.has(tile.id)) {\n next.delete(tile.id);\n } else {\n next.add(tile.id);\n }\n setSelection(next);\n e.stopPropagation();\n return;\n }\n\n const tileIsSelected = selection.value.has(tile.id);\n\n if (!tileIsSelected) {\n setSelection(new Set([tile.id]));\n }\n\n // Capture pointer only when starting a drag.\n (e.currentTarget as HTMLDivElement).setPointerCapture(e.pointerId);\n\n // Group drag if 2+ tiles selected including this one.\n const effectiveSelection = tileIsSelected ? selection.value : new Set([tile.id]);\n if (effectiveSelection.size > 1) {\n const ids = Array.from(effectiveSelection);\n if (!groupDragController.start(ids)) return;\n dragStartPointerX = e.clientX;\n dragStartPointerY = e.clientY;\n groupDrag.value = {\n tileIds: ids,\n deltaX: 0,\n deltaY: 0,\n committedDcol: 0,\n committedDrow: 0,\n };\n emit('dragStart', tile.id);\n e.stopPropagation();\n return;\n }\n\n // Single tile drag.\n if (!dragController.start(tile.id)) return;\n dragStartPointerX = e.clientX;\n dragStartPointerY = e.clientY;\n drag.value = {\n tileId: tile.id,\n pickupCol: tile.col,\n pickupRow: tile.row,\n deltaX: 0,\n deltaY: 0,\n indicatorCol: tile.col,\n indicatorRow: tile.row,\n };\n emit('dragStart', tile.id);\n e.stopPropagation();\n}\n\nfunction onBackgroundPointerDown(e: PointerEvent) {\n if ((e.target as HTMLElement).closest('[data-griddle-tile]')) return;\n // Draw-to-create is gated by config (default on). When disabled, empty-space\n // pointer-downs are a no-op so the host page keeps its native scroll/pan.\n if (config.value.interactive?.drawToCreate === false) return;\n setSelection(new Set());\n\n const el = scrollEl.value;\n if (!el) return;\n const rect = el.getBoundingClientRect();\n const x = e.clientX - rect.left + el.scrollLeft;\n const y = e.clientY - rect.top + el.scrollTop;\n const col = Math.floor(x / colSize.value);\n const row = Math.floor(y / rowSize.value);\n drawState.value = { anchorCol: col, anchorRow: row, currentCol: col, currentRow: row };\n (el as HTMLDivElement).setPointerCapture(e.pointerId);\n}\n\nfunction onResizeHandleDown(e: PointerEvent, tile: Tile, c: Corner) {\n if (tile.resizable === false) return;\n (e.currentTarget as HTMLDivElement).setPointerCapture(e.pointerId);\n resize.value = {\n tileId: tile.id,\n corner: c,\n startPointerX: e.clientX,\n startPointerY: e.clientY,\n startW: tile.w,\n startH: tile.h,\n startCol: tile.col,\n startRow: tile.row,\n previewW: tile.w,\n previewH: tile.h,\n previewCol: tile.col,\n previewRow: tile.row,\n };\n emit('resizeStart', tile.id);\n e.stopPropagation();\n}\n\nfunction onPointerMove(e: PointerEvent) {\n if (drawState.value) {\n const el = scrollEl.value;\n if (el) {\n const rect = el.getBoundingClientRect();\n const x = e.clientX - rect.left + el.scrollLeft;\n const y = e.clientY - rect.top + el.scrollTop;\n const col = Math.max(0, Math.floor(x / colSize.value));\n const row = Math.max(0, Math.floor(y / rowSize.value));\n drawState.value = { ...drawState.value, currentCol: col, currentRow: row };\n }\n return;\n }\n const pd = pinDrag.value;\n const gd = groupDrag.value;\n const d = drag.value;\n const r = resize.value;\n if (pd) {\n const dx = e.clientX - pd.startPointerX;\n const dy = e.clientY - pd.startPointerY;\n const newPinPx = { x: pd.startPinPx.x + dx, y: pd.startPinPx.y + dy };\n const newPin = pixelsToPin(newPinPx, config.value);\n props.api.grid.setTilePinned(pd.tileId, newPin);\n }\n if (gd) {\n const dx = e.clientX - dragStartPointerX;\n const dy = e.clientY - dragStartPointerY;\n const dcol = Math.round(dx / colSize.value);\n const drow = Math.round(dy / rowSize.value);\n const result = groupDragController.update({ dcol, drow });\n groupDrag.value = {\n ...gd,\n deltaX: dx,\n deltaY: dy,\n committedDcol: result.indicatorDelta?.dcol ?? gd.committedDcol,\n committedDrow: result.indicatorDelta?.drow ?? gd.committedDrow,\n };\n if (result.changed) syncTiles();\n }\n if (d) {\n const dx = e.clientX - dragStartPointerX;\n const dy = e.clientY - dragStartPointerY;\n const candidateCol = d.pickupCol + Math.round(dx / colSize.value);\n const candidateRow = d.pickupRow + Math.round(dy / rowSize.value);\n const result = dragController.update({ col: candidateCol, row: candidateRow });\n drag.value = {\n ...d,\n deltaX: dx,\n deltaY: dy,\n indicatorCol: result.indicatorCell ? result.indicatorCell.col : null,\n indicatorRow: result.indicatorCell ? result.indicatorCell.row : null,\n };\n // DragController.restoreTiles() doesn't emit change events, so when the\n // candidate cell changes (especially returning to pickup), force-sync the\n // reactive tiles ref so the FLIP animation picks up displaced tile resets.\n if (result.changed) syncTiles();\n }\n if (r) {\n const dx = e.clientX - r.startPointerX;\n const dy = e.clientY - r.startPointerY;\n let dw = 0, dh = 0, dcol = 0, drow = 0;\n const stepsX = Math.round(dx / colSize.value);\n const stepsY = Math.round(dy / rowSize.value);\n if (r.corner === 'se' || r.corner === 'ne') dw = stepsX;\n if (r.corner === 'se' || r.corner === 'sw') dh = stepsY;\n if (r.corner === 'sw' || r.corner === 'nw') { dw = -stepsX; dcol = stepsX; }\n if (r.corner === 'ne' || r.corner === 'nw') { dh = -stepsY; drow = stepsY; }\n const tile = props.api.grid.getTile(r.tileId);\n const minW = tile?.minW ?? 1;\n const minH = tile?.minH ?? 1;\n const maxW = tile?.maxW ?? Infinity;\n const maxH = tile?.maxH ?? Infinity;\n const nW = Math.min(maxW, Math.max(minW, r.startW + dw));\n const nH = Math.min(maxH, Math.max(minH, r.startH + dh));\n const nC = r.startCol + dcol;\n const nR = r.startRow + drow;\n if (nW !== r.previewW || nH !== r.previewH || nC !== r.previewCol || nR !== r.previewRow) {\n resize.value = { ...r, previewW: nW, previewH: nH, previewCol: nC, previewRow: nR };\n }\n }\n}\n\nfunction syncTiles() {\n // DragController/GroupDragController may restore grid snapshots without\n // emitting change events. Force-sync the reactive tiles ref so the UI\n // reflects the grid's true state after a drag ends.\n props.api.tiles.value = props.api.grid.tiles;\n props.api.version.value++;\n}\n\nfunction onPointerUp() {\n if (drawState.value) {\n const ds = drawState.value;\n const col = Math.min(ds.anchorCol, ds.currentCol);\n const row = Math.min(ds.anchorRow, ds.currentRow);\n const w = Math.max(1, Math.abs(ds.currentCol - ds.anchorCol) + 1);\n const h = Math.max(1, Math.abs(ds.currentRow - ds.anchorRow) + 1);\n drawState.value = null;\n emit('drawCreate', { col, row, w, h });\n return;\n }\n if (pinDrag.value) {\n const tileId = pinDrag.value.tileId;\n pinDrag.value = null;\n emit('dragEnd', tileId, true);\n }\n if (groupDrag.value) {\n const tileIds = groupDrag.value.tileIds;\n const { committed } = groupDragController.end();\n groupDrag.value = null;\n syncTiles();\n const firstId = tileIds[0];\n if (firstId !== undefined) emit('dragEnd', firstId, committed);\n }\n if (drag.value) {\n const tileId = drag.value.tileId;\n const { committed } = dragController.end();\n drag.value = null;\n syncTiles();\n emit('dragEnd', tileId, committed);\n }\n const r = resize.value;\n if (r) {\n const t = props.api.grid.getTile(r.tileId);\n let committed = false;\n if (t) {\n if (r.previewCol !== t.col || r.previewRow !== t.row) {\n props.api.moveTile(r.tileId, { col: r.previewCol, row: r.previewRow });\n }\n if (r.previewW !== t.w || r.previewH !== t.h) {\n committed = props.api.resizeTile(r.tileId, { w: r.previewW, h: r.previewH });\n } else {\n committed = r.previewCol !== r.startCol || r.previewRow !== r.startRow\n || r.previewW !== r.startW || r.previewH !== r.startH;\n }\n }\n resize.value = null;\n emit('resizeEnd', r.tileId, committed);\n }\n}\n\nfunction updateViewport() {\n const el = scrollEl.value;\n if (!el) return;\n viewport.value = {\n scrollX: el.scrollLeft,\n scrollY: el.scrollTop,\n width: el.clientWidth,\n height: el.clientHeight,\n };\n}\n\nfunction onKeyDown(e: KeyboardEvent) {\n if (e.key === 'Escape') setSelection(new Set());\n}\n\nlet ro: ResizeObserver | null = null;\nonMounted(() => {\n updateViewport();\n // scrollEl is absent while loop mode delegates to GriddleLoopGrid.\n const el = scrollEl.value;\n if (el) {\n el.addEventListener('scroll', updateViewport, { passive: true });\n ro = new ResizeObserver(updateViewport);\n ro.observe(el);\n }\n window.addEventListener('pointermove', onPointerMove);\n window.addEventListener('pointerup', onPointerUp);\n window.addEventListener('pointercancel', onPointerUp);\n window.addEventListener('keydown', onKeyDown);\n});\nonBeforeUnmount(() => {\n const el = scrollEl.value;\n if (el) el.removeEventListener('scroll', updateViewport);\n ro?.disconnect();\n window.removeEventListener('pointermove', onPointerMove);\n window.removeEventListener('pointerup', onPointerUp);\n window.removeEventListener('pointercancel', onPointerUp);\n window.removeEventListener('keydown', onKeyDown);\n});\n\nconst tileNodes = new Map<string, HTMLDivElement>();\nconst prevRects = new Map<string, { x: number; y: number }>();\nfunction registerNode(id: string, el: HTMLDivElement | null) {\n if (el) tileNodes.set(id, el);\n else tileNodes.delete(id);\n}\n\nwatch(() => props.api.version.value, async () => {\n await nextTick();\n const draggerId = drag.value?.tileId ?? null;\n const gdSet = groupDragSet.value;\n for (const t of props.api.tiles.value) {\n const x = t.col * colSize.value + halfGap.value;\n const y = t.row * rowSize.value + halfGap.value;\n if (t.id === draggerId || gdSet.has(t.id)) {\n prevRects.set(t.id, { x, y });\n continue;\n }\n const p = prevRects.get(t.id);\n const node = tileNodes.get(t.id);\n if (p && node) {\n const dx = p.x - x;\n const dy = p.y - y;\n if (dx !== 0 || dy !== 0) {\n node.style.transition = 'none';\n node.style.transform = `translate(${dx}px, ${dy}px)`;\n requestAnimationFrame(() => {\n node.style.transition = 'transform 220ms cubic-bezier(.2,.7,.2,1)';\n node.style.transform = 'translate(0,0)';\n });\n }\n }\n prevRects.set(t.id, { x, y });\n }\n});\n\n// Compute layouts for all rendered tiles in one pass so resolveStickyStacking\n// can see every sticky tile and adjust them as a group. Recomputes whenever\n// rendered, config, viewport, drag, resize, or pinDrag change.\nconst tileLayouts = computed(() => {\n const out = new Map<string, TileLayout>();\n const stickyEntries: { tile: Tile; layout: TileLayout }[] = [];\n const gd = groupDrag.value;\n const gdIds = groupDragSet.value;\n for (const tile of rendered.value) {\n let layout: TileLayout;\n if (resize.value?.tileId === tile.id) {\n const w = resize.value.previewW;\n const h = resize.value.previewH;\n layout = {\n left: resize.value.previewCol * colSize.value + halfGap.value,\n top: resize.value.previewRow * rowSize.value + halfGap.value,\n width: w * config.value.unitWidth + (w - 1) * gap.value,\n height: h * config.value.unitHeight + (h - 1) * gap.value,\n zIndex: 10,\n effective: 'static',\n };\n } else if (drag.value?.tileId === tile.id) {\n const d = drag.value;\n layout = {\n left: d.pickupCol * colSize.value + halfGap.value,\n top: d.pickupRow * rowSize.value + halfGap.value,\n width: tile.w * config.value.unitWidth + (tile.w - 1) * gap.value,\n height: tile.h * config.value.unitHeight + (tile.h - 1) * gap.value,\n transform: `translate(${d.deltaX}px, ${d.deltaY}px)`,\n zIndex: 20,\n effective: 'static',\n };\n } else if (gd && gdIds.has(tile.id)) {\n const pickup = groupDragController.pickupCell(tile.id);\n const left = (pickup ? pickup.col * colSize.value : tile.col * colSize.value) + halfGap.value;\n const top = (pickup ? pickup.row * rowSize.value : tile.row * rowSize.value) + halfGap.value;\n layout = {\n left,\n top,\n width: tile.w * config.value.unitWidth + (tile.w - 1) * gap.value,\n height: tile.h * config.value.unitHeight + (tile.h - 1) * gap.value,\n transform: `translate(${gd.deltaX}px, ${gd.deltaY}px)`,\n zIndex: 20,\n effective: 'static',\n };\n } else {\n layout = computeTileLayout({\n tile,\n config: config.value,\n scrollX: viewport.value.scrollX,\n scrollY: viewport.value.scrollY,\n viewportWidth: viewport.value.width,\n viewportHeight: viewport.value.height,\n });\n if (layout.effective === 'sticky') {\n stickyEntries.push({ tile, layout });\n }\n }\n out.set(tile.id, layout);\n }\n if (stickyEntries.length > 1) resolveStickyStacking(stickyEntries);\n return out;\n});\n\nfunction tileStyle(tile: Tile) {\n const isDragging = drag.value?.tileId === tile.id;\n const isGroupDragging = groupDragSet.value.has(tile.id) && groupDrag.value !== null;\n const isPinDragging = pinDrag.value?.tileId === tile.id;\n const isResizing = resize.value?.tileId === tile.id;\n const isSelected = selection.value.has(tile.id);\n const layout = tileLayouts.value.get(tile.id) ?? {\n left: 0, top: 0, width: 0, height: 0, zIndex: 1, effective: 'static' as const,\n };\n const lifted = isDragging || isPinDragging || isGroupDragging;\n return {\n position: 'absolute' as const,\n left: layout.left + 'px',\n top: layout.top + 'px',\n width: layout.width + 'px',\n height: layout.height + 'px',\n boxSizing: 'border-box' as const,\n cursor: lifted ? 'grabbing' : 'grab',\n userSelect: 'none' as const,\n zIndex: layout.zIndex,\n opacity: lifted || isResizing ? 0.85 : 1,\n willChange: 'transform',\n transform: layout.transform ?? '',\n filter: lifted ? 'drop-shadow(0 8px 16px rgba(0,0,0,0.18))' : '',\n transition: lifted ? 'filter 120ms ease-out, opacity 120ms ease-out' : '',\n boxShadow: isSelected\n ? '0 0 0 3px rgba(59, 91, 219, 0.85), inset 0 0 0 1px rgba(59, 91, 219, 0.3)'\n : '',\n borderRadius: (config.value.tileRadius ?? 4) + 'px',\n };\n}\n\n\nconst indicatorRect = computed(() => {\n const d = drag.value;\n if (!d || d.indicatorCol === null || d.indicatorRow === null) return null;\n const t = props.api.grid.getTile(d.tileId);\n if (!t) return null;\n return {\n left: d.indicatorCol * colSize.value + halfGap.value,\n top: d.indicatorRow * rowSize.value + halfGap.value,\n width: t.w * config.value.unitWidth + (t.w - 1) * gap.value,\n height: t.h * config.value.unitHeight + (t.h - 1) * gap.value,\n };\n});\n\nconst drawGhostRect = computed(() => {\n const ds = drawState.value;\n if (!ds) return null;\n const col = Math.min(ds.anchorCol, ds.currentCol);\n const row = Math.min(ds.anchorRow, ds.currentRow);\n const w = Math.max(1, Math.abs(ds.currentCol - ds.anchorCol) + 1);\n const h = Math.max(1, Math.abs(ds.currentRow - ds.anchorRow) + 1);\n return {\n left: col * colSize.value + halfGap.value,\n top: row * rowSize.value + halfGap.value,\n width: w * config.value.unitWidth + (w - 1) * gap.value,\n height: h * config.value.unitHeight + (h - 1) * gap.value,\n label: `${w}×${h}`,\n };\n});\n\nfunction tileHandles(tile: Tile): Corner[] {\n return tile.resizeHandles ?? config.value.resizeHandles ?? ['se'];\n}\n\nfunction handleStyle(c: Corner) {\n const size = 12;\n const base = {\n position: 'absolute' as const,\n width: size + 'px',\n height: size + 'px',\n background: 'rgba(60,60,60,0.7)',\n border: '2px solid white',\n borderRadius: '3px',\n cursor: `${c}-resize`,\n touchAction: 'none' as const,\n } as Record<string, unknown>;\n if (c === 'nw') return { ...base, top: -size / 2 + 'px', left: -size / 2 + 'px' };\n if (c === 'ne') return { ...base, top: -size / 2 + 'px', right: -size / 2 + 'px' };\n if (c === 'sw') return { ...base, bottom: -size / 2 + 'px', left: -size / 2 + 'px' };\n return { ...base, bottom: -size / 2 + 'px', right: -size / 2 + 'px' };\n}\n\nconst className = computed(() => props.className ?? '');\n</script>\n","// Vue composable that wraps a Grid instance with reactive state.\n\nimport { onBeforeUnmount, reactive, ref, shallowRef } from 'vue';\nimport { Grid } from '@griddle/core';\nimport type { GridConfig, Tile, GridSnapshot } from '@griddle/core';\n\nexport interface UseGriddleInit {\n config: GridConfig;\n tiles?: Tile[];\n}\n\nexport function useGriddle(init: UseGriddleInit) {\n const grid = new Grid(init.config, init.tiles ?? []);\n\n // Reactive mirrors of tiles and config. We re-assign on changes.\n const tiles = shallowRef<Tile[]>(grid.tiles);\n const config = shallowRef<GridConfig>(grid.config);\n const version = ref(0);\n\n const off = grid.changes.on(() => {\n tiles.value = grid.tiles;\n config.value = grid.config;\n version.value++;\n });\n onBeforeUnmount(off);\n\n const api = {\n grid,\n tiles,\n config,\n version,\n moveTile: (id: string, target: { col: number; row: number }) => grid.moveTile(id, target),\n resizeTile: (id: string, size: { w: number; h: number }) => grid.resizeTile(id, size),\n addTile: (t: Tile) => grid.addTile(t),\n removeTile: (id: string) => grid.removeTile(id),\n updateConfig: (patch: Partial<GridConfig>) => grid.updateConfig(patch),\n toJSON: () => grid.toJSON(),\n loadJSON: (snap: GridSnapshot) => grid.loadJSON(snap),\n };\n return api;\n}\n\nexport type GriddleApi = ReturnType<typeof useGriddle>;\n"],"names":["DEFAULT_DRAG_IGNORE","PAN_THRESHOLD_PX","props","__props","emit","__emit","viewportEl","ref","planeEl","config","computed","loop","resolveLoop","editable","_a","gap","halfGap","colSize","rowSize","period","loopPeriod","pan","PanController","watch","l","view","lastCam","raf","resizeObserver","onWheel","e","k","frame","now","st","plane","el","cxCell","cyCell","cur","instances","bufX","bufY","loopInstances","panGesture","suppressClick","onContainerPointerDown","onTile","setSelection","ignoreSelector","onClickCapture","internalSelection","selection","next","dragController","DragController","drag","dragStartPointerX","dragStartPointerY","resize","syncTiles","isBase","inst","isGhost","onTilePointerDown","tile","onResizeHandleDown","c","baseLeft","baseTop","onPointerMove","d","dx","dy","candidate","result","r","dw","dh","dcol","drow","stepsX","stepsY","minW","minH","maxW","maxH","nW","nH","nC","nR","onPointerUp","tileId","committed","t","target","onKeyDown","onMounted","measure","onBeforeUnmount","tileNodes","prevRects","registerNode","key","nextTick","draggerId","seen","x","y","p","node","viewportStyle","bg","planeStyle","instanceStyle","isResizingInst","left","top","width","heightPx","ghost","isSelected","draggedTile","dragOverlayStyle","indicatorRect","tileHandles","handleStyle","base","className","_createElementBlock","_createElementVNode","_normalizeStyle","_Fragment","_renderList","_normalizeClass","_renderSlot","_ctx","_openBlock","loopOn","scrollEl","viewport","range","visibleRange","rendered","visibleTiles","contentSize","gridContentSize","scrollStyle","contained","style","contentStyle","groupDragSet","groupDrag","groupDragController","GroupDragController","pinDrag","drawState","metaKey","isOutOfFlow","layout","computeTileLayout","startPinPx","tileIsSelected","effectiveSelection","ids","onBackgroundPointerDown","rect","col","row","pd","gd","newPinPx","newPin","pixelsToPin","_b","candidateCol","candidateRow","ds","w","h","tileIds","firstId","updateViewport","ro","id","gdSet","tileLayouts","out","stickyEntries","gdIds","pickup","resolveStickyStacking","tileStyle","isDragging","isGroupDragging","isPinDragging","isResizing","_c","lifted","drawGhostRect","_createBlock","GriddleLoopGrid","_cache","s","cam","_withCtx","slotProps","_toDisplayString","useGriddle","init","grid","Grid","tiles","shallowRef","version","off","size","patch","snap"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@griddle/vue",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Vue 3 bindings for Griddle — a headless, zero-dependency grid/canvas engine.",
5
5
  "keywords": [
6
6
  "grid",
@@ -36,7 +36,10 @@
36
36
  "import": "./dist/index.js"
37
37
  }
38
38
  },
39
- "files": ["dist", "src"],
39
+ "files": [
40
+ "dist",
41
+ "src"
42
+ ],
40
43
  "engines": {
41
44
  "node": ">=18"
42
45
  },
@@ -147,12 +147,18 @@ const range = computed(() => visibleRange(config.value, viewport.value, 4));
147
147
  const rendered = computed(() => visibleTiles(props.api.tiles.value, range.value));
148
148
  const contentSize = computed(() => gridContentSize(config.value, props.api.tiles.value));
149
149
 
150
- const scrollStyle = computed(() => ({
151
- position: 'relative' as const,
152
- overflow: 'auto' as const,
153
- height: props.height ?? '100%',
154
- touchAction: 'none' as const,
155
- }));
150
+ const scrollStyle = computed(() => {
151
+ // 'none' scroll mode: the grid sizes to content and lets the host page own
152
+ // scrolling/panning no internal scroll box, no touch-action lock.
153
+ const contained = config.value.scroll !== 'none';
154
+ const style: Record<string, string | number> = {
155
+ position: 'relative',
156
+ overflow: contained ? 'auto' : 'visible',
157
+ height: contained ? (props.height ?? '100%') : (props.height ?? 'auto'),
158
+ };
159
+ if (contained) style.touchAction = 'none';
160
+ return style;
161
+ });
156
162
 
157
163
  const contentStyle = computed(() => {
158
164
  const showGrid = props.showGrid !== false;
@@ -338,6 +344,9 @@ function onTilePointerDown(e: PointerEvent, tile: Tile) {
338
344
 
339
345
  function onBackgroundPointerDown(e: PointerEvent) {
340
346
  if ((e.target as HTMLElement).closest('[data-griddle-tile]')) return;
347
+ // Draw-to-create is gated by config (default on). When disabled, empty-space
348
+ // pointer-downs are a no-op so the host page keeps its native scroll/pan.
349
+ if (config.value.interactive?.drawToCreate === false) return;
341
350
  setSelection(new Set());
342
351
 
343
352
  const el = scrollEl.value;