@selimssevgi/cube-design-angular 0.4.0 → 0.5.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.
package/CHANGELOG.md CHANGED
@@ -4,6 +4,17 @@
4
4
 
5
5
  nothing yet.
6
6
 
7
+ ## 0.5.1 (4 november 2026: an empty piece has room)
8
+
9
+ - **`least` on `<cube-square>`** and the pure `squareLeast(side, { cell, min, max })` (`SQUARE_LEAST_CELL`, 200): a dashed square (something can be added) stands at least as many across as keep a place near 200 px, 3 × 3 on a phone, 4 × 4 in a desktop column, 5 × 5 at the widest; past that the tiles grow it as before. an empty piece is its own box first, then dashed places, never one place as wide as the screen (selim's pick, way c of `studies/empty-piece-places.md`, 4 november 2026: "this single add looks ridiculous"). `squareLayout` takes `least` too. on by default (`'room'`) for every dashed square; `[least]="0"` keeps the smallest. a square that is not dashed never changes.
10
+
11
+ ## 0.5.0 (4 november 2026: released so mosaic's home grouped my way brings things in and keeps my own order)
12
+
13
+ - **bring things in**, `bringOf(source, into, { at, pieces })` and `bringLevel` (`CubeBring`, `BringOptions`, `BringWords`): where turned round (the study `studies/bringing-things-in.md`, way b, picked by selim on 4 november 2026). where lists places for one piece; bring lists pieces for one place: what stands in `at` (the top by default), each ticked when it is in already, the place itself and a piece holding it pale, a › on a piece with something to bring inside it, what a tap asks (`stand`, `take-out`) and why it would be refused, over the same `WhereSource`. `pieces` lists the app's own (lately) instead. from mosaic's grouping prototype (`bring-things-in.html`).
14
+ - **my own order**, `moveBefore(order, piece, before, { fixedFirst })`, `orderOf` and `orderLevel` (`CubeOrderPlace`, `OrderWords`, `OrderRefusal`, `MINE_SORT`): the person orders a place's pieces by hand; the order is the place's, never the piece's, and a fixed first piece the app names (mosaic's apps at its top) stays first. the level is the place's pieces as they come, the held one ticked, a tap puts it before another, **last** at the end.
15
+ - **add as a level**, `addLevel(ways)` (`AddWay`): the app's ways to add to a place as context tiles, the plus last (selim: bring things in first, then the plus with a short line). what add holds is each app's, and may differ from place to place.
16
+ - `ContextPartKey` and `CONTEXT_PART_ORDER` know `bring` (after change) and `order` (after sort), drawn as move and sort (`PART_ICONS`). an app that uses neither sees no change.
17
+
7
18
  ## 0.4.0 (4 november 2026: released so mosaic's home grouped my way draws its context cube with `<cube-context>`)
8
19
 
9
20
  - `ContextTile.attrs`: the app's own `data-*` attributes on a tile's cell (`cc-cell`, which holds the tile and its ›), so a test or a use-case runner finds the context cube's tiles by the app's own handles (`data-name`, `data-kind`, `data-ticked`). only `data-*` names are set, a null leaves one out, and one a later tile no longer gives is taken off. found moving mosaic's home grouped my way onto `<cube-context>` (4 november 2026): it drew its context cube with its own square only to carry the runner's handles, and so it had no view (selim: "whenever there is a solution in the library, we should make use of it").
