@n-uf/placement 26.11.4 → 26.11.5
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 +12 -0
- package/README.md +42 -1
- package/dist/{chunk-PBH6TKET.js → chunk-FMTCXDKK.js} +4 -3
- package/dist/chunk-FMTCXDKK.js.map +1 -0
- package/dist/targets.d.ts +44 -1
- package/dist/targets.js +62 -2
- package/dist/targets.js.map +1 -1
- package/dist/toolbar.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-PBH6TKET.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,18 @@
|
|
|
3
3
|
Versions are calendar versions, `YY.M.R` (year, month of the release, counter within the month), shared with
|
|
4
4
|
`@n-uf/motion`: both packages carry the same version, and a release bumps both.
|
|
5
5
|
|
|
6
|
+
## 26.11.5
|
|
7
|
+
|
|
8
|
+
- `@n-uf/placement/targets`: `paneZone(rect, point, previous, options?)`, a pane's five drop zones: the centre
|
|
9
|
+
rectangle (34 % of each axis, at least 24 px, its edges snapped to the device-pixel grid) or one of four edge
|
|
10
|
+
trapezoids from the corners. The previous zone holds for 6 px past its boundary. `paneCentre` gives the centre's
|
|
11
|
+
rectangle (to draw the zones); `PANE_ZONE_DEFAULTS` and `PANE_EDGES` (the tie-break order) come with it. It fits
|
|
12
|
+
`@n-uf/motion/drag`'s new `placeOf(target, point, previous)`: the zone is the place, and a zone that takes no drop
|
|
13
|
+
answers null. Ported from hypr-tiling's engine.
|
|
14
|
+
- Fix: `sameArrangement` compares the collapsed groups and the floating groups' ids both ways, so a repeated group on
|
|
15
|
+
one side no longer passes for a different group on the other.
|
|
16
|
+
- The README lists all fifteen layout note codes; every code has a test.
|
|
17
|
+
|
|
6
18
|
## 26.11.4
|
|
7
19
|
|
|
8
20
|
The first release: where things go, as pure functions over plain data. No DOM, no framework, no motion, no
|
package/README.md
CHANGED
|
@@ -55,7 +55,25 @@ console.log(items.get("panel:3")!.look, notes.map((n) => n.code)); // header [ '
|
|
|
55
55
|
Each construction is `{ id, title, idea, initial(docs, size?), layout(state, size, options) }`. A layout returns a
|
|
56
56
|
`Placed` per item (its rect, look, layer, and whether it is hidden, has a minimum or may scroll off the stage) and
|
|
57
57
|
notes saying how it gave way. A note's `code` (with its `side` and `items` where they apply) is the contract; its
|
|
58
|
-
`text` is English for people, and its wording may change in any release.
|
|
58
|
+
`text` is English for people, and its wording may change in any release. The codes (`NoteCode`):
|
|
59
|
+
|
|
60
|
+
| Code | Says | Also |
|
|
61
|
+
|---|---|---|
|
|
62
|
+
| `bottom-folded` | the bottom dock folded to its header | |
|
|
63
|
+
| `dock-folded` | a side dock folded to its rail | `side` |
|
|
64
|
+
| `sections-folded` | sections folded to their headers by themselves, least recently used first | |
|
|
65
|
+
| `torn-floating` | panels torn off a dock float | `items` |
|
|
66
|
+
| `torn-shaded` | some torn-off panels shade because they don't fit | |
|
|
67
|
+
| `columns-railed` | the tiling tree's side columns folded to rails | `side` when only one |
|
|
68
|
+
| `tiles-float` | tiles that broke a minimum float, newest first | `items` |
|
|
69
|
+
| `tabs-folded` | a tabbed side folded to icon tabs | `side` |
|
|
70
|
+
| `drawer-over` | a drawer slides over the documents | `side` |
|
|
71
|
+
| `column-split` | a strip column split in two | `items` |
|
|
72
|
+
| `strip-scrolls` | the strip is wider than the stage | |
|
|
73
|
+
| `stacks-merged` | both palette stacks share one corner | |
|
|
74
|
+
| `palettes-shaded` | palettes shaded to their title bars | |
|
|
75
|
+
| `palettes-cover` | how much of the documents the palettes cover | |
|
|
76
|
+
| `docs-room` | how much room the palettes leave the documents | |
|
|
59
77
|
|
|
60
78
|
## Toolbar groups
|
|
61
79
|
|
|
@@ -90,6 +108,29 @@ console.log(drop.label, drop.slot.x, drop.slot.y); // Float here 580 290
|
|
|
90
108
|
A toolbar group's targets come from `hostTargets` (a host's lines and empty zones, with its own place left out and
|
|
91
109
|
returned as `own`, for the drag's home) and `floatTarget`.
|
|
92
110
|
|
|
111
|
+
## Pane zones
|
|
112
|
+
|
|
113
|
+
`paneZone(rect, point, previous, options?)` says which of a pane's five zones a point is in: the centre rectangle
|
|
114
|
+
(34 % of each axis, at least 24 px) or one of four edge trapezoids. The previous zone holds for 6 px past its
|
|
115
|
+
boundary. It fits `@n-uf/motion/drag`'s `placeOf(target, point, previous)`: one target per pane, the zone as the
|
|
116
|
+
place, and a null place for a zone that takes no drop.
|
|
117
|
+
|
|
118
|
+
```ts
|
|
119
|
+
import { paneZone, type PaneZone } from "@n-uf/placement/targets";
|
|
120
|
+
|
|
121
|
+
const pane = { x: 0, y: 0, width: 200, height: 200 };
|
|
122
|
+
console.log(paneZone(pane, { x: 100, y: 100 }), paneZone(pane, { x: 190, y: 100 })); // center right
|
|
123
|
+
console.log(paneZone(pane, { x: 137, y: 100 }, "center")); // center: 3 px past the line, it holds
|
|
124
|
+
|
|
125
|
+
// As a placeOf: the pane's id and zone, none where this pane can't take a drop beside it.
|
|
126
|
+
const canSplit = false;
|
|
127
|
+
const placeOf = (t: { id: string; hit: typeof pane }, p: { x: number; y: number }, previous: string | null): string | null => {
|
|
128
|
+
const zone = paneZone(t.hit, p, (previous?.split(":")[1] as PaneZone | undefined) ?? null);
|
|
129
|
+
return zone === "center" || canSplit ? `${t.id}:${zone}` : null;
|
|
130
|
+
};
|
|
131
|
+
console.log(placeOf({ id: "a", hit: pane }, { x: 100, y: 100 }, null), placeOf({ id: "a", hit: pane }, { x: 10, y: 100 }, null)); // a:center null
|
|
132
|
+
```
|
|
133
|
+
|
|
93
134
|
## License
|
|
94
135
|
|
|
95
136
|
[PolyForm Perimeter 1.0.1](./LICENSE).
|
|
@@ -51,9 +51,10 @@ var isEmptyHost = (a, h) => ZONES.every((zn) => a[h][zn].length === 0);
|
|
|
51
51
|
var samePlace = (a, b) => a === null || b === null ? a === b : a.host === b.host && a.zone === b.zone && a.index === b.index;
|
|
52
52
|
function sameArrangement(a, b) {
|
|
53
53
|
const sameList = (x, y) => x.length === y.length && x.every((g, i) => g === y[i]);
|
|
54
|
-
const sameSet = (x, y) => x.length === y.length && x.every((g) => y.includes(g));
|
|
54
|
+
const sameSet = (x, y) => x.length === y.length && x.every((g) => y.includes(g)) && y.every((g) => x.includes(g));
|
|
55
55
|
if (!HOSTS.every((h) => ZONES.every((zn) => sameList(a[h][zn], b[h][zn])))) return false;
|
|
56
|
-
if (!sameSet(a.collapsed, b.collapsed)
|
|
56
|
+
if (!sameSet(a.collapsed, b.collapsed)) return false;
|
|
57
|
+
if (!sameSet(a.floating.map((f) => f.id), b.floating.map((f) => f.id))) return false;
|
|
57
58
|
return a.floating.every((f) => {
|
|
58
59
|
const o = b.floating.find((x) => x.id === f.id);
|
|
59
60
|
return !!o && o.x === f.x && o.y === f.y && samePlace(o.from, f.from);
|
|
@@ -163,4 +164,4 @@ export {
|
|
|
163
164
|
layoutHost,
|
|
164
165
|
insertions
|
|
165
166
|
};
|
|
166
|
-
//# sourceMappingURL=chunk-
|
|
167
|
+
//# sourceMappingURL=chunk-FMTCXDKK.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/toolbar/index.ts"],"sourcesContent":["/**\n * @n-uf/placement/toolbar: toolbar groups as a pure model. Commands come in groups, each sitting in one of five\n * hosts (the title bar, the top toolbar, a bottom toolbar, a left and a right side toolbar), in one of three zones\n * (start, centre, end; top, middle, bottom on a side), in order; or floating. A toolbar is a slot: it never moves\n * itself, its groups do. Group sizes come in as numbers; group ids are the consumer's strings.\n *\n * - A host lays its zones out along its length: start from the lead, end up to the tail, the centre centred on the\n * whole host; when the centre would hit the start or end zone it centres in the space between them.\n * - Toolbars never wrap: when room runs out, groups collapse to their handle and » from the trailing end. A group\n * collapsed by hand stays collapsed.\n * - A group drop lands in a zone before all, after all, or between two groups. An empty zone is a target of its\n * own. A group's own place is home: a drop there changes nothing.\n */\nimport type { Rect } from \"../geometry\";\n\nexport type HostId = \"title\" | \"top\" | \"bottom\" | \"left\" | \"right\";\nexport type ZoneId = \"start\" | \"center\" | \"end\";\nexport type Zones<G extends string = string> = Readonly<Record<ZoneId, readonly G[]>>;\n\n/** Where a group is docked: a host, a zone, and its index there. */\nexport interface Place {\n readonly host: HostId;\n readonly zone: ZoneId;\n readonly index: number;\n}\n\n/** A group floating over the content: its top-left corner, and where it was docked. */\nexport interface Floating<G extends string = string> {\n readonly id: G;\n readonly x: number;\n readonly y: number;\n readonly from: Place | null;\n}\n\nexport type Arrangement<G extends string = string> = Readonly<Record<HostId, Zones<G>>> & {\n /** Groups collapsed to their handle and » by hand. */\n readonly collapsed: readonly G[];\n readonly floating: readonly Floating<G>[];\n};\n\nexport const HOSTS: readonly HostId[] = [\"title\", \"top\", \"bottom\", \"left\", \"right\"];\nexport const ZONES: readonly ZoneId[] = [\"start\", \"center\", \"end\"];\n\nexport const HOST_LABEL: Readonly<Record<HostId, string>> = { title: \"Title bar\", top: \"Top bar\", bottom: \"Bottom bar\", left: \"Left edge\", right: \"Right edge\" };\nexport const zoneLabel = (h: HostId, z: ZoneId): string => (vertical(h) ? { start: \"top\", center: \"middle\", end: \"bottom\" } : { start: \"left\", center: \"centre\", end: \"right\" })[z];\n\n/** The side edges hold their groups in a column. */\nexport const vertical = (h: HostId): boolean => h === \"left\" || h === \"right\";\n\n/** Between two groups (the handle of the second is the separator). */\nexport const GAP = 12;\n/** Between zones. */\nexport const ZONE_GAP = 16;\n\n/** An arrangement from the zones each host has (the rest empty), nothing collapsed or floating. */\nexport function arrangement<G extends string>(p: Partial<Record<HostId, Partial<Record<ZoneId, readonly G[]>>>>): Arrangement<G> {\n const z = (q: Partial<Record<ZoneId, readonly G[]>> = {}): Zones<G> => ({ start: [], center: [], end: [], ...q });\n return { title: z(p.title), top: z(p.top), bottom: z(p.bottom), left: z(p.left), right: z(p.right), collapsed: [], floating: [] };\n}\n\n// --- changes -------------------------------------------------------------------------------------------------------\n\nconst mapHosts = <G extends string>(a: Arrangement<G>, f: (h: HostId, zone: ZoneId, list: readonly G[]) => readonly G[]): Arrangement<G> => ({\n ...a,\n ...(Object.fromEntries(HOSTS.map((h) => [h, Object.fromEntries(ZONES.map((zn) => [zn, f(h, zn, a[h][zn])]))])) as Record<HostId, Zones<G>>),\n});\n\n/** Where `g` is docked (null: floating or absent). */\nexport function hostOf<G extends string>(a: Arrangement<G>, g: G): Place | null {\n for (const h of HOSTS) for (const zn of ZONES) if (a[h][zn].includes(g)) return { host: h, zone: zn, index: a[h][zn].indexOf(g) };\n return null;\n}\n\n/** The arrangement with group `g` lifted out (of its host, or from floating). */\nexport const withoutGroup = <G extends string>(a: Arrangement<G>, g: G): Arrangement<G> => ({ ...mapHosts(a, (_h, _z, l) => l.filter((x) => x !== g)), floating: a.floating.filter((f) => f.id !== g) });\n\n/** The arrangement with `g` docked at place `i` of zone `zone` of host `h` (`i` counts the others). */\nexport function insertGroup<G extends string>(a: Arrangement<G>, g: G, h: HostId, zone: ZoneId, i: number): Arrangement<G> {\n return mapHosts(withoutGroup(a, g), (hh, zz, l) => (hh === h && zz === zone ? [...l.slice(0, i), g, ...l.slice(i)] : l));\n}\n\n/** `g` floating with its top-left corner at (x, y); it remembers where it was docked. */\nexport function floatGroup<G extends string>(a: Arrangement<G>, g: G, x: number, y: number): Arrangement<G> {\n const from = hostOf(a, g) ?? a.floating.find((f) => f.id === g)?.from ?? null;\n const out = withoutGroup(a, g);\n return { ...out, floating: [...out.floating, { id: g, x, y, from }] };\n}\n\n/** `g` at `place`, its index kept within the zone. */\nconst dockAt = <G extends string>(a: Arrangement<G>, g: G, place: Place): Arrangement<G> =>\n insertGroup(a, g, place.host, place.zone, Math.min(place.index, a[place.host][place.zone].filter((x) => x !== g).length));\n\n/** `g` docked again where it floated from, else where `home` (the default arrangement) has it. */\nexport function dockGroup<G extends string>(a: Arrangement<G>, g: G, home: Arrangement<G>): Arrangement<G> {\n const from = a.floating.find((f) => f.id === g)?.from ?? hostOf(home, g);\n return from ? dockAt(a, g, from) : a;\n}\n\n/** `g` back where `home` (the default arrangement) has it, expanded. */\nexport function resetGroup<G extends string>(a: Arrangement<G>, g: G, home: Arrangement<G>): Arrangement<G> {\n const place = hostOf(home, g);\n const out = place ? dockAt(a, g, place) : a;\n return { ...out, collapsed: out.collapsed.filter((x) => x !== g) };\n}\n\n/** `g` moved to host `h`: after its last group (in its last zone that has any), or into its start zone. */\nexport function moveToHost<G extends string>(a: Arrangement<G>, g: G, h: HostId): Arrangement<G> {\n const rest = withoutGroup(a, g);\n const zone = [...ZONES].reverse().find((zn) => rest[h][zn].length > 0) ?? \"start\";\n return insertGroup(a, g, h, zone, rest[h][zone].length);\n}\n\n/** Every group of host `from` moved to host `to`, zone by zone, after the groups there. */\nexport function moveBar<G extends string>(a: Arrangement<G>, from: HostId, to: HostId): Arrangement<G> {\n if (from === to) return a;\n return mapHosts(a, (h, zn, l) => (h === from ? [] : h === to ? [...l, ...a[from][zn]] : l));\n}\n\nexport const toggleCollapsed = <G extends string>(a: Arrangement<G>, g: G): Arrangement<G> => ({ ...a, collapsed: a.collapsed.includes(g) ? a.collapsed.filter((x) => x !== g) : [...a.collapsed, g] });\n\nexport const isEmptyHost = <G extends string>(a: Arrangement<G>, h: HostId): boolean => ZONES.every((zn) => a[h][zn].length === 0);\n\nconst samePlace = (a: Place | null, b: Place | null): boolean => (a === null || b === null ? a === b : a.host === b.host && a.zone === b.zone && a.index === b.index);\n\n/**\n * The same arrangement: the same groups in the same order in every zone of every host, the same groups collapsed,\n * and the same groups floating at the same corner with the same home (in any order: neither list's order means\n * anything). Compared field by field, so how the arrangement was written down (its keys' order) doesn't matter.\n */\nexport function sameArrangement<G extends string>(a: Arrangement<G>, b: Arrangement<G>): boolean {\n const sameList = (x: readonly G[], y: readonly G[]): boolean => x.length === y.length && x.every((g, i) => g === y[i]);\n // Both ways, so a repeated id on one side can't stand in for a missing one ([\"a\", \"a\"] is not [\"a\", \"b\"]).\n const sameSet = (x: readonly G[], y: readonly G[]): boolean => x.length === y.length && x.every((g) => y.includes(g)) && y.every((g) => x.includes(g));\n if (!HOSTS.every((h) => ZONES.every((zn) => sameList(a[h][zn], b[h][zn])))) return false;\n if (!sameSet(a.collapsed, b.collapsed)) return false;\n if (!sameSet(a.floating.map((f) => f.id), b.floating.map((f) => f.id))) return false;\n return a.floating.every((f) => {\n const o = b.floating.find((x) => x.id === f.id);\n return !!o && o.x === f.x && o.y === f.y && samePlace(o.from, f.from);\n });\n}\n\n/** Dropping `g` at `place` changes nothing: it is the group's own place, its home, never a target. */\nexport const isOwnPlace = <G extends string>(a: Arrangement<G>, g: G, place: Place): boolean => sameArrangement(insertGroup(a, g, place.host, place.zone, place.index), a);\n\n// --- a host's layout -----------------------------------------------------------------------------------------------\n\n/** A host's room: its length and thickness, and what its ends keep for themselves (window controls, a margin). */\nexport interface HostSpec {\n readonly length: number;\n readonly thickness: number;\n readonly lead: number;\n readonly tail: number;\n /**\n * The centre zone's minimum length and its margin on each side, counted in the need whether it holds groups or\n * not (an empty centre keeps its drop size). Unset: the centre counts only its groups.\n */\n readonly center?: { readonly min: number; readonly margin: number };\n}\n\n/** A group's size in a host, expanded or collapsed: along it (`along`) and across it (`across`). */\nexport type GroupSize<G extends string = string> = (id: G, vertical: boolean, collapsed: boolean) => { along: number; across: number };\n\nexport interface HostLayout<G extends string = string> {\n /** Each group's rect in the host (x along, y across for a horizontal host; transposed on a side). */\n readonly slots: ReadonlyMap<G, Rect>;\n /** Groups shown collapsed (by hand, or because the room ran out). */\n readonly collapsed: readonly G[];\n /** Of those, the ones the room collapsed (from the trailing end). */\n readonly overflow: readonly G[];\n /** The length the groups and the ends take. */\n readonly need: number;\n}\n\n/** How long the host's groups need it to be, collapsing only those in `collapsed`. */\nexport function hostNeed<G extends string>(zones: Zones<G>, collapsed: readonly G[], spec: Pick<HostSpec, \"lead\" | \"tail\" | \"center\">, size: GroupSize<G>, v: boolean): number {\n const lens = ZONES.map((zn) => zones[zn].reduce((s, g) => s + size(g, v, collapsed.includes(g)).along, 0) + GAP * Math.max(0, zones[zn].length - 1));\n const used = ZONES.filter((zn) => zones[zn].length > 0).length;\n const c = spec.center;\n if (!c) return spec.lead + spec.tail + lens.reduce((s, x) => s + x, 0) + ZONE_GAP * Math.max(0, used - 1);\n // The centre always counts, at its minimum at least, and its margins keep it apart from the start and end zones.\n return spec.lead + spec.tail + lens[0]! + lens[2]! + Math.max(lens[1]!, c.min) + 2 * c.margin;\n}\n\n/** Lay a host out: zones along its length; when they don't fit, groups collapse from the trailing end. */\nexport function layoutHost<G extends string>(zones: Zones<G>, h: HostId, spec: HostSpec, size: GroupSize<G>, byHand: readonly G[] = []): HostLayout<G> {\n const v = vertical(h);\n const collapsed = new Set<G>(ZONES.flatMap((zn) => zones[zn]).filter((g) => byHand.includes(g)));\n const overflow: G[] = [];\n const len = (g: G): number => size(g, v, collapsed.has(g)).along;\n const zoneLen = (l: readonly G[]): number => l.reduce((s, g) => s + len(g), 0) + GAP * Math.max(0, l.length - 1);\n const needNow = (): number => hostNeed(zones, [...collapsed], spec, size, v);\n // The trailing end first: the end zone's last group, back to the start zone's first.\n for (const g of [...ZONES].reverse().flatMap((zn) => [...zones[zn]].reverse())) {\n if (needNow() <= spec.length) break;\n if (collapsed.has(g)) continue;\n collapsed.add(g);\n overflow.push(g);\n }\n const a0 = spec.lead;\n const b0 = spec.length - spec.tail;\n const S = zoneLen(zones.start);\n const C = zoneLen(zones.center);\n const E = zoneLen(zones.end);\n const lo = a0 + S + (S > 0 ? ZONE_GAP : 0);\n const hi = b0 - E - (E > 0 ? ZONE_GAP : 0);\n let c0 = spec.length / 2 - C / 2;\n if (c0 < lo || c0 + C > hi) c0 = (lo + hi) / 2 - C / 2;\n const slots = new Map<G, Rect>();\n const place = (l: readonly G[], from: number): void => {\n let at = from;\n for (const g of l) {\n const s = size(g, v, collapsed.has(g));\n const across = (spec.thickness - s.across) / 2;\n slots.set(g, v ? { x: across, y: at, width: s.across, height: s.along } : { x: at, y: across, width: s.along, height: s.across });\n at += s.along + GAP;\n }\n };\n place(zones.start, a0);\n place(zones.center, c0);\n place(zones.end, b0 - E);\n return { slots, collapsed: [...collapsed], overflow, need: needNow() };\n}\n\n// --- insertion points ----------------------------------------------------------------------------------------------\n\n/** A place a dragged group can go: a zone of a host and the index among the others there, and where it is. */\nexport interface Insertion extends Place {\n /** Along the host: the insertion line (between groups); for an empty zone, the zone's middle. */\n readonly at: number;\n /** The stretch of the host it owns (host coordinates). */\n readonly span: readonly [number, number];\n /** An empty zone: it owns all of its stretch, whatever is nearer (it wins while the pointer is inside it). */\n readonly empty: boolean;\n readonly label: string;\n}\n\n/**\n * The insertion points of a host laid out without the dragged group: in each zone before all, between two, after\n * all; each owns the stretch of the host nearest to it. An empty zone owns its own stretch: the host's first third\n * (start), middle third (centre) or last third (end), less what its neighbours' groups take. `label` names a group\n * in the \"between\" labels (default: its id).\n */\nexport function insertions<G extends string>(zones: Zones<G>, h: HostId, spec: HostSpec, l: HostLayout<G>, label: (g: G) => string = (g) => g): Insertion[] {\n const v = vertical(h);\n const lo = (r: Rect): number => (v ? r.y : r.x);\n const hi = (r: Rect): number => (v ? r.y + r.height : r.x + r.width);\n const L = spec.length;\n const all = ZONES.flatMap((zn) => zones[zn].map((g) => l.slots.get(g)).filter((r): r is Rect => !!r));\n const first = all.length ? Math.min(...all.map(lo)) : L;\n const last = all.length ? Math.max(...all.map(hi)) : 0;\n const zoneEdge = (zn: ZoneId, end: \"lo\" | \"hi\"): number | null => {\n const rs = zones[zn].map((g) => l.slots.get(g)).filter((r): r is Rect => !!r);\n if (!rs.length) return null;\n return end === \"lo\" ? Math.min(...rs.map(lo)) : Math.max(...rs.map(hi));\n };\n const near: Omit<Insertion, \"span\">[] = [];\n const empties: Insertion[] = [];\n for (const zn of ZONES) {\n const name = `${HOST_LABEL[h]} · ${zoneLabel(h, zn)}`;\n const vis = zones[zn].map((g, i) => ({ g, i, r: l.slots.get(g)! }));\n if (!vis.length) {\n const sEnd = zoneEdge(\"start\", \"hi\");\n const eStart = zoneEdge(\"end\", \"lo\");\n const span: [number, number] =\n zn === \"start\" ? [0, Math.min(L / 3, first - GAP / 2)] : zn === \"end\" ? [Math.max((2 * L) / 3, last + GAP / 2), L] : [Math.max(L / 3, (sEnd ?? 0) + GAP / 2), Math.min((2 * L) / 3, (eStart ?? L) - GAP / 2)];\n if (span[1] - span[0] >= 8) empties.push({ host: h, zone: zn, index: 0, at: (span[0] + span[1]) / 2, span, empty: true, label: name });\n continue;\n }\n near.push({ host: h, zone: zn, index: vis[0]!.i, at: lo(vis[0]!.r) - GAP / 2, empty: false, label: `${name} · before all` });\n for (let k = 1; k < vis.length; k++) near.push({ host: h, zone: zn, index: vis[k]!.i, at: (hi(vis[k - 1]!.r) + lo(vis[k]!.r)) / 2, empty: false, label: `${name} · between ${label(vis[k - 1]!.g)} and ${label(vis[k]!.g)}` });\n near.push({ host: h, zone: zn, index: zones[zn].length, at: hi(vis.at(-1)!.r) + GAP / 2, empty: false, label: `${name} · after all` });\n }\n near.sort((a, b) => a.at - b.at);\n const lines = near.map((p, k) => ({ ...p, span: [k === 0 ? 0 : (near[k - 1]!.at + p.at) / 2, k === near.length - 1 ? L : (p.at + near[k + 1]!.at) / 2] as const }));\n return [...lines, ...empties];\n}\n"],"mappings":"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","names":[]}
|
package/dist/targets.d.ts
CHANGED
|
@@ -122,4 +122,47 @@ declare function floatTarget<G extends string>(input: {
|
|
|
122
122
|
readonly height: number;
|
|
123
123
|
}): ToolbarFloatTarget<G>;
|
|
124
124
|
|
|
125
|
-
|
|
125
|
+
/**
|
|
126
|
+
* A pane's drop zones: a centre rectangle (put it in the pane's place, merge or swap) and four edge trapezoids (put
|
|
127
|
+
* it beside the pane on that side), formed by the diagonals from each pane corner to the nearest corner of the
|
|
128
|
+
* centre. The five zones tile the pane with no gaps and no overlaps.
|
|
129
|
+
*
|
|
130
|
+
* Meant for `@n-uf/motion/drag`'s `placeOf(target, point, previous)`: one target per pane, its place the zone under
|
|
131
|
+
* the pointer, the previous zone held for `hysteresis` px past its boundary so a pointer resting on a boundary
|
|
132
|
+
* doesn't flicker. A zone that takes no drop is the consumer's to answer with a null place.
|
|
133
|
+
*/
|
|
134
|
+
|
|
135
|
+
type PaneZone = "center" | "top" | "right" | "bottom" | "left";
|
|
136
|
+
/** The edge zones in their tie-break order: at an exact diagonal the first wins (a corner resolves to `top`). */
|
|
137
|
+
declare const PANE_EDGES: readonly Exclude<PaneZone, "center">[];
|
|
138
|
+
interface PaneZoneOptions {
|
|
139
|
+
/** The centre rectangle's share of each pane axis (0.05 to 0.95); `centreX` / `centreY` override one axis. */
|
|
140
|
+
readonly centre?: number;
|
|
141
|
+
readonly centreX?: number;
|
|
142
|
+
readonly centreY?: number;
|
|
143
|
+
/** The least the centre spans on either axis, px (a small pane keeps a usable centre). */
|
|
144
|
+
readonly centreMin?: number;
|
|
145
|
+
/** How far past its boundary the previous zone holds, px. */
|
|
146
|
+
readonly hysteresis?: number;
|
|
147
|
+
/** Device pixels per px: the centre's edges snap to that grid, as the browser draws them. */
|
|
148
|
+
readonly pixelRatio?: number;
|
|
149
|
+
}
|
|
150
|
+
declare const PANE_ZONE_DEFAULTS: Required<Omit<PaneZoneOptions, "centreX" | "centreY">>;
|
|
151
|
+
/** The centre rectangle of a pane of `size`, in pane-local px (origin at the pane's top-left corner). */
|
|
152
|
+
interface PaneCentre {
|
|
153
|
+
readonly width: number;
|
|
154
|
+
readonly height: number;
|
|
155
|
+
readonly left: number;
|
|
156
|
+
readonly top: number;
|
|
157
|
+
readonly right: number;
|
|
158
|
+
readonly bottom: number;
|
|
159
|
+
}
|
|
160
|
+
/** Where the centre rectangle of a pane of `size` lies, by these options. */
|
|
161
|
+
declare function paneCentre(size: Size, options?: PaneZoneOptions): PaneCentre;
|
|
162
|
+
/**
|
|
163
|
+
* The zone of `rect` (a pane, in the same coordinates as `point`) the point is in. With a `previous` zone, the point
|
|
164
|
+
* has to be `hysteresis` px past that zone's boundary before the zone changes: no time-based debounce, only geometry.
|
|
165
|
+
*/
|
|
166
|
+
declare function paneZone(rect: Rect, point: Point, previous?: PaneZone | null, options?: PaneZoneOptions): PaneZone;
|
|
167
|
+
|
|
168
|
+
export { type DeskDrop, type DeskTarget, type DeskTargetInput, type HostTargetsInput, LINE_REACH, type Made, PANE_EDGES, PANE_ZONE_DEFAULTS, type PaneCentre, type PaneZone, type PaneZoneOptions, SNAP, type Target, type ToolbarFloatTarget, type ToolbarTarget, ZONE_REACH, deskDrop, deskTargets, floatTarget, hostTargets, paneCentre, paneZone };
|
package/dist/targets.js
CHANGED
|
@@ -38,7 +38,7 @@ import {
|
|
|
38
38
|
layoutHost,
|
|
39
39
|
vertical,
|
|
40
40
|
withoutGroup
|
|
41
|
-
} from "./chunk-
|
|
41
|
+
} from "./chunk-FMTCXDKK.js";
|
|
42
42
|
|
|
43
43
|
// src/targets/desk.ts
|
|
44
44
|
var SNAP = 18;
|
|
@@ -367,13 +367,73 @@ function floatTarget(input) {
|
|
|
367
367
|
}
|
|
368
368
|
};
|
|
369
369
|
}
|
|
370
|
+
|
|
371
|
+
// src/targets/zones.ts
|
|
372
|
+
var PANE_EDGES = ["top", "right", "bottom", "left"];
|
|
373
|
+
var PANE_ZONE_DEFAULTS = { centre: 0.34, centreMin: 24, hysteresis: 6, pixelRatio: 1 };
|
|
374
|
+
var clamp2 = (v, lo, hi) => Math.min(Math.max(v, lo), hi);
|
|
375
|
+
var snap = (v, ratio) => Math.round(v * ratio) / ratio;
|
|
376
|
+
function paneCentre(size, options = {}) {
|
|
377
|
+
const o = { ...PANE_ZONE_DEFAULTS, ...options };
|
|
378
|
+
const width = Math.max(0, size.width);
|
|
379
|
+
const height = Math.max(0, size.height);
|
|
380
|
+
const ratio = o.pixelRatio > 0 ? o.pixelRatio : 1;
|
|
381
|
+
const rx = clamp2(o.centreX ?? o.centre, 0.05, 0.95);
|
|
382
|
+
const ry = clamp2(o.centreY ?? o.centre, 0.05, 0.95);
|
|
383
|
+
const cw = Math.min(width, Math.max(width * rx, Math.min(o.centreMin, width)));
|
|
384
|
+
const ch = Math.min(height, Math.max(height * ry, Math.min(o.centreMin, height)));
|
|
385
|
+
return { width, height, left: snap((width - cw) / 2, ratio), top: snap((height - ch) / 2, ratio), right: snap((width + cw) / 2, ratio), bottom: snap((height + ch) / 2, ratio) };
|
|
386
|
+
}
|
|
387
|
+
function depths(p, c) {
|
|
388
|
+
return [
|
|
389
|
+
{ zone: "top", depth: (c.top - p.y) / Math.max(c.top, 1) },
|
|
390
|
+
{ zone: "right", depth: (p.x - c.right) / Math.max(c.width - c.right, 1) },
|
|
391
|
+
{ zone: "bottom", depth: (p.y - c.bottom) / Math.max(c.height - c.bottom, 1) },
|
|
392
|
+
{ zone: "left", depth: (c.left - p.x) / Math.max(c.left, 1) }
|
|
393
|
+
];
|
|
394
|
+
}
|
|
395
|
+
function rawZone(p, c) {
|
|
396
|
+
if (p.x >= c.left && p.x <= c.right && p.y >= c.top && p.y <= c.bottom) return "center";
|
|
397
|
+
let best = "center";
|
|
398
|
+
let deepest = 0;
|
|
399
|
+
for (const d of depths(p, c)) {
|
|
400
|
+
if (d.depth > deepest) {
|
|
401
|
+
deepest = d.depth;
|
|
402
|
+
best = d.zone;
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
return best;
|
|
406
|
+
}
|
|
407
|
+
function toward(p, zone, by, c) {
|
|
408
|
+
if (zone === "left") return { x: p.x - by, y: p.y };
|
|
409
|
+
if (zone === "right") return { x: p.x + by, y: p.y };
|
|
410
|
+
if (zone === "top") return { x: p.x, y: p.y - by };
|
|
411
|
+
if (zone === "bottom") return { x: p.x, y: p.y + by };
|
|
412
|
+
const dx = c.width / 2 - p.x;
|
|
413
|
+
const dy = c.height / 2 - p.y;
|
|
414
|
+
const len = Math.hypot(dx, dy);
|
|
415
|
+
if (len <= by || len === 0) return { x: c.width / 2, y: c.height / 2 };
|
|
416
|
+
return { x: p.x + dx / len * by, y: p.y + dy / len * by };
|
|
417
|
+
}
|
|
418
|
+
function paneZone(rect2, point, previous = null, options = {}) {
|
|
419
|
+
const c = paneCentre(rect2, options);
|
|
420
|
+
const p = { x: point.x - rect2.x, y: point.y - rect2.y };
|
|
421
|
+
const raw = rawZone(p, c);
|
|
422
|
+
const by = Math.max(0, options.hysteresis ?? PANE_ZONE_DEFAULTS.hysteresis);
|
|
423
|
+
if (previous === null || by === 0 || previous === raw) return raw;
|
|
424
|
+
return rawZone(toward(p, previous, by, c), c) === previous ? previous : raw;
|
|
425
|
+
}
|
|
370
426
|
export {
|
|
371
427
|
LINE_REACH,
|
|
428
|
+
PANE_EDGES,
|
|
429
|
+
PANE_ZONE_DEFAULTS,
|
|
372
430
|
SNAP,
|
|
373
431
|
ZONE_REACH,
|
|
374
432
|
deskDrop,
|
|
375
433
|
deskTargets,
|
|
376
434
|
floatTarget,
|
|
377
|
-
hostTargets
|
|
435
|
+
hostTargets,
|
|
436
|
+
paneCentre,
|
|
437
|
+
paneZone
|
|
378
438
|
};
|
|
379
439
|
//# sourceMappingURL=targets.js.map
|
package/dist/targets.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/targets/desk.ts","../src/targets/toolbar.ts"],"sourcesContent":["/**\n * Each desk construction's drop targets, as pure functions: from the state with the dragged item lifted out, a list\n * of zones with a priority, each able to make the state with the item dropped there.\n *\n * - Edge docks (`docks`, `docksFull`, `dockTear`): a rail (priority 1) takes the panel at the end of its dock (a\n * folded dock keeps it in the rail); a slot between sections (2) and the bottom dock (2) take it at that place;\n * with tear-off, the documents area (3) tears it off to float there.\n * - Tiling tree (`tree`): each slot an insertion produces (2), a side column's row or a dwindle region of the\n * centre; an empty side column's edge (2).\n * - Strip (`strip`): between two columns (2) makes a new column; a gap inside a column (2) puts it there.\n * - Navigator, drawers (`navigator`, `drawers`): a tab strip (1) at the tab under the pointer, a folded side's rail\n * (1), a side's panel (3); the panel becomes the side's showing one.\n * - Palettes (`floatOver`, `floatAround`): a corner stack's column (2) at the place under the pointer; anywhere\n * else in the area (3), snapped to the area's edges (over the documents, also to other palettes' edges).\n */\nimport { centre, overlap, rect, type Point, type Rect, type Size } from \"../geometry\";\nimport type { Construction } from \"../dock/constructions\";\nimport { BAR, G, RAIL, TITLE, idOf, isDocKey, isPanelKey, panelKey, touch, type DeskState, type Layout, type Options, type Side } from \"../dock/model\";\nimport {\n DOCK,\n OVER_MARGIN,\n PALETTE_NARROW,\n TORN_W,\n TREE_COLUMN,\n dockGeometry,\n paletteArea,\n paletteWidth,\n stripColumns,\n stripGeometry,\n treeArea,\n treeFloats,\n treeRails,\n treeShown,\n treeTiles,\n} from \"../dock/parts\";\nimport type { Target } from \"./target\";\n\n/** A target's drop for a pointer: the state with the item there, a label, and a key (same key, same place). */\nexport interface Made {\n readonly state: DeskState;\n readonly label: string;\n readonly key: string;\n}\n\nexport interface DeskTarget extends Target {\n /** The drop with the pointer at `p`, holding the item at `grab` from its top-left corner. */\n readonly make: (p: Point, grab: Point) => Made;\n /** Where the keyboard stops in this target, in order (default: its zone's centre). */\n readonly stops?: readonly Point[];\n}\n\n/** A made drop, laid out. */\nexport interface DeskDrop extends Made {\n readonly target: string;\n readonly layout: Layout;\n /** Where the item lands. */\n readonly slot: Rect;\n /** It lands hidden (folded into a rail). */\n readonly hidden: boolean;\n /** It floats where it is dropped: no room is made for it. */\n readonly free: boolean;\n}\n\nexport interface DeskTargetInput {\n readonly c: Construction;\n /** The state with the dragged item lifted out (`liftOut`). */\n readonly s0: DeskState;\n readonly key: string;\n readonly size: Size;\n readonly opt: Options;\n}\n\n/** How close (stage px) a free drop has to come to an edge to snap to it. */\nexport const SNAP = 18;\n\nconst insert = <T>(list: readonly T[], i: number, x: T): T[] => [...list.slice(0, i), x, ...list.slice(i)];\nconst clamp = (v: number, lo: number, hi: number): number => Math.min(Math.max(v, lo), Math.max(lo, hi));\nconst Cap = (s: Side): string => (s === \"left\" ? \"Left\" : \"Right\");\nconst fixed = (state: DeskState, label: string) => (): Made => ({ state, label, key: label });\n\n/** Zones `count + 1` slots split between items at `mids` (their centres), from `lo` to `hi`: slot i's span. */\nconst slotSpan = (mids: readonly number[], lo: number, hi: number, i: number): [number, number] => [i === 0 ? lo : mids[i - 1]!, i === mids.length ? hi : mids[i]!];\n\n// --- edge docks ----------------------------------------------------------------------------------------------------\n\nfunction dockTargets({ c, s0, key, size, opt }: DeskTargetInput): DeskTarget[] {\n const cat = c.desk.catalog;\n const out: DeskTarget[] = [];\n const id = idOf(key);\n const mode = c.id === \"docksFull\" ? \"full\" : \"between\";\n const d = dockGeometry(cat, s0, size, opt, mode);\n const l0 = c.layout(s0, size, opt);\n const W = size.width;\n const H = size.height;\n for (const side of [\"left\", \"right\"] as const) {\n const railed = l0.items.get(`rail:${side}`);\n if (!railed) continue;\n const label = `${Cap(side)} rail: into the ${side} dock`;\n out.push({ id: `rail:${side}`, priority: 1, hit: railed.rect, make: fixed(touch({ ...s0, [side]: [...s0[side], id] }, id), label) });\n if (side === \"left\" ? !d.lOpen : !d.rOpen) continue;\n // The dock's slots: each section's halves belong to the slots above and below it.\n const shown = side === \"left\" ? s0.left : d.right;\n const mids = shown.map((p) => centre(l0.items.get(panelKey(p))!.rect).y);\n const x = side === \"left\" ? RAIL : W - RAIL - DOCK;\n for (let i = 0; i <= shown.length; i++) {\n const [y0, y1] = slotSpan(mids, 0, d.h, i);\n // Past the side list (the bottom dock is off and its panels show here): into the bottom list.\n const state = i <= s0[side].length ? { ...s0, [side]: insert(s0[side], i, id) } : { ...s0, bottom: insert(s0.bottom, i - s0[side].length, id) };\n out.push({ id: `dock:${side}:${i}`, priority: 2, hit: rect(x, y0, DOCK, y1 - y0), make: fixed(touch(state, id), `${Cap(side)} dock · slot ${i + 1}`) });\n }\n }\n if (opt.bottom !== \"off\") {\n const b = d.bottomRect ?? rect(d.x0, H - 40 - G, d.x1 - d.x0, 40);\n const mids = s0.bottom.map((p) => centre(l0.items.get(panelKey(p))!.rect).x);\n for (let i = 0; i <= s0.bottom.length; i++) {\n const [x0, x1] = slotSpan(mids, b.x, b.x + b.width, i);\n out.push({ id: `bottom:${i}`, priority: 2, hit: rect(x0, b.y - 24, x1 - x0, H - b.y + 24), make: fixed(touch({ ...s0, bottom: insert(s0.bottom, i, id) }, id), `Bottom dock · slot ${i + 1}`) });\n }\n }\n if (c.id === \"dockTear\") {\n // Torn off, floating where it is dropped; snapped to the documents' edges, kept on the stage.\n out.push({\n id: \"float\",\n priority: 3,\n free: true,\n hit: rect(d.x0, 0, d.x1 - d.x0, H),\n make: (p, grab) => {\n let x = p.x - grab.x;\n let y = p.y - grab.y;\n if (Math.abs(x - d.x0) < SNAP) x = d.x0;\n if (Math.abs(x + TORN_W - d.x1) < SNAP) x = d.x1 - TORN_W;\n if (Math.abs(y - G) < SNAP) y = G;\n x = clamp(x, 0, W - TORN_W);\n y = clamp(y, 0, H - Math.min(cat.natural(id), H));\n return { state: touch({ ...s0, torn: [...s0.torn, { id, at: { x, y } }] }, id), label: \"Float here\", key: `float:${Math.round(x)},${Math.round(y)}` };\n },\n });\n }\n return out;\n}\n\n// --- tiling tree ---------------------------------------------------------------------------------------------------\n\n/**\n * The tree's targets are the slots an insertion produces: inserting at place i of a side column gives row i of its\n * n + 1 rows, inserting at place i of the centre gives dwindle's region i of n + 1. Those regions tile the column and\n * the centre, so a zone is where the item lands (unless that makes the newest tile float, which reshapes the rest);\n * the label says where it lands in the tree as laid out, and what floats.\n */\nfunction treeTargets({ c, s0, key, size }: DeskTargetInput): DeskTarget[] {\n const cat = c.desk.catalog;\n const out: DeskTarget[] = [];\n const area = treeArea(size, s0);\n // The tree as tiled: a column folded to its rail offers its rail instead of its rows.\n const t = treeShown(s0);\n const rails = treeRails(s0);\n // A side column is narrower than a document's minimum: a document dropped into one would only float.\n const sides = !isDocKey(key);\n for (const [side, group] of [[\"left\", \"L\"], [\"right\", \"R\"]] as const) {\n if (!sides || !rails[side]) continue;\n const hit = rect(side === \"left\" ? 0 : size.width - RAIL, BAR, RAIL, size.height - BAR);\n out.push({ id: `rail:${side}`, priority: 1, hit, make: fixed({ ...s0, tree: { ...s0.tree, [group]: [...s0.tree[group], key] } }, `${Cap(side)} rail: into the ${side} column`) });\n }\n if (sides && s0.tree.L.length === 0) out.push({ id: \"edge:L\", priority: 2, hit: rect(area.x, area.y, 30, area.height), make: fixed({ ...s0, tree: { ...s0.tree, L: [key] } }, \"New left column\") });\n if (sides && s0.tree.R.length === 0) out.push({ id: \"edge:R\", priority: 2, hit: rect(area.x + area.width - 30, area.y, 30, area.height), make: fixed({ ...s0, tree: { ...s0.tree, R: [key] } }, \"New right column\") });\n const x0 = area.x + (t.L.length ? TREE_COLUMN + G : 0);\n const x1 = area.x + area.width - (t.R.length ? TREE_COLUMN + G : 0);\n const middle = rect(x0, area.y, x1 - x0, area.height);\n const NAME = { L: \"Left column\", R: \"Right column\", C: \"Centre\" } as const;\n const seen: { label: string; hit: Rect }[] = [];\n const sameZone = (a: Rect, b: Rect): boolean => Math.max(Math.abs(a.x - b.x), Math.abs(a.y - b.y), Math.abs(a.width - b.width), Math.abs(a.height - b.height)) < 0.5;\n for (const group of [\"L\", \"R\", \"C\"] as const) {\n const list = t[group];\n if (group !== \"C\" && list.length === 0) continue;\n if (group !== \"C\" && !sides) continue;\n for (let i = 0; i <= list.length; i++) {\n const state = { ...s0, tree: { ...s0.tree, [group]: insert(list, i, key) } };\n const shown = treeShown(state);\n // The slot as laid out once the tiles that break a minimum have floated (as laid out without them if it floats).\n const tiled = treeFloats(cat, shown, area);\n const zone = treeTiles(cat, tiled.floats.includes(key) ? shown : tiled.tree, area).get(key)!;\n const label = `${NAME[group]}, ${landing(c, shown, area, key, group, middle)}`;\n // Places that come out the same (around a floating tile) are one target: the keyboard stops there once.\n if (seen.some((o) => o.label === label && sameZone(o.hit, zone))) continue;\n seen.push({ label, hit: zone });\n out.push({ id: `tile:${group}:${i}`, priority: 2, hit: zone, make: fixed(state, label) });\n }\n }\n return out;\n}\n\n/**\n * Where `key` lands in the tree as laid out (after the newest tiles that break a minimum float): its row of its\n * column, or its region of the centre; or that it floats, or what floats because of it.\n */\nfunction landing(c: Construction, tree: DeskState[\"tree\"], area: Rect, key: string, group: \"L\" | \"R\" | \"C\", middle: Rect): string {\n const cat = c.desk.catalog;\n const { tree: tiled, floats } = treeFloats(cat, tree, area);\n if (floats.includes(key)) return \"it floats there (too small)\";\n const others = floats.length ? `; ${floats.map(cat.title).join(\", \")} ${floats.length > 1 ? \"float\" : \"floats\"}` : \"\";\n if (group !== \"C\") return `row ${tiled[group].indexOf(key) + 1} of ${tiled[group].length}${others}`;\n const x0 = tiled.L.length ? middle.x : area.x;\n const x1 = tiled.R.length ? middle.x + middle.width : area.x + area.width;\n return `${regionName(treeTiles(cat, tiled, area).get(key)!, rect(x0, area.y, x1 - x0, area.height))}${others}`;\n}\n\n/** Where a region lies in `whole`, in words: \"all of it\", \"left half\", \"top right\"… */\nfunction regionName(r: Rect, whole: Rect): string {\n const near = (a: number, b: number): boolean => Math.abs(a - b) < 1;\n const h = near(r.width, whole.width) ? \"\" : near(r.x, whole.x) ? \"left\" : near(r.x + r.width, whole.x + whole.width) ? \"right\" : \"middle\";\n const v = near(r.height, whole.height) ? \"\" : near(r.y, whole.y) ? \"top\" : near(r.y + r.height, whole.y + whole.height) ? \"bottom\" : \"middle\";\n if (!h && !v) return \"all of it\";\n if (!v) return `${h} part`;\n if (!h) return `${v} part`;\n return `${v} ${h}`;\n}\n\n// --- scrolling strip -----------------------------------------------------------------------------------------------\n\nfunction stripTargets({ c, s0, key, size, opt }: DeskTargetInput): DeskTarget[] {\n const cat = c.desk.catalog;\n const out: DeskTarget[] = [];\n const g = stripGeometry(cat, s0, size);\n const l0 = c.layout(s0, size, opt);\n // The laid-out columns, each with the state column it comes from and where in it it starts.\n const parts: { owner: number; start: number; keys: string[] }[] = [];\n s0.cols.forEach((col, owner) => {\n let start = 0;\n for (const keys of stripColumns(cat, [col], g.h)) {\n parts.push({ owner, start, keys });\n start += keys.length;\n }\n });\n const newColumn = (at: number, label: string): Made => ({ state: { ...s0, cols: insert(s0.cols, at, [key]) }, label, key: label });\n if (parts.length === 0) return [{ id: \"strip\", priority: 3, hit: rect(0, g.y, size.width, g.h), make: () => newColumn(0, \"The strip\") }];\n // Between columns: a band across each boundary where a state column starts or ends.\n for (let k = 0; k <= parts.length; k++) {\n if (k < parts.length && parts[k]!.start !== 0) continue;\n const x = k < parts.length ? g.xs[k]! - G / 2 : g.xs[parts.length - 1]! + g.widths[parts.length - 1]! + G / 2;\n const at = k < parts.length ? parts[k]!.owner : s0.cols.length;\n const label = k === 0 ? \"New column at the start\" : k === parts.length ? \"New column at the end\" : `New column before ${cat.title(parts[k]!.keys[0]!)}`;\n out.push({ id: `between:${at}`, priority: 2, hit: rect(x - 28, g.y, 56, g.h), make: () => newColumn(at, label) });\n }\n // Inside a column: each item's halves belong to the gaps above and below it.\n parts.forEach((part, k) => {\n const mids = part.keys.map((pk) => centre(l0.items.get(pk)!.rect).y);\n for (let j = 0; j <= part.keys.length; j++) {\n const [y0, y1] = slotSpan(mids, g.y, g.y + g.h, j);\n const at = part.start + j;\n const cols = s0.cols.map((col, ci) => (ci === part.owner ? insert(col, at, key) : col));\n const label = `Into the column with ${cat.title(s0.cols[part.owner]![0]!)} · ${at + 1}`;\n out.push({ id: `into:${part.owner}:${at}`, priority: 2, hit: rect(g.xs[k]!, y0, g.widths[k]!, y1 - y0), make: fixed({ ...s0, cols }, label) });\n }\n });\n return out;\n}\n\n// --- navigator and drawers -----------------------------------------------------------------------------------------\n\nfunction tabTargets({ c, s0, key, size, opt }: DeskTargetInput): DeskTarget[] {\n const out: DeskTarget[] = [];\n const id = idOf(key);\n const l0 = c.layout(s0, size, opt);\n const onSide = (side: Side, i: number): DeskState => touch({ ...s0, [side]: insert(s0[side], i, id), active: { ...s0.active, [side]: id } }, id);\n for (const side of [\"left\", \"right\"] as const) {\n const list = s0[side];\n const tabs = l0.items.get(`tabs:${side}`);\n const railed = l0.items.get(`rail:${side}`);\n if (tabs && !tabs.hidden) {\n const r = tabs.rect;\n const tw = r.width / (list.length + 1);\n out.push({\n id: `tabs:${side}`,\n priority: 1,\n hit: rect(r.x, r.y - 4, r.width, r.height + 8),\n make: (p) => {\n const i = clamp(Math.floor((p.x - r.x) / tw), 0, list.length);\n const label = `${Cap(side)} tab strip · tab ${i + 1}`;\n return { state: onSide(side, i), label, key: label };\n },\n stops: Array.from({ length: list.length + 1 }, (_, i) => ({ x: r.x + tw * (i + 0.5), y: r.y + r.height / 2 })),\n });\n const panel = list.map((p) => l0.items.get(panelKey(p))).find((pl) => pl && !pl.hidden);\n if (panel) out.push({ id: `side:${side}`, priority: 3, hit: panel.rect, make: fixed(onSide(side, list.length), `${Cap(side)} side`) });\n }\n if (railed && !railed.hidden) out.push({ id: `rail:${side}`, priority: 1, hit: railed.rect, make: fixed(onSide(side, list.length), `${Cap(side)} rail`) });\n if (list.length === 0 && (!railed || railed.hidden)) {\n const hit = side === \"left\" ? rect(0, 0, 40, size.height) : rect(size.width - 40, 0, 40, size.height);\n out.push({ id: `edge:${side}`, priority: 2, hit, make: fixed(onSide(side, 0), `${Cap(side)} side`) });\n }\n }\n return out;\n}\n\n// --- palettes ------------------------------------------------------------------------------------------------------\n\nfunction paletteTargets({ c, s0, key, size, opt }: DeskTargetInput): DeskTarget[] {\n const cat = c.desk.catalog;\n const out: DeskTarget[] = [];\n const id = idOf(key);\n const { area } = paletteArea(size, opt);\n const m = c.id === \"floatOver\" ? OVER_MARGIN : 0;\n const pw = paletteWidth(size.width);\n const ph = s0.folded.includes(id) ? TITLE : cat.natural(id);\n const narrow = size.width < PALETTE_NARROW;\n const anchor = { left: area.x + m, right: area.x + area.width - m - pw };\n const l0 = c.layout(s0, size, opt);\n const rectOf = (pid: number): Rect => l0.items.get(panelKey(pid))!.rect;\n const tb = l0.items.get(\"toolbar\");\n const pillRect = tb?.look === \"pill\" ? tb.rect : null;\n // A corner stack's column, down to just under its last palette: it joins the stack at the place under the pointer.\n for (const side of narrow ? ([\"right\"] as const) : ([\"left\", \"right\"] as const)) {\n const ids = narrow ? [...s0.stacks.left, ...s0.stacks.right] : [...s0.stacks[side]];\n const bottom = ids.length ? Math.max(...ids.map((pid) => rectOf(pid).y + rectOf(pid).height)) : area.y + m;\n const at = (y: number): number => ids.filter((pid) => centre(rectOf(pid)).y < y).length;\n const join = (i: number): Made => {\n let stacks = s0.stacks;\n if (!narrow) stacks = { ...stacks, [side]: insert(stacks[side], i, id) };\n else if (i <= s0.stacks.left.length) stacks = { ...stacks, left: insert(stacks.left, i, id) };\n else stacks = { ...stacks, right: insert(stacks.right, i - s0.stacks.left.length, id) };\n const label = `${narrow ? \"The\" : Cap(side)} corner stack · ${i + 1}`;\n return { state: touch({ ...s0, stacks }, id), label, key: label };\n };\n out.push({\n id: `stack:${side}`,\n priority: 2,\n hit: rect(anchor[side], area.y, pw, bottom + 30 - area.y),\n make: (p) => join(at(p.y)),\n stops: [area.y + m, ...ids.map((pid) => rectOf(pid).y + rectOf(pid).height + G / 2)].map((y) => ({ x: anchor[side] + pw / 2, y })),\n });\n }\n // Anywhere: snapped to the area's edges (over the documents also to other palettes' edges), kept inside the area.\n out.push({\n id: \"free\",\n priority: 3,\n free: true,\n hit: area,\n make: (p, grab) => {\n let x = p.x - grab.x;\n let y = p.y - grab.y;\n const snaps: string[] = [];\n if (Math.abs(x - anchor.left) < SNAP) [x, snaps[0]] = [anchor.left, \"left edge\"];\n else if (Math.abs(x - anchor.right) < SNAP) [x, snaps[0]] = [anchor.right, \"right edge\"];\n if (Math.abs(y - (area.y + m)) < SNAP) [y, snaps[1]] = [area.y + m, \"top\"];\n else if (Math.abs(y + ph - (area.y + area.height - m)) < SNAP) [y, snaps[1]] = [area.y + area.height - m - ph, \"bottom\"];\n if (c.id === \"floatOver\") {\n for (const [k, pl] of l0.items) {\n if (!isPanelKey(k) || pl.hidden) continue;\n const o = pl.rect;\n if (snaps[0] === undefined && Math.abs(x - o.x) < SNAP) [x, snaps[0]] = [o.x, `${cat.title(k)}'s edge`];\n if (snaps[1] === undefined && Math.abs(y - (o.y + o.height + G)) < SNAP && x < o.x + o.width && x + pw > o.x) [y, snaps[1]] = [o.y + o.height + G, `under ${cat.title(k)}`];\n }\n }\n x = clamp(x, area.x, area.x + area.width - pw);\n y = clamp(y, area.y, area.y + area.height - ph);\n // Never under a floating pill: it moves clear, below a pill at the top, above one at the bottom.\n if (pillRect && overlap(rect(x, y, pw, ph), pillRect) > 0) {\n y = pillRect.y < size.height / 2 ? pillRect.y + pillRect.height + G : pillRect.y - G - ph;\n y = clamp(y, 0, size.height - ph);\n snaps[1] = \"clear of the toolbar\";\n }\n const how = snaps.filter(Boolean).join(\", \");\n return { state: touch({ ...s0, free: [...s0.free, { id, at: { x, y } }] }, id), label: how ? `Here · snapped to the ${how}` : \"Here\", key: `free:${Math.round(x)},${Math.round(y)}` };\n },\n });\n return out;\n}\n\n/** The drop targets for dragging `key` in construction `c`, in a fixed order (the keyboard's). */\nexport function deskTargets(input: DeskTargetInput): DeskTarget[] {\n switch (input.c.id) {\n case \"docks\":\n case \"docksFull\":\n case \"dockTear\":\n return dockTargets(input);\n case \"tree\":\n return treeTargets(input);\n case \"strip\":\n return stripTargets(input);\n case \"navigator\":\n case \"drawers\":\n return tabTargets(input);\n case \"floatOver\":\n case \"floatAround\":\n return paletteTargets(input);\n }\n}\n\n/** A target's drop for a pointer at `p` holding the item at `grab`, laid out: where the item lands. */\nexport function deskDrop(input: DeskTargetInput, target: DeskTarget, p: Point, grab: Point): DeskDrop {\n const made = target.make(p, grab);\n const layout = input.c.layout(made.state, input.size, input.opt);\n const placed = layout.items.get(input.key)!;\n return { ...made, key: `${target.id}|${made.key}`, target: target.id, layout, slot: placed.rect, hidden: !!placed.hidden, free: !!target.free };\n}\n","/**\n * Toolbar group targets: a host's insertion points (lines between groups, priority 2) and empty zones (priority 1),\n * and floating over the content (priority 3). A group's own place is home, never a target: its stretch comes back\n * in `own`, for the consumer to join to the drag's home.\n */\nimport { rect, type Point, type Rect } from \"../geometry\";\nimport { ZONES, floatGroup, insertGroup, insertions, isOwnPlace, layoutHost, vertical, withoutGroup, type Arrangement, type GroupSize, type HostId, type HostSpec, type Place } from \"../toolbar\";\nimport type { Target } from \"./target\";\n\n/** How far a line's hit reaches beyond the host's thickness on each side; an empty zone's. */\nexport const LINE_REACH = 12;\nexport const ZONE_REACH = 4;\n\nexport interface ToolbarTarget<G extends string = string> extends Target {\n readonly label: string;\n readonly kind: \"line\" | \"zone\";\n readonly place: Place;\n /** It lands in a side edge's column. */\n readonly vertical: boolean;\n /** The insertion line (3 px, inset 4 px from the host's sides) in stage coordinates; for an empty zone, at its middle. */\n readonly line: Rect;\n /** The arrangement a drop here makes. */\n readonly arrangement: Arrangement<G>;\n}\n\nexport interface HostTargetsInput<G extends string> {\n readonly group: G;\n /** The arrangement as it is, the group still in its place. */\n readonly arrangement: Arrangement<G>;\n readonly host: HostId;\n /** The host's top-left corner in stage coordinates. */\n readonly origin: Point;\n readonly spec: HostSpec;\n readonly size: GroupSize<G>;\n /** A group's name in the labels (default: its id). */\n readonly label?: (g: G) => string;\n}\n\n/** The targets a host offers a dragged group, zone by zone in order, and the stretches that are its own place. */\nexport function hostTargets<G extends string>(input: HostTargetsInput<G>): { targets: ToolbarTarget<G>[]; own: Rect[] } {\n const { group, arrangement: a, host: h, origin: o, spec } = input;\n const a0 = withoutGroup(a, group);\n const l = layoutHost(a0[h], h, spec, input.size, a0.collapsed);\n const v = vertical(h);\n const T = spec.thickness;\n const across = (s0: number, s1: number, reach: number): Rect => (v ? rect(o.x - reach, o.y + s0, T + 2 * reach, s1 - s0) : rect(o.x + s0, o.y - reach, s1 - s0, T + 2 * reach));\n const targets: ToolbarTarget<G>[] = [];\n const own: Rect[] = [];\n const pts = insertions(a0[h], h, spec, l, input.label).sort((p, q) => ZONES.indexOf(p.zone) - ZONES.indexOf(q.zone) || p.index - q.index);\n for (const p of pts) {\n const [s0, s1] = p.span;\n const place: Place = { host: h, zone: p.zone, index: p.index };\n if (isOwnPlace(a, group, place)) {\n own.push(across(s0, s1, LINE_REACH));\n continue;\n }\n targets.push({\n id: `g:${h}:${p.zone}:${p.index}`,\n priority: p.empty ? 1 : 2,\n hit: p.empty ? across(s0, s1, ZONE_REACH) : across(s0, s1, LINE_REACH),\n label: p.label,\n kind: p.empty ? \"zone\" : \"line\",\n place,\n vertical: v,\n line: v ? rect(o.x + 4, o.y + p.at - 1.5, T - 8, 3) : rect(o.x + p.at - 1.5, o.y + 4, 3, T - 8),\n arrangement: insertGroup(a, group, h, p.zone, p.index),\n });\n }\n return { targets, own };\n}\n\nexport interface ToolbarFloatTarget<G extends string = string> extends Target {\n readonly label: string;\n readonly kind: \"float\";\n /** The group's top-left corner relative to the stage, and the arrangement, for a drop with the pointer at `p`. */\n readonly make: (p: Point, grab: Point) => Arrangement<G>;\n}\n\n/** Floating over the content (`stage`, in stage coordinates): the group's top-left corner kept on the stage. */\nexport function floatTarget<G extends string>(input: { readonly group: G; readonly arrangement: Arrangement<G>; readonly stage: Rect; readonly width: number; readonly height: number }): ToolbarFloatTarget<G> {\n const { group, arrangement, stage } = input;\n return {\n id: \"g:float\",\n priority: 3,\n free: true,\n hit: stage,\n label: \"Float here\",\n kind: \"float\",\n // Kept on the stage; a group larger than the stage keeps its top-left corner on the stage's.\n make: (p, grab) => {\n const x = Math.max(0, Math.min(p.x - grab.x - stage.x, stage.width - input.width));\n const y = Math.max(0, Math.min(p.y - grab.y - stage.y, stage.height - input.height));\n return floatGroup(arrangement, group, x, y);\n },\n };\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/targets/desk.ts","../src/targets/toolbar.ts","../src/targets/zones.ts"],"sourcesContent":["/**\n * Each desk construction's drop targets, as pure functions: from the state with the dragged item lifted out, a list\n * of zones with a priority, each able to make the state with the item dropped there.\n *\n * - Edge docks (`docks`, `docksFull`, `dockTear`): a rail (priority 1) takes the panel at the end of its dock (a\n * folded dock keeps it in the rail); a slot between sections (2) and the bottom dock (2) take it at that place;\n * with tear-off, the documents area (3) tears it off to float there.\n * - Tiling tree (`tree`): each slot an insertion produces (2), a side column's row or a dwindle region of the\n * centre; an empty side column's edge (2).\n * - Strip (`strip`): between two columns (2) makes a new column; a gap inside a column (2) puts it there.\n * - Navigator, drawers (`navigator`, `drawers`): a tab strip (1) at the tab under the pointer, a folded side's rail\n * (1), a side's panel (3); the panel becomes the side's showing one.\n * - Palettes (`floatOver`, `floatAround`): a corner stack's column (2) at the place under the pointer; anywhere\n * else in the area (3), snapped to the area's edges (over the documents, also to other palettes' edges).\n */\nimport { centre, overlap, rect, type Point, type Rect, type Size } from \"../geometry\";\nimport type { Construction } from \"../dock/constructions\";\nimport { BAR, G, RAIL, TITLE, idOf, isDocKey, isPanelKey, panelKey, touch, type DeskState, type Layout, type Options, type Side } from \"../dock/model\";\nimport {\n DOCK,\n OVER_MARGIN,\n PALETTE_NARROW,\n TORN_W,\n TREE_COLUMN,\n dockGeometry,\n paletteArea,\n paletteWidth,\n stripColumns,\n stripGeometry,\n treeArea,\n treeFloats,\n treeRails,\n treeShown,\n treeTiles,\n} from \"../dock/parts\";\nimport type { Target } from \"./target\";\n\n/** A target's drop for a pointer: the state with the item there, a label, and a key (same key, same place). */\nexport interface Made {\n readonly state: DeskState;\n readonly label: string;\n readonly key: string;\n}\n\nexport interface DeskTarget extends Target {\n /** The drop with the pointer at `p`, holding the item at `grab` from its top-left corner. */\n readonly make: (p: Point, grab: Point) => Made;\n /** Where the keyboard stops in this target, in order (default: its zone's centre). */\n readonly stops?: readonly Point[];\n}\n\n/** A made drop, laid out. */\nexport interface DeskDrop extends Made {\n readonly target: string;\n readonly layout: Layout;\n /** Where the item lands. */\n readonly slot: Rect;\n /** It lands hidden (folded into a rail). */\n readonly hidden: boolean;\n /** It floats where it is dropped: no room is made for it. */\n readonly free: boolean;\n}\n\nexport interface DeskTargetInput {\n readonly c: Construction;\n /** The state with the dragged item lifted out (`liftOut`). */\n readonly s0: DeskState;\n readonly key: string;\n readonly size: Size;\n readonly opt: Options;\n}\n\n/** How close (stage px) a free drop has to come to an edge to snap to it. */\nexport const SNAP = 18;\n\nconst insert = <T>(list: readonly T[], i: number, x: T): T[] => [...list.slice(0, i), x, ...list.slice(i)];\nconst clamp = (v: number, lo: number, hi: number): number => Math.min(Math.max(v, lo), Math.max(lo, hi));\nconst Cap = (s: Side): string => (s === \"left\" ? \"Left\" : \"Right\");\nconst fixed = (state: DeskState, label: string) => (): Made => ({ state, label, key: label });\n\n/** Zones `count + 1` slots split between items at `mids` (their centres), from `lo` to `hi`: slot i's span. */\nconst slotSpan = (mids: readonly number[], lo: number, hi: number, i: number): [number, number] => [i === 0 ? lo : mids[i - 1]!, i === mids.length ? hi : mids[i]!];\n\n// --- edge docks ----------------------------------------------------------------------------------------------------\n\nfunction dockTargets({ c, s0, key, size, opt }: DeskTargetInput): DeskTarget[] {\n const cat = c.desk.catalog;\n const out: DeskTarget[] = [];\n const id = idOf(key);\n const mode = c.id === \"docksFull\" ? \"full\" : \"between\";\n const d = dockGeometry(cat, s0, size, opt, mode);\n const l0 = c.layout(s0, size, opt);\n const W = size.width;\n const H = size.height;\n for (const side of [\"left\", \"right\"] as const) {\n const railed = l0.items.get(`rail:${side}`);\n if (!railed) continue;\n const label = `${Cap(side)} rail: into the ${side} dock`;\n out.push({ id: `rail:${side}`, priority: 1, hit: railed.rect, make: fixed(touch({ ...s0, [side]: [...s0[side], id] }, id), label) });\n if (side === \"left\" ? !d.lOpen : !d.rOpen) continue;\n // The dock's slots: each section's halves belong to the slots above and below it.\n const shown = side === \"left\" ? s0.left : d.right;\n const mids = shown.map((p) => centre(l0.items.get(panelKey(p))!.rect).y);\n const x = side === \"left\" ? RAIL : W - RAIL - DOCK;\n for (let i = 0; i <= shown.length; i++) {\n const [y0, y1] = slotSpan(mids, 0, d.h, i);\n // Past the side list (the bottom dock is off and its panels show here): into the bottom list.\n const state = i <= s0[side].length ? { ...s0, [side]: insert(s0[side], i, id) } : { ...s0, bottom: insert(s0.bottom, i - s0[side].length, id) };\n out.push({ id: `dock:${side}:${i}`, priority: 2, hit: rect(x, y0, DOCK, y1 - y0), make: fixed(touch(state, id), `${Cap(side)} dock · slot ${i + 1}`) });\n }\n }\n if (opt.bottom !== \"off\") {\n const b = d.bottomRect ?? rect(d.x0, H - 40 - G, d.x1 - d.x0, 40);\n const mids = s0.bottom.map((p) => centre(l0.items.get(panelKey(p))!.rect).x);\n for (let i = 0; i <= s0.bottom.length; i++) {\n const [x0, x1] = slotSpan(mids, b.x, b.x + b.width, i);\n out.push({ id: `bottom:${i}`, priority: 2, hit: rect(x0, b.y - 24, x1 - x0, H - b.y + 24), make: fixed(touch({ ...s0, bottom: insert(s0.bottom, i, id) }, id), `Bottom dock · slot ${i + 1}`) });\n }\n }\n if (c.id === \"dockTear\") {\n // Torn off, floating where it is dropped; snapped to the documents' edges, kept on the stage.\n out.push({\n id: \"float\",\n priority: 3,\n free: true,\n hit: rect(d.x0, 0, d.x1 - d.x0, H),\n make: (p, grab) => {\n let x = p.x - grab.x;\n let y = p.y - grab.y;\n if (Math.abs(x - d.x0) < SNAP) x = d.x0;\n if (Math.abs(x + TORN_W - d.x1) < SNAP) x = d.x1 - TORN_W;\n if (Math.abs(y - G) < SNAP) y = G;\n x = clamp(x, 0, W - TORN_W);\n y = clamp(y, 0, H - Math.min(cat.natural(id), H));\n return { state: touch({ ...s0, torn: [...s0.torn, { id, at: { x, y } }] }, id), label: \"Float here\", key: `float:${Math.round(x)},${Math.round(y)}` };\n },\n });\n }\n return out;\n}\n\n// --- tiling tree ---------------------------------------------------------------------------------------------------\n\n/**\n * The tree's targets are the slots an insertion produces: inserting at place i of a side column gives row i of its\n * n + 1 rows, inserting at place i of the centre gives dwindle's region i of n + 1. Those regions tile the column and\n * the centre, so a zone is where the item lands (unless that makes the newest tile float, which reshapes the rest);\n * the label says where it lands in the tree as laid out, and what floats.\n */\nfunction treeTargets({ c, s0, key, size }: DeskTargetInput): DeskTarget[] {\n const cat = c.desk.catalog;\n const out: DeskTarget[] = [];\n const area = treeArea(size, s0);\n // The tree as tiled: a column folded to its rail offers its rail instead of its rows.\n const t = treeShown(s0);\n const rails = treeRails(s0);\n // A side column is narrower than a document's minimum: a document dropped into one would only float.\n const sides = !isDocKey(key);\n for (const [side, group] of [[\"left\", \"L\"], [\"right\", \"R\"]] as const) {\n if (!sides || !rails[side]) continue;\n const hit = rect(side === \"left\" ? 0 : size.width - RAIL, BAR, RAIL, size.height - BAR);\n out.push({ id: `rail:${side}`, priority: 1, hit, make: fixed({ ...s0, tree: { ...s0.tree, [group]: [...s0.tree[group], key] } }, `${Cap(side)} rail: into the ${side} column`) });\n }\n if (sides && s0.tree.L.length === 0) out.push({ id: \"edge:L\", priority: 2, hit: rect(area.x, area.y, 30, area.height), make: fixed({ ...s0, tree: { ...s0.tree, L: [key] } }, \"New left column\") });\n if (sides && s0.tree.R.length === 0) out.push({ id: \"edge:R\", priority: 2, hit: rect(area.x + area.width - 30, area.y, 30, area.height), make: fixed({ ...s0, tree: { ...s0.tree, R: [key] } }, \"New right column\") });\n const x0 = area.x + (t.L.length ? TREE_COLUMN + G : 0);\n const x1 = area.x + area.width - (t.R.length ? TREE_COLUMN + G : 0);\n const middle = rect(x0, area.y, x1 - x0, area.height);\n const NAME = { L: \"Left column\", R: \"Right column\", C: \"Centre\" } as const;\n const seen: { label: string; hit: Rect }[] = [];\n const sameZone = (a: Rect, b: Rect): boolean => Math.max(Math.abs(a.x - b.x), Math.abs(a.y - b.y), Math.abs(a.width - b.width), Math.abs(a.height - b.height)) < 0.5;\n for (const group of [\"L\", \"R\", \"C\"] as const) {\n const list = t[group];\n if (group !== \"C\" && list.length === 0) continue;\n if (group !== \"C\" && !sides) continue;\n for (let i = 0; i <= list.length; i++) {\n const state = { ...s0, tree: { ...s0.tree, [group]: insert(list, i, key) } };\n const shown = treeShown(state);\n // The slot as laid out once the tiles that break a minimum have floated (as laid out without them if it floats).\n const tiled = treeFloats(cat, shown, area);\n const zone = treeTiles(cat, tiled.floats.includes(key) ? shown : tiled.tree, area).get(key)!;\n const label = `${NAME[group]}, ${landing(c, shown, area, key, group, middle)}`;\n // Places that come out the same (around a floating tile) are one target: the keyboard stops there once.\n if (seen.some((o) => o.label === label && sameZone(o.hit, zone))) continue;\n seen.push({ label, hit: zone });\n out.push({ id: `tile:${group}:${i}`, priority: 2, hit: zone, make: fixed(state, label) });\n }\n }\n return out;\n}\n\n/**\n * Where `key` lands in the tree as laid out (after the newest tiles that break a minimum float): its row of its\n * column, or its region of the centre; or that it floats, or what floats because of it.\n */\nfunction landing(c: Construction, tree: DeskState[\"tree\"], area: Rect, key: string, group: \"L\" | \"R\" | \"C\", middle: Rect): string {\n const cat = c.desk.catalog;\n const { tree: tiled, floats } = treeFloats(cat, tree, area);\n if (floats.includes(key)) return \"it floats there (too small)\";\n const others = floats.length ? `; ${floats.map(cat.title).join(\", \")} ${floats.length > 1 ? \"float\" : \"floats\"}` : \"\";\n if (group !== \"C\") return `row ${tiled[group].indexOf(key) + 1} of ${tiled[group].length}${others}`;\n const x0 = tiled.L.length ? middle.x : area.x;\n const x1 = tiled.R.length ? middle.x + middle.width : area.x + area.width;\n return `${regionName(treeTiles(cat, tiled, area).get(key)!, rect(x0, area.y, x1 - x0, area.height))}${others}`;\n}\n\n/** Where a region lies in `whole`, in words: \"all of it\", \"left half\", \"top right\"… */\nfunction regionName(r: Rect, whole: Rect): string {\n const near = (a: number, b: number): boolean => Math.abs(a - b) < 1;\n const h = near(r.width, whole.width) ? \"\" : near(r.x, whole.x) ? \"left\" : near(r.x + r.width, whole.x + whole.width) ? \"right\" : \"middle\";\n const v = near(r.height, whole.height) ? \"\" : near(r.y, whole.y) ? \"top\" : near(r.y + r.height, whole.y + whole.height) ? \"bottom\" : \"middle\";\n if (!h && !v) return \"all of it\";\n if (!v) return `${h} part`;\n if (!h) return `${v} part`;\n return `${v} ${h}`;\n}\n\n// --- scrolling strip -----------------------------------------------------------------------------------------------\n\nfunction stripTargets({ c, s0, key, size, opt }: DeskTargetInput): DeskTarget[] {\n const cat = c.desk.catalog;\n const out: DeskTarget[] = [];\n const g = stripGeometry(cat, s0, size);\n const l0 = c.layout(s0, size, opt);\n // The laid-out columns, each with the state column it comes from and where in it it starts.\n const parts: { owner: number; start: number; keys: string[] }[] = [];\n s0.cols.forEach((col, owner) => {\n let start = 0;\n for (const keys of stripColumns(cat, [col], g.h)) {\n parts.push({ owner, start, keys });\n start += keys.length;\n }\n });\n const newColumn = (at: number, label: string): Made => ({ state: { ...s0, cols: insert(s0.cols, at, [key]) }, label, key: label });\n if (parts.length === 0) return [{ id: \"strip\", priority: 3, hit: rect(0, g.y, size.width, g.h), make: () => newColumn(0, \"The strip\") }];\n // Between columns: a band across each boundary where a state column starts or ends.\n for (let k = 0; k <= parts.length; k++) {\n if (k < parts.length && parts[k]!.start !== 0) continue;\n const x = k < parts.length ? g.xs[k]! - G / 2 : g.xs[parts.length - 1]! + g.widths[parts.length - 1]! + G / 2;\n const at = k < parts.length ? parts[k]!.owner : s0.cols.length;\n const label = k === 0 ? \"New column at the start\" : k === parts.length ? \"New column at the end\" : `New column before ${cat.title(parts[k]!.keys[0]!)}`;\n out.push({ id: `between:${at}`, priority: 2, hit: rect(x - 28, g.y, 56, g.h), make: () => newColumn(at, label) });\n }\n // Inside a column: each item's halves belong to the gaps above and below it.\n parts.forEach((part, k) => {\n const mids = part.keys.map((pk) => centre(l0.items.get(pk)!.rect).y);\n for (let j = 0; j <= part.keys.length; j++) {\n const [y0, y1] = slotSpan(mids, g.y, g.y + g.h, j);\n const at = part.start + j;\n const cols = s0.cols.map((col, ci) => (ci === part.owner ? insert(col, at, key) : col));\n const label = `Into the column with ${cat.title(s0.cols[part.owner]![0]!)} · ${at + 1}`;\n out.push({ id: `into:${part.owner}:${at}`, priority: 2, hit: rect(g.xs[k]!, y0, g.widths[k]!, y1 - y0), make: fixed({ ...s0, cols }, label) });\n }\n });\n return out;\n}\n\n// --- navigator and drawers -----------------------------------------------------------------------------------------\n\nfunction tabTargets({ c, s0, key, size, opt }: DeskTargetInput): DeskTarget[] {\n const out: DeskTarget[] = [];\n const id = idOf(key);\n const l0 = c.layout(s0, size, opt);\n const onSide = (side: Side, i: number): DeskState => touch({ ...s0, [side]: insert(s0[side], i, id), active: { ...s0.active, [side]: id } }, id);\n for (const side of [\"left\", \"right\"] as const) {\n const list = s0[side];\n const tabs = l0.items.get(`tabs:${side}`);\n const railed = l0.items.get(`rail:${side}`);\n if (tabs && !tabs.hidden) {\n const r = tabs.rect;\n const tw = r.width / (list.length + 1);\n out.push({\n id: `tabs:${side}`,\n priority: 1,\n hit: rect(r.x, r.y - 4, r.width, r.height + 8),\n make: (p) => {\n const i = clamp(Math.floor((p.x - r.x) / tw), 0, list.length);\n const label = `${Cap(side)} tab strip · tab ${i + 1}`;\n return { state: onSide(side, i), label, key: label };\n },\n stops: Array.from({ length: list.length + 1 }, (_, i) => ({ x: r.x + tw * (i + 0.5), y: r.y + r.height / 2 })),\n });\n const panel = list.map((p) => l0.items.get(panelKey(p))).find((pl) => pl && !pl.hidden);\n if (panel) out.push({ id: `side:${side}`, priority: 3, hit: panel.rect, make: fixed(onSide(side, list.length), `${Cap(side)} side`) });\n }\n if (railed && !railed.hidden) out.push({ id: `rail:${side}`, priority: 1, hit: railed.rect, make: fixed(onSide(side, list.length), `${Cap(side)} rail`) });\n if (list.length === 0 && (!railed || railed.hidden)) {\n const hit = side === \"left\" ? rect(0, 0, 40, size.height) : rect(size.width - 40, 0, 40, size.height);\n out.push({ id: `edge:${side}`, priority: 2, hit, make: fixed(onSide(side, 0), `${Cap(side)} side`) });\n }\n }\n return out;\n}\n\n// --- palettes ------------------------------------------------------------------------------------------------------\n\nfunction paletteTargets({ c, s0, key, size, opt }: DeskTargetInput): DeskTarget[] {\n const cat = c.desk.catalog;\n const out: DeskTarget[] = [];\n const id = idOf(key);\n const { area } = paletteArea(size, opt);\n const m = c.id === \"floatOver\" ? OVER_MARGIN : 0;\n const pw = paletteWidth(size.width);\n const ph = s0.folded.includes(id) ? TITLE : cat.natural(id);\n const narrow = size.width < PALETTE_NARROW;\n const anchor = { left: area.x + m, right: area.x + area.width - m - pw };\n const l0 = c.layout(s0, size, opt);\n const rectOf = (pid: number): Rect => l0.items.get(panelKey(pid))!.rect;\n const tb = l0.items.get(\"toolbar\");\n const pillRect = tb?.look === \"pill\" ? tb.rect : null;\n // A corner stack's column, down to just under its last palette: it joins the stack at the place under the pointer.\n for (const side of narrow ? ([\"right\"] as const) : ([\"left\", \"right\"] as const)) {\n const ids = narrow ? [...s0.stacks.left, ...s0.stacks.right] : [...s0.stacks[side]];\n const bottom = ids.length ? Math.max(...ids.map((pid) => rectOf(pid).y + rectOf(pid).height)) : area.y + m;\n const at = (y: number): number => ids.filter((pid) => centre(rectOf(pid)).y < y).length;\n const join = (i: number): Made => {\n let stacks = s0.stacks;\n if (!narrow) stacks = { ...stacks, [side]: insert(stacks[side], i, id) };\n else if (i <= s0.stacks.left.length) stacks = { ...stacks, left: insert(stacks.left, i, id) };\n else stacks = { ...stacks, right: insert(stacks.right, i - s0.stacks.left.length, id) };\n const label = `${narrow ? \"The\" : Cap(side)} corner stack · ${i + 1}`;\n return { state: touch({ ...s0, stacks }, id), label, key: label };\n };\n out.push({\n id: `stack:${side}`,\n priority: 2,\n hit: rect(anchor[side], area.y, pw, bottom + 30 - area.y),\n make: (p) => join(at(p.y)),\n stops: [area.y + m, ...ids.map((pid) => rectOf(pid).y + rectOf(pid).height + G / 2)].map((y) => ({ x: anchor[side] + pw / 2, y })),\n });\n }\n // Anywhere: snapped to the area's edges (over the documents also to other palettes' edges), kept inside the area.\n out.push({\n id: \"free\",\n priority: 3,\n free: true,\n hit: area,\n make: (p, grab) => {\n let x = p.x - grab.x;\n let y = p.y - grab.y;\n const snaps: string[] = [];\n if (Math.abs(x - anchor.left) < SNAP) [x, snaps[0]] = [anchor.left, \"left edge\"];\n else if (Math.abs(x - anchor.right) < SNAP) [x, snaps[0]] = [anchor.right, \"right edge\"];\n if (Math.abs(y - (area.y + m)) < SNAP) [y, snaps[1]] = [area.y + m, \"top\"];\n else if (Math.abs(y + ph - (area.y + area.height - m)) < SNAP) [y, snaps[1]] = [area.y + area.height - m - ph, \"bottom\"];\n if (c.id === \"floatOver\") {\n for (const [k, pl] of l0.items) {\n if (!isPanelKey(k) || pl.hidden) continue;\n const o = pl.rect;\n if (snaps[0] === undefined && Math.abs(x - o.x) < SNAP) [x, snaps[0]] = [o.x, `${cat.title(k)}'s edge`];\n if (snaps[1] === undefined && Math.abs(y - (o.y + o.height + G)) < SNAP && x < o.x + o.width && x + pw > o.x) [y, snaps[1]] = [o.y + o.height + G, `under ${cat.title(k)}`];\n }\n }\n x = clamp(x, area.x, area.x + area.width - pw);\n y = clamp(y, area.y, area.y + area.height - ph);\n // Never under a floating pill: it moves clear, below a pill at the top, above one at the bottom.\n if (pillRect && overlap(rect(x, y, pw, ph), pillRect) > 0) {\n y = pillRect.y < size.height / 2 ? pillRect.y + pillRect.height + G : pillRect.y - G - ph;\n y = clamp(y, 0, size.height - ph);\n snaps[1] = \"clear of the toolbar\";\n }\n const how = snaps.filter(Boolean).join(\", \");\n return { state: touch({ ...s0, free: [...s0.free, { id, at: { x, y } }] }, id), label: how ? `Here · snapped to the ${how}` : \"Here\", key: `free:${Math.round(x)},${Math.round(y)}` };\n },\n });\n return out;\n}\n\n/** The drop targets for dragging `key` in construction `c`, in a fixed order (the keyboard's). */\nexport function deskTargets(input: DeskTargetInput): DeskTarget[] {\n switch (input.c.id) {\n case \"docks\":\n case \"docksFull\":\n case \"dockTear\":\n return dockTargets(input);\n case \"tree\":\n return treeTargets(input);\n case \"strip\":\n return stripTargets(input);\n case \"navigator\":\n case \"drawers\":\n return tabTargets(input);\n case \"floatOver\":\n case \"floatAround\":\n return paletteTargets(input);\n }\n}\n\n/** A target's drop for a pointer at `p` holding the item at `grab`, laid out: where the item lands. */\nexport function deskDrop(input: DeskTargetInput, target: DeskTarget, p: Point, grab: Point): DeskDrop {\n const made = target.make(p, grab);\n const layout = input.c.layout(made.state, input.size, input.opt);\n const placed = layout.items.get(input.key)!;\n return { ...made, key: `${target.id}|${made.key}`, target: target.id, layout, slot: placed.rect, hidden: !!placed.hidden, free: !!target.free };\n}\n","/**\n * Toolbar group targets: a host's insertion points (lines between groups, priority 2) and empty zones (priority 1),\n * and floating over the content (priority 3). A group's own place is home, never a target: its stretch comes back\n * in `own`, for the consumer to join to the drag's home.\n */\nimport { rect, type Point, type Rect } from \"../geometry\";\nimport { ZONES, floatGroup, insertGroup, insertions, isOwnPlace, layoutHost, vertical, withoutGroup, type Arrangement, type GroupSize, type HostId, type HostSpec, type Place } from \"../toolbar\";\nimport type { Target } from \"./target\";\n\n/** How far a line's hit reaches beyond the host's thickness on each side; an empty zone's. */\nexport const LINE_REACH = 12;\nexport const ZONE_REACH = 4;\n\nexport interface ToolbarTarget<G extends string = string> extends Target {\n readonly label: string;\n readonly kind: \"line\" | \"zone\";\n readonly place: Place;\n /** It lands in a side edge's column. */\n readonly vertical: boolean;\n /** The insertion line (3 px, inset 4 px from the host's sides) in stage coordinates; for an empty zone, at its middle. */\n readonly line: Rect;\n /** The arrangement a drop here makes. */\n readonly arrangement: Arrangement<G>;\n}\n\nexport interface HostTargetsInput<G extends string> {\n readonly group: G;\n /** The arrangement as it is, the group still in its place. */\n readonly arrangement: Arrangement<G>;\n readonly host: HostId;\n /** The host's top-left corner in stage coordinates. */\n readonly origin: Point;\n readonly spec: HostSpec;\n readonly size: GroupSize<G>;\n /** A group's name in the labels (default: its id). */\n readonly label?: (g: G) => string;\n}\n\n/** The targets a host offers a dragged group, zone by zone in order, and the stretches that are its own place. */\nexport function hostTargets<G extends string>(input: HostTargetsInput<G>): { targets: ToolbarTarget<G>[]; own: Rect[] } {\n const { group, arrangement: a, host: h, origin: o, spec } = input;\n const a0 = withoutGroup(a, group);\n const l = layoutHost(a0[h], h, spec, input.size, a0.collapsed);\n const v = vertical(h);\n const T = spec.thickness;\n const across = (s0: number, s1: number, reach: number): Rect => (v ? rect(o.x - reach, o.y + s0, T + 2 * reach, s1 - s0) : rect(o.x + s0, o.y - reach, s1 - s0, T + 2 * reach));\n const targets: ToolbarTarget<G>[] = [];\n const own: Rect[] = [];\n const pts = insertions(a0[h], h, spec, l, input.label).sort((p, q) => ZONES.indexOf(p.zone) - ZONES.indexOf(q.zone) || p.index - q.index);\n for (const p of pts) {\n const [s0, s1] = p.span;\n const place: Place = { host: h, zone: p.zone, index: p.index };\n if (isOwnPlace(a, group, place)) {\n own.push(across(s0, s1, LINE_REACH));\n continue;\n }\n targets.push({\n id: `g:${h}:${p.zone}:${p.index}`,\n priority: p.empty ? 1 : 2,\n hit: p.empty ? across(s0, s1, ZONE_REACH) : across(s0, s1, LINE_REACH),\n label: p.label,\n kind: p.empty ? \"zone\" : \"line\",\n place,\n vertical: v,\n line: v ? rect(o.x + 4, o.y + p.at - 1.5, T - 8, 3) : rect(o.x + p.at - 1.5, o.y + 4, 3, T - 8),\n arrangement: insertGroup(a, group, h, p.zone, p.index),\n });\n }\n return { targets, own };\n}\n\nexport interface ToolbarFloatTarget<G extends string = string> extends Target {\n readonly label: string;\n readonly kind: \"float\";\n /** The group's top-left corner relative to the stage, and the arrangement, for a drop with the pointer at `p`. */\n readonly make: (p: Point, grab: Point) => Arrangement<G>;\n}\n\n/** Floating over the content (`stage`, in stage coordinates): the group's top-left corner kept on the stage. */\nexport function floatTarget<G extends string>(input: { readonly group: G; readonly arrangement: Arrangement<G>; readonly stage: Rect; readonly width: number; readonly height: number }): ToolbarFloatTarget<G> {\n const { group, arrangement, stage } = input;\n return {\n id: \"g:float\",\n priority: 3,\n free: true,\n hit: stage,\n label: \"Float here\",\n kind: \"float\",\n // Kept on the stage; a group larger than the stage keeps its top-left corner on the stage's.\n make: (p, grab) => {\n const x = Math.max(0, Math.min(p.x - grab.x - stage.x, stage.width - input.width));\n const y = Math.max(0, Math.min(p.y - grab.y - stage.y, stage.height - input.height));\n return floatGroup(arrangement, group, x, y);\n },\n };\n}\n","/**\n * A pane's drop zones: a centre rectangle (put it in the pane's place, merge or swap) and four edge trapezoids (put\n * it beside the pane on that side), formed by the diagonals from each pane corner to the nearest corner of the\n * centre. The five zones tile the pane with no gaps and no overlaps.\n *\n * Meant for `@n-uf/motion/drag`'s `placeOf(target, point, previous)`: one target per pane, its place the zone under\n * the pointer, the previous zone held for `hysteresis` px past its boundary so a pointer resting on a boundary\n * doesn't flicker. A zone that takes no drop is the consumer's to answer with a null place.\n */\nimport type { Point, Rect, Size } from \"../geometry\";\n\nexport type PaneZone = \"center\" | \"top\" | \"right\" | \"bottom\" | \"left\";\n\n/** The edge zones in their tie-break order: at an exact diagonal the first wins (a corner resolves to `top`). */\nexport const PANE_EDGES: readonly Exclude<PaneZone, \"center\">[] = [\"top\", \"right\", \"bottom\", \"left\"];\n\nexport interface PaneZoneOptions {\n /** The centre rectangle's share of each pane axis (0.05 to 0.95); `centreX` / `centreY` override one axis. */\n readonly centre?: number;\n readonly centreX?: number;\n readonly centreY?: number;\n /** The least the centre spans on either axis, px (a small pane keeps a usable centre). */\n readonly centreMin?: number;\n /** How far past its boundary the previous zone holds, px. */\n readonly hysteresis?: number;\n /** Device pixels per px: the centre's edges snap to that grid, as the browser draws them. */\n readonly pixelRatio?: number;\n}\n\nexport const PANE_ZONE_DEFAULTS: Required<Omit<PaneZoneOptions, \"centreX\" | \"centreY\">> = { centre: 0.34, centreMin: 24, hysteresis: 6, pixelRatio: 1 };\n\n/** The centre rectangle of a pane of `size`, in pane-local px (origin at the pane's top-left corner). */\nexport interface PaneCentre {\n readonly width: number;\n readonly height: number;\n readonly left: number;\n readonly top: number;\n readonly right: number;\n readonly bottom: number;\n}\n\nconst clamp = (v: number, lo: number, hi: number): number => Math.min(Math.max(v, lo), hi);\nconst snap = (v: number, ratio: number): number => Math.round(v * ratio) / ratio;\n\n/** Where the centre rectangle of a pane of `size` lies, by these options. */\nexport function paneCentre(size: Size, options: PaneZoneOptions = {}): PaneCentre {\n const o = { ...PANE_ZONE_DEFAULTS, ...options };\n const width = Math.max(0, size.width);\n const height = Math.max(0, size.height);\n const ratio = o.pixelRatio > 0 ? o.pixelRatio : 1;\n const rx = clamp(o.centreX ?? o.centre, 0.05, 0.95);\n const ry = clamp(o.centreY ?? o.centre, 0.05, 0.95);\n const cw = Math.min(width, Math.max(width * rx, Math.min(o.centreMin, width)));\n const ch = Math.min(height, Math.max(height * ry, Math.min(o.centreMin, height)));\n return { width, height, left: snap((width - cw) / 2, ratio), top: snap((height - ch) / 2, ratio), right: snap((width + cw) / 2, ratio), bottom: snap((height + ch) / 2, ratio) };\n}\n\n/** How deep past the centre a point is toward each edge, as a share of that edge's band (positive: in that band). */\nfunction depths(p: Point, c: PaneCentre): { zone: Exclude<PaneZone, \"center\">; depth: number }[] {\n return [\n { zone: \"top\", depth: (c.top - p.y) / Math.max(c.top, 1) },\n { zone: \"right\", depth: (p.x - c.right) / Math.max(c.width - c.right, 1) },\n { zone: \"bottom\", depth: (p.y - c.bottom) / Math.max(c.height - c.bottom, 1) },\n { zone: \"left\", depth: (c.left - p.x) / Math.max(c.left, 1) },\n ];\n}\n\n/** The zone a pane-local point is in, by position alone. */\nfunction rawZone(p: Point, c: PaneCentre): PaneZone {\n if (p.x >= c.left && p.x <= c.right && p.y >= c.top && p.y <= c.bottom) return \"center\";\n let best: PaneZone = \"center\";\n let deepest = 0;\n for (const d of depths(p, c)) {\n if (d.depth > deepest) {\n deepest = d.depth;\n best = d.zone;\n }\n }\n return best;\n}\n\n/** `p` moved `by` px into `zone` (toward the pane's middle for the centre). */\nfunction toward(p: Point, zone: PaneZone, by: number, c: PaneCentre): Point {\n if (zone === \"left\") return { x: p.x - by, y: p.y };\n if (zone === \"right\") return { x: p.x + by, y: p.y };\n if (zone === \"top\") return { x: p.x, y: p.y - by };\n if (zone === \"bottom\") return { x: p.x, y: p.y + by };\n const dx = c.width / 2 - p.x;\n const dy = c.height / 2 - p.y;\n const len = Math.hypot(dx, dy);\n if (len <= by || len === 0) return { x: c.width / 2, y: c.height / 2 };\n return { x: p.x + (dx / len) * by, y: p.y + (dy / len) * by };\n}\n\n/**\n * The zone of `rect` (a pane, in the same coordinates as `point`) the point is in. With a `previous` zone, the point\n * has to be `hysteresis` px past that zone's boundary before the zone changes: no time-based debounce, only geometry.\n */\nexport function paneZone(rect: Rect, point: Point, previous: PaneZone | null = null, options: PaneZoneOptions = {}): PaneZone {\n const c = paneCentre(rect, options);\n const p = { x: point.x - rect.x, y: point.y - rect.y };\n const raw = rawZone(p, c);\n const by = Math.max(0, options.hysteresis ?? PANE_ZONE_DEFAULTS.hysteresis);\n if (previous === null || by === 0 || previous === raw) return raw;\n return rawZone(toward(p, previous, by, c), c) === previous ? previous : raw;\n}\n"],"mappings":"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","names":["clamp","rect"]}
|
package/dist/toolbar.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@n-uf/placement",
|
|
3
|
-
"version": "26.11.
|
|
3
|
+
"version": "26.11.5",
|
|
4
4
|
"description": "Where things go: desk docks, rails and palettes, toolbar groups, and the drop targets for each. Pure state in, rects out. No DOM, no framework, no motion.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"layout",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/toolbar/index.ts"],"sourcesContent":["/**\n * @n-uf/placement/toolbar: toolbar groups as a pure model. Commands come in groups, each sitting in one of five\n * hosts (the title bar, the top toolbar, a bottom toolbar, a left and a right side toolbar), in one of three zones\n * (start, centre, end; top, middle, bottom on a side), in order; or floating. A toolbar is a slot: it never moves\n * itself, its groups do. Group sizes come in as numbers; group ids are the consumer's strings.\n *\n * - A host lays its zones out along its length: start from the lead, end up to the tail, the centre centred on the\n * whole host; when the centre would hit the start or end zone it centres in the space between them.\n * - Toolbars never wrap: when room runs out, groups collapse to their handle and » from the trailing end. A group\n * collapsed by hand stays collapsed.\n * - A group drop lands in a zone before all, after all, or between two groups. An empty zone is a target of its\n * own. A group's own place is home: a drop there changes nothing.\n */\nimport type { Rect } from \"../geometry\";\n\nexport type HostId = \"title\" | \"top\" | \"bottom\" | \"left\" | \"right\";\nexport type ZoneId = \"start\" | \"center\" | \"end\";\nexport type Zones<G extends string = string> = Readonly<Record<ZoneId, readonly G[]>>;\n\n/** Where a group is docked: a host, a zone, and its index there. */\nexport interface Place {\n readonly host: HostId;\n readonly zone: ZoneId;\n readonly index: number;\n}\n\n/** A group floating over the content: its top-left corner, and where it was docked. */\nexport interface Floating<G extends string = string> {\n readonly id: G;\n readonly x: number;\n readonly y: number;\n readonly from: Place | null;\n}\n\nexport type Arrangement<G extends string = string> = Readonly<Record<HostId, Zones<G>>> & {\n /** Groups collapsed to their handle and » by hand. */\n readonly collapsed: readonly G[];\n readonly floating: readonly Floating<G>[];\n};\n\nexport const HOSTS: readonly HostId[] = [\"title\", \"top\", \"bottom\", \"left\", \"right\"];\nexport const ZONES: readonly ZoneId[] = [\"start\", \"center\", \"end\"];\n\nexport const HOST_LABEL: Readonly<Record<HostId, string>> = { title: \"Title bar\", top: \"Top bar\", bottom: \"Bottom bar\", left: \"Left edge\", right: \"Right edge\" };\nexport const zoneLabel = (h: HostId, z: ZoneId): string => (vertical(h) ? { start: \"top\", center: \"middle\", end: \"bottom\" } : { start: \"left\", center: \"centre\", end: \"right\" })[z];\n\n/** The side edges hold their groups in a column. */\nexport const vertical = (h: HostId): boolean => h === \"left\" || h === \"right\";\n\n/** Between two groups (the handle of the second is the separator). */\nexport const GAP = 12;\n/** Between zones. */\nexport const ZONE_GAP = 16;\n\n/** An arrangement from the zones each host has (the rest empty), nothing collapsed or floating. */\nexport function arrangement<G extends string>(p: Partial<Record<HostId, Partial<Record<ZoneId, readonly G[]>>>>): Arrangement<G> {\n const z = (q: Partial<Record<ZoneId, readonly G[]>> = {}): Zones<G> => ({ start: [], center: [], end: [], ...q });\n return { title: z(p.title), top: z(p.top), bottom: z(p.bottom), left: z(p.left), right: z(p.right), collapsed: [], floating: [] };\n}\n\n// --- changes -------------------------------------------------------------------------------------------------------\n\nconst mapHosts = <G extends string>(a: Arrangement<G>, f: (h: HostId, zone: ZoneId, list: readonly G[]) => readonly G[]): Arrangement<G> => ({\n ...a,\n ...(Object.fromEntries(HOSTS.map((h) => [h, Object.fromEntries(ZONES.map((zn) => [zn, f(h, zn, a[h][zn])]))])) as Record<HostId, Zones<G>>),\n});\n\n/** Where `g` is docked (null: floating or absent). */\nexport function hostOf<G extends string>(a: Arrangement<G>, g: G): Place | null {\n for (const h of HOSTS) for (const zn of ZONES) if (a[h][zn].includes(g)) return { host: h, zone: zn, index: a[h][zn].indexOf(g) };\n return null;\n}\n\n/** The arrangement with group `g` lifted out (of its host, or from floating). */\nexport const withoutGroup = <G extends string>(a: Arrangement<G>, g: G): Arrangement<G> => ({ ...mapHosts(a, (_h, _z, l) => l.filter((x) => x !== g)), floating: a.floating.filter((f) => f.id !== g) });\n\n/** The arrangement with `g` docked at place `i` of zone `zone` of host `h` (`i` counts the others). */\nexport function insertGroup<G extends string>(a: Arrangement<G>, g: G, h: HostId, zone: ZoneId, i: number): Arrangement<G> {\n return mapHosts(withoutGroup(a, g), (hh, zz, l) => (hh === h && zz === zone ? [...l.slice(0, i), g, ...l.slice(i)] : l));\n}\n\n/** `g` floating with its top-left corner at (x, y); it remembers where it was docked. */\nexport function floatGroup<G extends string>(a: Arrangement<G>, g: G, x: number, y: number): Arrangement<G> {\n const from = hostOf(a, g) ?? a.floating.find((f) => f.id === g)?.from ?? null;\n const out = withoutGroup(a, g);\n return { ...out, floating: [...out.floating, { id: g, x, y, from }] };\n}\n\n/** `g` at `place`, its index kept within the zone. */\nconst dockAt = <G extends string>(a: Arrangement<G>, g: G, place: Place): Arrangement<G> =>\n insertGroup(a, g, place.host, place.zone, Math.min(place.index, a[place.host][place.zone].filter((x) => x !== g).length));\n\n/** `g` docked again where it floated from, else where `home` (the default arrangement) has it. */\nexport function dockGroup<G extends string>(a: Arrangement<G>, g: G, home: Arrangement<G>): Arrangement<G> {\n const from = a.floating.find((f) => f.id === g)?.from ?? hostOf(home, g);\n return from ? dockAt(a, g, from) : a;\n}\n\n/** `g` back where `home` (the default arrangement) has it, expanded. */\nexport function resetGroup<G extends string>(a: Arrangement<G>, g: G, home: Arrangement<G>): Arrangement<G> {\n const place = hostOf(home, g);\n const out = place ? dockAt(a, g, place) : a;\n return { ...out, collapsed: out.collapsed.filter((x) => x !== g) };\n}\n\n/** `g` moved to host `h`: after its last group (in its last zone that has any), or into its start zone. */\nexport function moveToHost<G extends string>(a: Arrangement<G>, g: G, h: HostId): Arrangement<G> {\n const rest = withoutGroup(a, g);\n const zone = [...ZONES].reverse().find((zn) => rest[h][zn].length > 0) ?? \"start\";\n return insertGroup(a, g, h, zone, rest[h][zone].length);\n}\n\n/** Every group of host `from` moved to host `to`, zone by zone, after the groups there. */\nexport function moveBar<G extends string>(a: Arrangement<G>, from: HostId, to: HostId): Arrangement<G> {\n if (from === to) return a;\n return mapHosts(a, (h, zn, l) => (h === from ? [] : h === to ? [...l, ...a[from][zn]] : l));\n}\n\nexport const toggleCollapsed = <G extends string>(a: Arrangement<G>, g: G): Arrangement<G> => ({ ...a, collapsed: a.collapsed.includes(g) ? a.collapsed.filter((x) => x !== g) : [...a.collapsed, g] });\n\nexport const isEmptyHost = <G extends string>(a: Arrangement<G>, h: HostId): boolean => ZONES.every((zn) => a[h][zn].length === 0);\n\nconst samePlace = (a: Place | null, b: Place | null): boolean => (a === null || b === null ? a === b : a.host === b.host && a.zone === b.zone && a.index === b.index);\n\n/**\n * The same arrangement: the same groups in the same order in every zone of every host, the same groups collapsed,\n * and the same groups floating at the same corner with the same home (in any order: neither list's order means\n * anything). Compared field by field, so how the arrangement was written down (its keys' order) doesn't matter.\n */\nexport function sameArrangement<G extends string>(a: Arrangement<G>, b: Arrangement<G>): boolean {\n const sameList = (x: readonly G[], y: readonly G[]): boolean => x.length === y.length && x.every((g, i) => g === y[i]);\n const sameSet = (x: readonly G[], y: readonly G[]): boolean => x.length === y.length && x.every((g) => y.includes(g));\n if (!HOSTS.every((h) => ZONES.every((zn) => sameList(a[h][zn], b[h][zn])))) return false;\n if (!sameSet(a.collapsed, b.collapsed) || a.floating.length !== b.floating.length) return false;\n return a.floating.every((f) => {\n const o = b.floating.find((x) => x.id === f.id);\n return !!o && o.x === f.x && o.y === f.y && samePlace(o.from, f.from);\n });\n}\n\n/** Dropping `g` at `place` changes nothing: it is the group's own place, its home, never a target. */\nexport const isOwnPlace = <G extends string>(a: Arrangement<G>, g: G, place: Place): boolean => sameArrangement(insertGroup(a, g, place.host, place.zone, place.index), a);\n\n// --- a host's layout -----------------------------------------------------------------------------------------------\n\n/** A host's room: its length and thickness, and what its ends keep for themselves (window controls, a margin). */\nexport interface HostSpec {\n readonly length: number;\n readonly thickness: number;\n readonly lead: number;\n readonly tail: number;\n /**\n * The centre zone's minimum length and its margin on each side, counted in the need whether it holds groups or\n * not (an empty centre keeps its drop size). Unset: the centre counts only its groups.\n */\n readonly center?: { readonly min: number; readonly margin: number };\n}\n\n/** A group's size in a host, expanded or collapsed: along it (`along`) and across it (`across`). */\nexport type GroupSize<G extends string = string> = (id: G, vertical: boolean, collapsed: boolean) => { along: number; across: number };\n\nexport interface HostLayout<G extends string = string> {\n /** Each group's rect in the host (x along, y across for a horizontal host; transposed on a side). */\n readonly slots: ReadonlyMap<G, Rect>;\n /** Groups shown collapsed (by hand, or because the room ran out). */\n readonly collapsed: readonly G[];\n /** Of those, the ones the room collapsed (from the trailing end). */\n readonly overflow: readonly G[];\n /** The length the groups and the ends take. */\n readonly need: number;\n}\n\n/** How long the host's groups need it to be, collapsing only those in `collapsed`. */\nexport function hostNeed<G extends string>(zones: Zones<G>, collapsed: readonly G[], spec: Pick<HostSpec, \"lead\" | \"tail\" | \"center\">, size: GroupSize<G>, v: boolean): number {\n const lens = ZONES.map((zn) => zones[zn].reduce((s, g) => s + size(g, v, collapsed.includes(g)).along, 0) + GAP * Math.max(0, zones[zn].length - 1));\n const used = ZONES.filter((zn) => zones[zn].length > 0).length;\n const c = spec.center;\n if (!c) return spec.lead + spec.tail + lens.reduce((s, x) => s + x, 0) + ZONE_GAP * Math.max(0, used - 1);\n // The centre always counts, at its minimum at least, and its margins keep it apart from the start and end zones.\n return spec.lead + spec.tail + lens[0]! + lens[2]! + Math.max(lens[1]!, c.min) + 2 * c.margin;\n}\n\n/** Lay a host out: zones along its length; when they don't fit, groups collapse from the trailing end. */\nexport function layoutHost<G extends string>(zones: Zones<G>, h: HostId, spec: HostSpec, size: GroupSize<G>, byHand: readonly G[] = []): HostLayout<G> {\n const v = vertical(h);\n const collapsed = new Set<G>(ZONES.flatMap((zn) => zones[zn]).filter((g) => byHand.includes(g)));\n const overflow: G[] = [];\n const len = (g: G): number => size(g, v, collapsed.has(g)).along;\n const zoneLen = (l: readonly G[]): number => l.reduce((s, g) => s + len(g), 0) + GAP * Math.max(0, l.length - 1);\n const needNow = (): number => hostNeed(zones, [...collapsed], spec, size, v);\n // The trailing end first: the end zone's last group, back to the start zone's first.\n for (const g of [...ZONES].reverse().flatMap((zn) => [...zones[zn]].reverse())) {\n if (needNow() <= spec.length) break;\n if (collapsed.has(g)) continue;\n collapsed.add(g);\n overflow.push(g);\n }\n const a0 = spec.lead;\n const b0 = spec.length - spec.tail;\n const S = zoneLen(zones.start);\n const C = zoneLen(zones.center);\n const E = zoneLen(zones.end);\n const lo = a0 + S + (S > 0 ? ZONE_GAP : 0);\n const hi = b0 - E - (E > 0 ? ZONE_GAP : 0);\n let c0 = spec.length / 2 - C / 2;\n if (c0 < lo || c0 + C > hi) c0 = (lo + hi) / 2 - C / 2;\n const slots = new Map<G, Rect>();\n const place = (l: readonly G[], from: number): void => {\n let at = from;\n for (const g of l) {\n const s = size(g, v, collapsed.has(g));\n const across = (spec.thickness - s.across) / 2;\n slots.set(g, v ? { x: across, y: at, width: s.across, height: s.along } : { x: at, y: across, width: s.along, height: s.across });\n at += s.along + GAP;\n }\n };\n place(zones.start, a0);\n place(zones.center, c0);\n place(zones.end, b0 - E);\n return { slots, collapsed: [...collapsed], overflow, need: needNow() };\n}\n\n// --- insertion points ----------------------------------------------------------------------------------------------\n\n/** A place a dragged group can go: a zone of a host and the index among the others there, and where it is. */\nexport interface Insertion extends Place {\n /** Along the host: the insertion line (between groups); for an empty zone, the zone's middle. */\n readonly at: number;\n /** The stretch of the host it owns (host coordinates). */\n readonly span: readonly [number, number];\n /** An empty zone: it owns all of its stretch, whatever is nearer (it wins while the pointer is inside it). */\n readonly empty: boolean;\n readonly label: string;\n}\n\n/**\n * The insertion points of a host laid out without the dragged group: in each zone before all, between two, after\n * all; each owns the stretch of the host nearest to it. An empty zone owns its own stretch: the host's first third\n * (start), middle third (centre) or last third (end), less what its neighbours' groups take. `label` names a group\n * in the \"between\" labels (default: its id).\n */\nexport function insertions<G extends string>(zones: Zones<G>, h: HostId, spec: HostSpec, l: HostLayout<G>, label: (g: G) => string = (g) => g): Insertion[] {\n const v = vertical(h);\n const lo = (r: Rect): number => (v ? r.y : r.x);\n const hi = (r: Rect): number => (v ? r.y + r.height : r.x + r.width);\n const L = spec.length;\n const all = ZONES.flatMap((zn) => zones[zn].map((g) => l.slots.get(g)).filter((r): r is Rect => !!r));\n const first = all.length ? Math.min(...all.map(lo)) : L;\n const last = all.length ? Math.max(...all.map(hi)) : 0;\n const zoneEdge = (zn: ZoneId, end: \"lo\" | \"hi\"): number | null => {\n const rs = zones[zn].map((g) => l.slots.get(g)).filter((r): r is Rect => !!r);\n if (!rs.length) return null;\n return end === \"lo\" ? Math.min(...rs.map(lo)) : Math.max(...rs.map(hi));\n };\n const near: Omit<Insertion, \"span\">[] = [];\n const empties: Insertion[] = [];\n for (const zn of ZONES) {\n const name = `${HOST_LABEL[h]} · ${zoneLabel(h, zn)}`;\n const vis = zones[zn].map((g, i) => ({ g, i, r: l.slots.get(g)! }));\n if (!vis.length) {\n const sEnd = zoneEdge(\"start\", \"hi\");\n const eStart = zoneEdge(\"end\", \"lo\");\n const span: [number, number] =\n zn === \"start\" ? [0, Math.min(L / 3, first - GAP / 2)] : zn === \"end\" ? [Math.max((2 * L) / 3, last + GAP / 2), L] : [Math.max(L / 3, (sEnd ?? 0) + GAP / 2), Math.min((2 * L) / 3, (eStart ?? L) - GAP / 2)];\n if (span[1] - span[0] >= 8) empties.push({ host: h, zone: zn, index: 0, at: (span[0] + span[1]) / 2, span, empty: true, label: name });\n continue;\n }\n near.push({ host: h, zone: zn, index: vis[0]!.i, at: lo(vis[0]!.r) - GAP / 2, empty: false, label: `${name} · before all` });\n for (let k = 1; k < vis.length; k++) near.push({ host: h, zone: zn, index: vis[k]!.i, at: (hi(vis[k - 1]!.r) + lo(vis[k]!.r)) / 2, empty: false, label: `${name} · between ${label(vis[k - 1]!.g)} and ${label(vis[k]!.g)}` });\n near.push({ host: h, zone: zn, index: zones[zn].length, at: hi(vis.at(-1)!.r) + GAP / 2, empty: false, label: `${name} · after all` });\n }\n near.sort((a, b) => a.at - b.at);\n const lines = near.map((p, k) => ({ ...p, span: [k === 0 ? 0 : (near[k - 1]!.at + p.at) / 2, k === near.length - 1 ? L : (p.at + near[k + 1]!.at) / 2] as const }));\n return [...lines, ...empties];\n}\n"],"mappings":"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","names":[]}
|