@grafloria/element 0.4.34 → 0.4.36

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@grafloria/element",
3
- "version": "0.4.34",
3
+ "version": "0.4.36",
4
4
  "type": "module",
5
5
  "main": "./src/index.js",
6
6
  "types": "./src/index.d.ts",
@@ -626,6 +626,9 @@ export interface DashboardHandleContext {
626
626
  active: string;
627
627
  /** MUTABLE — set by the caller's finalize once the render API exists. */
628
628
  apiRef: DashboardApiRef | null;
629
+ /** MUTABLE — the canvas element, set with apiRef; parking a page or a view
630
+ * reaches the html layer through it (see `teleport`). */
631
+ container: HTMLElement | null;
629
632
  /** The consumer's layout hook, if any (dashboard() passes its option). */
630
633
  onLayoutChange?: (viewId: string, widgets: DashboardWidgetSpec[]) => void;
631
634
  /**
@@ -184,6 +184,29 @@ class SetWidgetLockCommand extends Command {
184
184
  const HISTORY_EVENTS = ['command:executed', 'command:undone', 'command:redone'];
185
185
  const DEFAULTS = { columns: 12, gap: 8, rowHeight: 130, width: 1180, height: 660 };
186
186
  const OFFSCREEN_X = -20000;
187
+ /**
188
+ * Parking is a TELEPORT, never a glide. `.axdb-glide` on the html layer eases
189
+ * every left/top write while a gesture runs and for 400 ms past its drop; a
190
+ * page or a view coming back from OFFSCREEN_X under it SLID in from 20,000 px
191
+ * away over 280 ms (0.4.36). The class comes off for the writes, the styles
192
+ * are flushed so the landing becomes the before-change state, and the class
193
+ * goes back to whichever gesture still holds it.
194
+ */
195
+ const teleport = (container, fn) => {
196
+ const layer = container === null || container === void 0 ? void 0 : container.querySelector('.grafloria-html-layer');
197
+ const held = (layer === null || layer === void 0 ? void 0 : layer.classList.contains('axdb-glide')) === true;
198
+ if (held)
199
+ layer.classList.remove('axdb-glide');
200
+ try {
201
+ fn();
202
+ }
203
+ finally {
204
+ if (held && layer) {
205
+ void layer.offsetWidth; // flush: the new positions are the before-change style now
206
+ layer.classList.add('axdb-glide');
207
+ }
208
+ }
209
+ };
187
210
  let autoId = 0;
188
211
  /** The node a widget spec becomes — one place, so addWidget() and the initial
189
212
  * spec build can never drift apart on metadata. */
@@ -1100,6 +1123,7 @@ export function createDashboardHandle(ctx) {
1100
1123
  },
1101
1124
  joinTargets: [...ctx.layoutOf.keys()].filter((id) => { var _a, _b; return id !== containerId && id !== pageId && ((_a = ctx.layoutOf.get(id)) !== null && _a !== void 0 ? _a : (_b = specById.get(id)) === null || _b === void 0 ? void 0 : _b.layout) === 'tabs' && !!model.getGroup(id) && !insidePage(id); }),
1102
1125
  stripHeight: (targetId) => tabStripReserve(ctx.tabsOf.get(targetId), Math.max(1, liveCount(targetId))),
1126
+ ownBoards: [pageId, ...[...ctx.boardGroups.keys()].filter((id) => insidePage(id))],
1103
1127
  stripIndex: (targetId, cx, cy) => {
1104
1128
  const strip = ctx.tabStrips.get(targetId);
1105
1129
  if (!strip)
@@ -1304,18 +1328,20 @@ export function createDashboardHandle(ctx) {
1304
1328
  return ctx.active;
1305
1329
  },
1306
1330
  showView(id) {
1307
- var _a, _b, _c;
1308
1331
  if (!groups.has(id))
1309
1332
  return;
1310
1333
  ctx.active = id;
1311
- for (const [vid, g] of groups) {
1312
- const x = vid === id ? 0 : OFFSCREEN_X;
1313
- const s = (_a = g.size) !== null && _a !== void 0 ? _a : { width: ctx.boardW, height: ctx.boardH };
1314
- if (g.position.x !== x)
1315
- g.setFrame({ x, y: 0, width: s.width, height: s.height });
1316
- }
1317
- (_b = binders.get(id)) === null || _b === void 0 ? void 0 : _b.sync();
1318
- (_c = ctx.apiRef) === null || _c === void 0 ? void 0 : _c.renderNow();
1334
+ teleport(ctx.container, () => {
1335
+ var _a, _b, _c;
1336
+ for (const [vid, g] of groups) {
1337
+ const x = vid === id ? 0 : OFFSCREEN_X;
1338
+ const s = (_a = g.size) !== null && _a !== void 0 ? _a : { width: ctx.boardW, height: ctx.boardH };
1339
+ if (g.position.x !== x)
1340
+ g.setFrame({ x, y: 0, width: s.width, height: s.height });
1341
+ }
1342
+ (_b = binders.get(id)) === null || _b === void 0 ? void 0 : _b.sync();
1343
+ (_c = ctx.apiRef) === null || _c === void 0 ? void 0 : _c.renderNow();
1344
+ });
1319
1345
  frameView(groups.get(id));
1320
1346
  },
1321
1347
  widget(id) {
@@ -1410,7 +1436,7 @@ export function createDashboardHandle(ctx) {
1410
1436
  },
1411
1437
  getCaption: (id) => { var _a; return (_a = specById.get(id)) === null || _a === void 0 ? void 0 : _a.caption; },
1412
1438
  activateTab(containerId, pageId) {
1413
- var _a, _b, _c, _d, _e, _f, _g;
1439
+ var _a, _b, _c, _d, _e;
1414
1440
  const cg = ctx.boardGroups.get(containerId);
1415
1441
  const w = specById.get(containerId);
1416
1442
  if (!cg || !w || ((_a = ctx.layoutOf.get(containerId)) !== null && _a !== void 0 ? _a : w.layout) !== 'tabs')
@@ -1423,9 +1449,12 @@ export function createDashboardHandle(ctx) {
1423
1449
  w.active = pageId;
1424
1450
  const cw = (_c = cg.getMetadata('containerWidget')) !== null && _c !== void 0 ? _c : {};
1425
1451
  cg.setMetadata('containerWidget', Object.assign(Object.assign({}, cw), { active: pageId }));
1426
- (_d = ctx.syncTabs) === null || _d === void 0 ? void 0 : _d.call(ctx, containerId);
1427
- (_e = ctx.apiRef) === null || _e === void 0 ? void 0 : _e.renderNow();
1428
- (_f = ctx.onTabChange) === null || _f === void 0 ? void 0 : _f.call(ctx, containerId, pageId, (_g = ctx.viewOfBoard.get(containerId)) !== null && _g !== void 0 ? _g : ctx.active);
1452
+ teleport(ctx.container, () => {
1453
+ var _a, _b;
1454
+ (_a = ctx.syncTabs) === null || _a === void 0 ? void 0 : _a.call(ctx, containerId);
1455
+ (_b = ctx.apiRef) === null || _b === void 0 ? void 0 : _b.renderNow();
1456
+ });
1457
+ (_d = ctx.onTabChange) === null || _d === void 0 ? void 0 : _d.call(ctx, containerId, pageId, (_e = ctx.viewOfBoard.get(containerId)) !== null && _e !== void 0 ? _e : ctx.active);
1429
1458
  reportChanged();
1430
1459
  return true;
1431
1460
  },
@@ -1921,6 +1950,7 @@ export function dashboard(options) {
1921
1950
  optionsBase: options,
1922
1951
  active: (_p = (_o = views[0]) === null || _o === void 0 ? void 0 : _o.id) !== null && _p !== void 0 ? _p : 'main',
1923
1952
  apiRef: null,
1953
+ container: null,
1924
1954
  onLayoutChange: options.onLayoutChange,
1925
1955
  };
1926
1956
  const { binders, groups } = ctx;
@@ -1935,24 +1965,25 @@ export function dashboard(options) {
1935
1965
  }, get handle() {
1936
1966
  return handle;
1937
1967
  }, finalize: (api) => {
1938
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
1968
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
1939
1969
  const a = api;
1940
1970
  if (!a)
1941
1971
  return;
1942
1972
  ctx.apiRef = a;
1973
+ ctx.container = (_a = a.container) !== null && _a !== void 0 ? _a : null;
1943
1974
  const model = a.getModel();
1944
1975
  // FLUID: the board starts at the container's box when it can be measured
1945
1976
  // (the binder keeps it there); the authored defaults only fill in for a
1946
1977
  // container with no size yet.
1947
1978
  const box = mode === 'fluid'
1948
- ? { w: ((_a = a.container) === null || _a === void 0 ? void 0 : _a.clientWidth) || 0, h: ((_b = a.container) === null || _b === void 0 ? void 0 : _b.clientHeight) || 0 }
1979
+ ? { w: ((_b = a.container) === null || _b === void 0 ? void 0 : _b.clientWidth) || 0, h: ((_c = a.container) === null || _c === void 0 ? void 0 : _c.clientHeight) || 0 }
1949
1980
  : { w: 0, h: 0 };
1950
1981
  const viewW = (v) => { var _a; return (mode === 'fluid' && box.w > 0 ? box.w : (_a = v.width) !== null && _a !== void 0 ? _a : boardW); };
1951
1982
  const viewH = (v) => { var _a; return (mode === 'fluid' && box.h > 0 ? box.h : (_a = v.height) !== null && _a !== void 0 ? _a : boardH); };
1952
1983
  for (const v of views) {
1953
1984
  // One board per view; the group is a pure LAYOUT CONTAINER, so its
1954
1985
  // chrome is suppressed (frameChrome) exactly as a dashboard needs.
1955
- const g = new GroupModel({ id: v.id, name: (_c = v.name) !== null && _c !== void 0 ? _c : v.id });
1986
+ const g = new GroupModel({ id: v.id, name: (_d = v.name) !== null && _d !== void 0 ? _d : v.id });
1956
1987
  model.addGroup(g);
1957
1988
  g.setMetadata('frameChrome', 'none');
1958
1989
  // THE BOARD'S GEOMETRY, PERSISTED. Cells alone do not describe a board:
@@ -1962,28 +1993,28 @@ export function dashboard(options) {
1962
1993
  // reload would be a picture of a dashboard rather than a dashboard.
1963
1994
  // Serializable values only: the binder's callbacks belong to the app.
1964
1995
  g.setMetadata('dashboardBoard', {
1965
- columns: (_d = v.columns) !== null && _d !== void 0 ? _d : columns,
1996
+ columns: (_e = v.columns) !== null && _e !== void 0 ? _e : columns,
1966
1997
  gap,
1967
1998
  padding: gap,
1968
1999
  sizing,
1969
2000
  baseRowHeight: rowHeight,
1970
2001
  designHeight: viewH(v),
1971
- float: (_e = options.float) !== null && _e !== void 0 ? _e : false,
1972
- rtl: (_f = options.rtl) !== null && _f !== void 0 ? _f : false,
2002
+ float: (_f = options.float) !== null && _f !== void 0 ? _f : false,
2003
+ rtl: (_g = options.rtl) !== null && _g !== void 0 ? _g : false,
1973
2004
  fluid: mode === 'fluid',
1974
2005
  overflow,
1975
- static: (_g = options.static) !== null && _g !== void 0 ? _g : false,
1976
- dragHandle: (_h = options.dragHandle) !== null && _h !== void 0 ? _h : false,
1977
- layout: (_j = ctx.layoutOf.get(v.id)) !== null && _j !== void 0 ? _j : layout,
2006
+ static: (_h = options.static) !== null && _h !== void 0 ? _h : false,
2007
+ dragHandle: (_j = options.dragHandle) !== null && _j !== void 0 ? _j : false,
2008
+ layout: (_k = ctx.layoutOf.get(v.id)) !== null && _k !== void 0 ? _k : layout,
1978
2009
  });
1979
- if (((_k = ctx.layoutOf.get(v.id)) !== null && _k !== void 0 ? _k : layout) === 'split' && v.tree !== undefined)
2010
+ if (((_l = ctx.layoutOf.get(v.id)) !== null && _l !== void 0 ? _l : layout) === 'split' && v.tree !== undefined)
1980
2011
  g.setMetadata(SPLIT_TREE_KEY, v.tree);
1981
2012
  g.size = { width: viewW(v), height: viewH(v), depth: 0 };
1982
2013
  g.position = { x: v.id === ctx.active ? 0 : OFFSCREEN_X, y: 0 };
1983
2014
  groups.set(v.id, g);
1984
2015
  ctx.boardGroups.set(v.id, g);
1985
2016
  mountBoard(v.id, v.id, v.widgets, g);
1986
- binders.set(v.id, bindView(v, g, (_l = ctx.layoutOf.get(v.id)) !== null && _l !== void 0 ? _l : layout));
2017
+ binders.set(v.id, bindView(v, g, (_m = ctx.layoutOf.get(v.id)) !== null && _m !== void 0 ? _m : layout));
1987
2018
  }
1988
2019
  // LIVE LAYOUT SWITCH (setLayout): keep the picture, swap the binder.
1989
2020
  // Either way the outgoing binder's cells are written where the grid
@@ -2099,8 +2130,8 @@ export function dashboard(options) {
2099
2130
  // runs. That cost me a debugging round: `ctx.syncTabs` stayed undefined
2100
2131
  // and every tab switch silently did nothing.)
2101
2132
  ctx.onTabChange = options.onTabChange;
2102
- attachTabsRuntime(ctx, model, (_m = a.container) !== null && _m !== void 0 ? _m : null, handle);
2103
- (_o = ctx.attachHistory) === null || _o === void 0 ? void 0 : _o.call(ctx);
2133
+ attachTabsRuntime(ctx, model, (_o = a.container) !== null && _o !== void 0 ? _o : null, handle);
2134
+ (_p = ctx.attachHistory) === null || _p === void 0 ? void 0 : _p.call(ctx);
2104
2135
  return;
2105
2136
  /**
2106
2137
  * Mount one board's widgets into its group — and recurse for CONTAINERS.
@@ -569,6 +569,8 @@ export interface TearOutPlan {
569
569
  stripIndex(targetId: string, clientX: number, clientY: number): number | null;
570
570
  /** The strip's height on `targetId`, px — the band above its body. */
571
571
  stripHeight(targetId: string): number;
572
+ /** The page itself and every board inside it — never a board the page can land on. */
573
+ ownBoards: string[];
572
574
  /** The commands that REORDER the page to `index` along its own strip. Empty when nothing changes. */
573
575
  reorder(index: number): Command[];
574
576
  /**
@@ -661,6 +663,10 @@ interface AdoptedLeg {
661
663
  }): boolean;
662
664
  /** Every other tile's cell before the ghost entered — the layout a row insert translates. */
663
665
  baseline(): Map<string, CellRect>;
666
+ /** Where the tile sits right now, or null while it is off the board. */
667
+ cell(): CellRect | null;
668
+ /** That cell in world space, by the adopting board's own geometry. */
669
+ rect(): WorldRect | null;
664
670
  /** Undo the adoption: target board back to its pre-entry layout. */
665
671
  abort(): void;
666
672
  /**