@@ -1417,8 +1417,10 @@ i0.ɵɵngDeclareClassMetadata({
1417
1417
  const CONTEXT_PART_ORDER = [
1418
1418
  "names",
1419
1419
  "change",
1420
+ "bring",
1420
1421
  "view",
1421
1422
  "sort",
1423
+ "order",
1422
1424
  "move",
1423
1425
  "where",
1424
1426
  "whose",
@@ -1432,7 +1434,9 @@ const CONTEXT_CUBE_SOURCE = new InjectionToken("CONTEXT_CUBE_SOURCE");
1432
1434
  const CONTEXT_CUBE_WORDS = new InjectionToken("CONTEXT_CUBE_WORDS");
1433
1435
  const PART_ICONS = {
1434
1436
  hide: "shown",
1435
- where: "place"
1437
+ where: "place",
1438
+ bring: "move",
1439
+ order: "sort"
1436
1440
  };
1437
1441
  function partsLevel(parts, words, now = {}) {
1438
1442
  return orderParts(parts).map((p) => ({
@@ -1505,6 +1509,36 @@ function sortItems(items, by, dir, text = "natural") {
1505
1509
  return sign * compare(a.value, b.value) || a.at - b.at;
1506
1510
  }).map((x) => x.item);
1507
1511
  }
1512
+ const MINE_SORT = "mine";
1513
+ function moveBefore(order, piece, before, opts = {}) {
1514
+ const fixed = opts.fixedFirst ?? null;
1515
+ if (fixed !== null && (piece === fixed || before === fixed)) return {
1516
+ order: [...order],
1517
+ refused: "fixed-first"
1518
+ };
1519
+ if (!order.includes(piece) || before === piece) return {
1520
+ order: [...order],
1521
+ refused: null
1522
+ };
1523
+ const rest = order.filter((p) => p !== piece);
1524
+ const at = before === null ? -1 : rest.indexOf(before);
1525
+ rest.splice(at < 0 ? rest.length : at, 0, piece);
1526
+ return {
1527
+ order: rest,
1528
+ refused: null
1529
+ };
1530
+ }
1531
+ function orderOf(order, held, opts = {}) {
1532
+ const fixed = opts.fixedFirst ?? null;
1533
+ return order.map((key, at) => ({
1534
+ key,
1535
+ at,
1536
+ held: key === held,
1537
+ fixed: key === fixed,
1538
+ tap: key === held ? null : "before",
1539
+ refused: key !== held && key === fixed ? "fixed-first" : null
1540
+ }));
1541
+ }
1508
1542
  function namesLevel(names, words, opts = {}) {
1509
1543
  const tiles = [...names.filter((n) => n.current), ...names.filter((n) => !n.current).reverse()].map((n, i) => ({
1510
1544
  key: `name:${i}:${n.name}`,
@@ -1582,6 +1616,36 @@ function sortDirectionsLevel(option, now, words) {
1582
1616
  data: dir
1583
1617
  }));
1584
1618
  }
1619
+ function orderLevel(places, words) {
1620
+ const tiles = places.map((p) => ({
1621
+ key: "order:" + p.key,
1622
+ title: words.title(p),
1623
+ line: words.line?.(p) ?? null,
1624
+ icon: "sort",
1625
+ inUse: p.held,
1626
+ pale: p.fixed,
1627
+ data: p
1628
+ }));
1629
+ if (places.length && !places[places.length - 1].held) tiles.push({
1630
+ key: "order:last",
1631
+ title: words.last.title,
1632
+ line: words.last.line ?? null,
1633
+ icon: "down",
1634
+ data: null
1635
+ });
1636
+ return tiles;
1637
+ }
1638
+ function addLevel(ways) {
1639
+ const tile = (w) => ({
1640
+ key: "add:" + w.key,
1641
+ title: w.title,
1642
+ line: w.line ?? null,
1643
+ icon: w.icon ?? (w.adds ? "plus" : "move"),
1644
+ adds: !!w.adds,
1645
+ data: w
1646
+ });
1647
+ return [...ways.filter((w) => !w.adds), ...ways.filter((w) => w.adds)].map(tile);
1648
+ }
1585
1649
  function insideOf(source, piece) {
1586
1650
  const seen = /* @__PURE__ */ new Set();
1587
1651
  const walk = [...source.partsOf(piece)];
@@ -1698,6 +1762,66 @@ function whereLevel(places, words = {}, opts = {}) {
1698
1762
  data: p
1699
1763
  }));
1700
1764
  }
1765
+ function bringOf(source, into, opts = {}) {
1766
+ const at = opts.at ?? source.top;
1767
+ const hidden = (id) => !!source.hidden?.(id);
1768
+ const shown = (place) => source.partsOf(place).filter((p) => !hidden(p));
1769
+ const inInto = (p) => source.placesOf(p).includes(into);
1770
+ const can = (p) => p !== into && !inInto(p) && !refusalOf(source, p, into);
1771
+ const reached = /* @__PURE__ */ new Map();
1772
+ const reaches = (q, trail = /* @__PURE__ */ new Set()) => {
1773
+ if (reached.has(q)) return reached.get(q);
1774
+ if (trail.has(q)) return false;
1775
+ trail.add(q);
1776
+ const r = shown(q).some((p) => can(p) || inInto(p) || reaches(p, trail));
1777
+ reached.set(q, r);
1778
+ return r;
1779
+ };
1780
+ return (opts.pieces ? opts.pieces.filter((p) => !hidden(p)) : shown(at)).filter((p) => p !== at || !!opts.pieces).map((p) => {
1781
+ const places = source.placesOf(p);
1782
+ const others = places.filter((q) => q !== into);
1783
+ const deeper = !opts.pieces && shown(p).length > 0 && reaches(p);
1784
+ if (p === into) return {
1785
+ key: p,
1786
+ title: source.nameOf(p),
1787
+ in: false,
1788
+ given: false,
1789
+ into: true,
1790
+ holdsInto: false,
1791
+ tap: null,
1792
+ refused: "inside-itself",
1793
+ places: others,
1794
+ deeper: false
1795
+ };
1796
+ const stands = places.includes(into);
1797
+ const given = (source.givenPlaceOf?.(p) ?? null) === into;
1798
+ return {
1799
+ key: p,
1800
+ title: source.nameOf(p),
1801
+ in: stands,
1802
+ given: stands && given,
1803
+ into: false,
1804
+ holdsInto: !stands && wouldLoop(source, p, into),
1805
+ tap: stands ? "take-out" : "stand",
1806
+ refused: stands ? given ? "given-place" : places.length === 1 ? "last-place" : null : refusalOf(source, p, into),
1807
+ places: others,
1808
+ deeper
1809
+ };
1810
+ });
1811
+ }
1812
+ function bringLevel(pieces, words = {}, opts = {}) {
1813
+ const pathOf = opts.pathOf ?? ((p) => ["bring", p.key]);
1814
+ return pieces.map((p) => ({
1815
+ key: "bring:" + p.key,
1816
+ title: words.title?.(p) ?? p.title,
1817
+ line: words.line?.(p) ?? null,
1818
+ icon: "place",
1819
+ inUse: p.in,
1820
+ pale: p.tap === null || !p.in && p.refused !== null,
1821
+ zoom: p.deeper ? pathOf(p) : null,
1822
+ data: p
1823
+ }));
1824
+ }
1701
1825
  const TURNING_SIDES = 4;
1702
1826
  function turningRows(pieces, own, cols = 3, rows = cols) {
1703
1827
  const across = Math.max(1, Math.floor(cols));
@@ -1729,11 +1853,18 @@ function squareGap(n) {
1729
1853
  }
1730
1854
  const SQUARE_MAX_SIDE = 880;
1731
1855
  const SQUARE_LIST_ROW = 76;
1856
+ const SQUARE_LEAST_CELL = 200;
1857
+ function squareLeast(side, opts = {}) {
1858
+ const { cell = 200, min = 3, max = 5 } = opts;
1859
+ if (!(side > 0)) return min;
1860
+ return Math.min(max, Math.max(min, Math.ceil(side / cell)));
1861
+ }
1732
1862
  function squareLayout(view, count, room, opts = {}) {
1733
1863
  const n = Math.max(0, count);
1734
1864
  const grid = gridFor(view, n);
1735
- const cols = grid.cols;
1736
- const rows = view === "square" ? grid.rows : Math.max(1, Math.ceil(n / cols));
1865
+ const least = view === "square" ? Math.max(0, Math.floor(opts.least ?? 0)) : 0;
1866
+ const cols = Math.max(grid.cols, least);
1867
+ const rows = view === "square" ? Math.max(grid.rows, least) : Math.max(1, Math.ceil(n / cols));
1737
1868
  const width = Math.max(0, Math.min(view === "square" ? Math.min(room.width, room.tall) : room.width, opts.maxSide ?? 880));
1738
1869
  const list = view === "one";
1739
1870
  const gap = list ? 8 : squareGap(Math.max(cols, Math.min(rows, 5)));
@@ -1840,6 +1971,7 @@ var CubeSquare = class CubeSquare {
1840
1971
  maxSide = input(880, ...ngDevMode ? [{ debugName: "maxSide" }] : /* istanbul ignore next */ []);
1841
1972
  listRow = input(76, ...ngDevMode ? [{ debugName: "listRow" }] : /* istanbul ignore next */ []);
1842
1973
  dashed = input(false, ...ngDevMode ? [{ debugName: "dashed" }] : /* istanbul ignore next */ []);
1974
+ least = input("room", ...ngDevMode ? [{ debugName: "least" }] : /* istanbul ignore next */ []);
1843
1975
  keyOf = input((_, i) => i, ...ngDevMode ? [{ debugName: "keyOf" }] : /* istanbul ignore next */ []);
1844
1976
  turning = input(false, ...ngDevMode ? [{ debugName: "turning" }] : /* istanbul ignore next */ []);
1845
1977
  turnBelow = input(640, ...ngDevMode ? [{ debugName: "turnBelow" }] : /* istanbul ignore next */ []);
@@ -1865,9 +1997,12 @@ var CubeSquare = class CubeSquare {
1865
1997
  width,
1866
1998
  tall: r.tall || width
1867
1999
  };
2000
+ const least = this.least();
2001
+ const side = Math.min(width, room.tall, this.maxSide());
1868
2002
  const opts = {
1869
2003
  maxSide: this.maxSide(),
1870
- listRow: this.listRow()
2004
+ listRow: this.listRow(),
2005
+ least: !this.dashed() ? 0 : least === "room" ? squareLeast(side) : least
1871
2006
  };
1872
2007
  const front = this.front();
1873
2008
  if (!front) return squareLayout(this.view(), this.tiles().length, room, opts);
@@ -2122,6 +2257,13 @@ var CubeSquare = class CubeSquare {
2122
2257
  isRequired: false,
2123
2258
  transformFunction: null
2124
2259
  },
2260
+ least: {
2261
+ classPropertyName: "least",
2262
+ publicName: "least",
2263
+ isSignal: true,
2264
+ isRequired: false,
2265
+ transformFunction: null
2266
+ },
2125
2267
  keyOf: {
2126
2268
  classPropertyName: "keyOf",
2127
2269
  publicName: "keyOf",
@@ -2467,6 +2609,14 @@ i0.ɵɵngDeclareClassMetadata({
2467
2609
  required: false
2468
2610
  }]
2469
2611
  }],
2612
+ least: [{
2613
+ type: i0.Input,
2614
+ args: [{
2615
+ isSignal: true,
2616
+ alias: "least",
2617
+ required: false
2618
+ }]
2619
+ }],
2470
2620
  keyOf: [{
2471
2621
  type: i0.Input,
2472
2622
  args: [{
@@ -2822,6 +2972,7 @@ var CubeContext = class CubeContext {
2822
2972
  "maxSide",
2823
2973
  "listRow",
2824
2974
  "dashed",
2975
+ "least",
2825
2976
  "keyOf",
2826
2977
  "turning",
2827
2978
  "turnBelow",
@@ -3165,6 +3316,7 @@ var CubeLoading = class CubeLoading {
3165
3316
  "maxSide",
3166
3317
  "listRow",
3167
3318
  "dashed",
3319
+ "least",
3168
3320
  "keyOf",
3169
3321
  "turning",
3170
3322
  "turnBelow",
@@ -3272,6 +3424,6 @@ i0.ɵɵngDeclareClassMetadata({
3272
3424
  }]
3273
3425
  }
3274
3426
  });
3275
- export { CONTEXT_CUBE_SOURCE, CONTEXT_CUBE_WORDS, CONTEXT_PART_ORDER, CUBE_CARRY_CLASSES, CUBE_CARRY_MOVE, CUBE_DROP_OUT, CUBE_HOLD_MS, CUBE_HOLD_SLOP, CUBE_ICON_NAMES, CUBE_LOADING_COLOURS, CUBE_LOADING_LEVELS, CUBE_LOADING_STEP_MS, CUBE_LOADING_STICKERS, CUBE_LOADING_WAYS, CUBE_LOADING_WIDTH, CUBE_PINCH_APART, CUBE_PINCH_TOGETHER, CUBE_WHEEL_QUIET_MS, CubeCarry, CubeContext, CubeHold, CubeIcon, CubeLoading, CubePicture, CubePinch, CubeSquare, CubeSquareTile, PART_ICONS, SQUARE_LIST_ROW, SQUARE_MAX_SIDE, TEXT_ORDERS, TURNING_BELOW, TURNING_NUDGE_UNTIL, TURNING_SIDES, VIEW_KEYS, contextIcon, contextLevelFor, contextSquare, cubeIconCells, directionWords, drawCube, gridFor, hideLevel, insideOf, isView, loadingStickers, loadingWayFor, namesLevel, orderParts, partsLevel, placesOf, refusalOf, sizeFor, sortDirectionsLevel, sortItems, sortLevel, squareGap, squareLayout, squareLevelFor, startsWheelGesture, stillStep, turningFront, turningRows, viewLevel, whereLevel, wouldLoop };
3427
+ export { CONTEXT_CUBE_SOURCE, CONTEXT_CUBE_WORDS, CONTEXT_PART_ORDER, CUBE_CARRY_CLASSES, CUBE_CARRY_MOVE, CUBE_DROP_OUT, CUBE_HOLD_MS, CUBE_HOLD_SLOP, CUBE_ICON_NAMES, CUBE_LOADING_COLOURS, CUBE_LOADING_LEVELS, CUBE_LOADING_STEP_MS, CUBE_LOADING_STICKERS, CUBE_LOADING_WAYS, CUBE_LOADING_WIDTH, CUBE_PINCH_APART, CUBE_PINCH_TOGETHER, CUBE_WHEEL_QUIET_MS, CubeCarry, CubeContext, CubeHold, CubeIcon, CubeLoading, CubePicture, CubePinch, CubeSquare, CubeSquareTile, MINE_SORT, PART_ICONS, SQUARE_LEAST_CELL, SQUARE_LIST_ROW, SQUARE_MAX_SIDE, TEXT_ORDERS, TURNING_BELOW, TURNING_NUDGE_UNTIL, TURNING_SIDES, VIEW_KEYS, addLevel, bringLevel, bringOf, contextIcon, contextLevelFor, contextSquare, cubeIconCells, directionWords, drawCube, gridFor, hideLevel, insideOf, isView, loadingStickers, loadingWayFor, moveBefore, namesLevel, orderLevel, orderOf, orderParts, partsLevel, placesOf, refusalOf, sizeFor, sortDirectionsLevel, sortItems, sortLevel, squareGap, squareLayout, squareLeast, squareLevelFor, startsWheelGesture, stillStep, turningFront, turningRows, viewLevel, whereLevel, wouldLoop };
3276
3428
 
3277
3429
  //# sourceMappingURL=selimssevgi-cube-design-angular.mjs.map