@grafloria/element 0.4.24 → 0.4.26

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.24",
3
+ "version": "0.4.26",
4
4
  "type": "module",
5
5
  "main": "./src/index.js",
6
6
  "types": "./src/index.d.ts",
@@ -1706,6 +1706,19 @@ export function bindDashboardGrid(api, group, options = {}) {
1706
1706
  // ratchet's second disguise (grow committed; a fresh shrink gesture could
1707
1707
  // never pull low enough to ask the parent for a row back).
1708
1708
  let h = bottom - top;
1709
+ /**
1710
+ * Did the escalation below move this tile AS PART OF THE STRIP? A
1711
+ * full-height tile shares its row count with every other full-height tile
1712
+ * in the section, so once the strip grew, this tile's height is the
1713
+ * strip's — not whatever its own pixels re-quantise to. Without this the
1714
+ * gesture undid itself for its own tile and left the NEIGHBOUR grown:
1715
+ * drag Churn's bottom 70 px and ORDERS became two rows while Churn stayed
1716
+ * one (reported from the fluid demo). The cause is the row height
1717
+ * changing mid-gesture: 86 px rows make +70 read as 2 rows, and the
1718
+ * moment the section grows, rows become 108 px and the same pixels read
1719
+ * as 1 again. See the sibling rule for the un-pulled axis below.
1720
+ */
1721
+ let stripFollow = false;
1709
1722
  // NESTED HEIGHT ESCALATION (live report: "i cant increase height"). A
1710
1723
  // bounded strip cannot grow a tile taller than itself — so pulling
1711
1724
  // clearly past its bottom GROWS THE STRIP: the slab gains a row in the
@@ -1720,10 +1733,13 @@ export function bindDashboardGrid(api, group, options = {}) {
1720
1733
  // commit and for Escape.
1721
1734
  // NESTED ESCALATION — a section is a board one level down, and a pull
1722
1735
  // inside it can need rows the section does not hold. Two shapes:
1723
- // · a tile spanning the section's FULL HEIGHT (every tile of a one-row
1724
- // KPI strip): the section gains a row and every full-height tile grows
1725
- // with it a row of tiles pulled taller stays a row (s21) — and gives
1726
- // it back when pulled up, never below the design;
1736
+ // · a tile spanning the section's FULL HEIGHT (any tile of a one-row KPI
1737
+ // strip): the section gains a row and THE DRAGGED TILE takes it; its
1738
+ // siblings keep their own cells, and the row goes back when the tile is
1739
+ // pulled up again, never below the design. (Until 0.4.26 every
1740
+ // full-height tile grew together — "a row stays a row" — but that
1741
+ // resized the widget NEXT to the one under the pointer, which is not
1742
+ // what a grid resize means.)
1727
1743
  // · a PARTIAL tile (a one-row control in a 14-row panel): it pushes what
1728
1744
  // is below it; a row the pushed layout needs and the section does not
1729
1745
  // hold is asked of the board, one per pointer step, and rows the
@@ -1764,25 +1780,49 @@ export function bindDashboardGrid(api, group, options = {}) {
1764
1780
  // The SAME rounding the resize path quantises with, or the tile shrinks
1765
1781
  // through that path first and the section never gets its row back.
1766
1782
  const wantRows = Math.max(1, Math.round((h + gap) / rowPx));
1767
- const wantsMore = wantRows > pulled.h;
1768
- const wantsLess = wantRows < pulled.h;
1769
1783
  const fullHeight = pulled.y === 0 && pulled.h >= inner;
1770
- const fullOnes = engine.getItems().filter((i) => i.y === 0 && i.h >= inner).map((i) => i.id);
1771
- const resizeAll = (ids, rowsTo) => {
1772
- for (const id of ids) {
1773
- const it = engine.getItem(id);
1774
- if (it)
1775
- engine.resizeCheck(id, it.w, rowsTo);
1776
- }
1777
- };
1784
+ // For the WHOLE gesture, not just the move that escalated: a strip
1785
+ // tile's height is its cells. Set on every move so the tile cannot
1786
+ // re-quantise back a row on the moves in between.
1787
+ stripFollow = fullHeight;
1788
+ /**
1789
+ * A STRIP IS MEASURED FROM THE PRESS, NOT FROM ITSELF. Growing the
1790
+ * strip changes the row height, so quantising the live pixels against
1791
+ * the LIVE row height feeds the decision back into its own input: at
1792
+ * 86 px rows a +80 px pull reads as 2 rows, the section grows, rows
1793
+ * become 108 px, the same pointer now reads as 1 row, the section
1794
+ * shrinks — and the gesture oscillates and lands wherever the last
1795
+ * move left it (measured: +60/+70/+90 grew, +80 did nothing).
1796
+ * Counting rows from the row height AT PRESS is monotonic in the
1797
+ * pointer, so the strip cannot fight itself.
1798
+ */
1799
+ const startCell = g.startCells.get(g.id);
1800
+ const startRowPx = startCell && startCell.h > 0 ? (g.startSize.height + gap) / startCell.h : rowPx;
1801
+ const stripRows = startCell
1802
+ ? Math.max(1, startCell.h + Math.round((h - g.startSize.height) / startRowPx))
1803
+ : wantRows;
1804
+ const effWant = fullHeight ? stripRows : wantRows;
1805
+ const wantsMore = effWant > pulled.h;
1806
+ const wantsLess = effWant < pulled.h;
1778
1807
  let touched = false;
1779
1808
  if (wantsMore) {
1780
- if (fullHeight) {
1809
+ if (fullHeight && !E.s) {
1810
+ // A tile that already starts at row 0 has nothing above it, so a
1811
+ // TOP-edge pull has nowhere to go: refuse it rather than growing
1812
+ // the tile downwards, away from the edge under the pointer. Same
1813
+ // rule the partial path follows (0.4.20).
1814
+ }
1815
+ else if (fullHeight) {
1781
1816
  const res = parent.resizeMemberBy(group.id, +1);
1782
1817
  if (res.changed) {
1783
1818
  record(res, +1);
1784
1819
  setInnerRows(inner + 1);
1785
- resizeAll(fullOnes, inner + 1);
1820
+ // ONLY THE TILE UNDER THE POINTER CHANGES. The section grows to
1821
+ // hold it and its siblings keep their own cells — a grid resize
1822
+ // adjusts what you grabbed, nothing else. (This board used to
1823
+ // grow EVERY full-height tile together, so pulling one KPI of a
1824
+ // strip silently resized its neighbour too.)
1825
+ engine.resizeCheck(g.id, pulled.w, pulled.h + 1);
1786
1826
  touched = true;
1787
1827
  }
1788
1828
  }
@@ -1806,14 +1846,21 @@ export function bindDashboardGrid(api, group, options = {}) {
1806
1846
  else if (wantsLess) {
1807
1847
  if (fullHeight) {
1808
1848
  if (slabRows > designRows && inner > 1) {
1809
- resizeAll(fullOnes, inner - 1);
1810
- const res = parent.resizeMemberBy(group.id, -1);
1811
- if (res.changed) {
1849
+ // Shrink the dragged tile, then hand back only the rows the
1850
+ // section no longer needs — a sibling still using them keeps
1851
+ // them (the extent floor below).
1852
+ engine.resizeCheck(g.id, pulled.w, Math.max(1, effWant));
1853
+ const floor = Math.max(designRows, extentOf(engine.getItems()));
1854
+ let slab = slabRows;
1855
+ let bound = inner;
1856
+ while (slab > floor) {
1857
+ const res = parent.resizeMemberBy(group.id, -1);
1858
+ if (!res.changed)
1859
+ break;
1812
1860
  record(res, -1);
1813
- setInnerRows(inner - 1);
1814
- }
1815
- else {
1816
- resizeAll(fullOnes, inner);
1861
+ slab -= 1;
1862
+ bound -= 1;
1863
+ setInnerRows(bound);
1817
1864
  }
1818
1865
  touched = true;
1819
1866
  }
@@ -1871,7 +1918,11 @@ export function bindDashboardGrid(api, group, options = {}) {
1871
1918
  // projection of its cell span instead of the start-of-gesture pixels.
1872
1919
  if (!pullsX)
1873
1920
  w = itemNow.w * (cuNow + gap) - gap;
1874
- if (!pullsY)
1921
+ // …and a tile the STRIP just moved follows its cells on the pulled axis
1922
+ // too: the strip is one row of tiles, so the dragged tile keeps the row
1923
+ // count its peers were given rather than re-quantising against the row
1924
+ // height the escalation itself just changed.
1925
+ if (!pullsY || stripFollow)
1875
1926
  h = itemNow.h * (rhNow + gap) - gap;
1876
1927
  }
1877
1928
  // Anchor: the pulled edges follow w/h, the opposite ones stay put — on