@n-uf/placement 26.11.6 → 26.11.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/targets/desk.ts","../src/targets/toolbar.ts","../src/targets/stops.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. A place `allows` forbids is no host target either.\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 /** Where the group lands, in stage coordinates: its rect in the host once the drop is made. */\n readonly slot: Rect;\n /** The arrangement a drop here makes. */\n readonly arrangement: Arrangement<G>;\n}\n\n/**\n * Where a group may go: a host's place, or floating. `hostTargets` leaves out a place it refuses; for floating, the\n * consumer adds `floatTarget` only when `allows(group, \"float\")`, so one rule covers both. `place.index` counts the\n * groups in that zone without the dragged one (as `insertGroup` does): 0 is before all of the others.\n */\nexport type Allows<G extends string> = (group: G, place: Place | \"float\") => boolean;\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<G>;\n readonly size: GroupSize<G>;\n /** A group's name in the labels (default: its id). */\n readonly label?: (g: G) => string;\n /** Where the group may go (default: anywhere). A place it may not go is left out. */\n readonly allows?: Allows<G>;\n /**\n * Where this host is, and how long, once a drop has made `arrangement` (a host may grow or appear when it gets a\n * group); default: where it is now. The targets' `slot`s are laid out there.\n */\n readonly hostAfter?: (arrangement: Arrangement<G>) => { readonly origin: Point; readonly spec: HostSpec<G> };\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 slotIn = (after: Arrangement<G>): Rect => {\n const at = input.hostAfter?.(after) ?? { origin: o, spec };\n const r = layoutHost(after[h], h, at.spec, input.size, after.collapsed).slots.get(group)!;\n return rect(at.origin.x + r.x, at.origin.y + r.y, r.width, r.height);\n };\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 if (input.allows && !input.allows(group, place)) continue;\n const after = insertGroup(a, group, h, p.zone, p.index);\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 slot: slotIn(after),\n arrangement: after,\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\nexport interface FloatTargetInput<G extends string> {\n readonly group: G;\n readonly arrangement: Arrangement<G>;\n /** The content the group floats over, in stage coordinates. */\n readonly stage: Rect;\n /** The group's size as it floats. */\n readonly width: number;\n readonly height: number;\n}\n\n/**\n * Floating over the content (`stage`, in stage coordinates): the group's top-left corner kept on the stage. A\n * group that may not float simply gets no float target: add it only when your rule allows it, with the same\n * `allows` you give `hostTargets`: `...(allows(group, \"float\") ? [floatTarget(input)] : [])`.\n */\nexport function floatTarget<G extends string>(input: FloatTargetInput<G>): 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 * Keyboard stops: every place a toolbar group can go, in one list in reading order, for the arrow keys and a\n * \"Move to\" menu alike. A consumer steps through the list; it never parses target ids.\n */\nimport { centre, type Point } from \"../geometry\";\nimport { HOST_LABEL, ZONES, zoneLabel, type Arrangement, type HostId, type Place } from \"../toolbar\";\nimport type { ToolbarFloatTarget, ToolbarTarget } from \"./toolbar\";\n\n/** The hosts in reading order: the title bar, the top bar, the left edge, the right edge, the bottom bar. */\nexport const HOST_READING_ORDER: readonly HostId[] = [\"title\", \"top\", \"left\", \"right\", \"bottom\"];\n\nexport interface KeyboardStop<G extends string = string> {\n /** The target's id (\"home\" for the group's own place). */\n readonly id: string;\n readonly label: string;\n /** Where in a host it is; null for floating. */\n readonly place: Place | null;\n /** The arrangement a move here makes (the current one for home). */\n readonly arrangement: Arrangement<G>;\n /** The group's own place: where the keyboard starts, and a move there changes nothing. */\n readonly home: boolean;\n}\n\nexport interface KeyboardStopsOptions<G extends string> {\n /** The group's own place, as a stop of its own in its reading-order position (the targets leave it out). */\n readonly home?: { readonly place: Place; readonly arrangement: Arrangement<G>; readonly label?: string };\n /**\n * Floating targets as stops at the end (default: left out). `at` is where the pointer would drop it and `grab`\n * where it holds the group (default: the float target's middle, the group's top-left corner).\n */\n readonly floats?: boolean | { readonly at: Point; readonly grab?: Point };\n}\n\nconst isFloat = <G extends string>(t: ToolbarTarget<G> | ToolbarFloatTarget<G>): t is ToolbarFloatTarget<G> => t.kind === \"float\";\n\n/** Reading order of a place: host, then zone, then index. */\nconst rank = (p: Place): number => HOST_READING_ORDER.indexOf(p.host) * 3000 + ZONES.indexOf(p.zone) * 1000 + p.index;\n\n/**\n * The places a group can go, in reading order: hosts title → top → left → right → bottom, zones start → centre →\n * end, then each insertion point in order; the group's own place among them when `home` is given; floating targets\n * at the end only when `floats` asks for them. One list serves the arrow keys and a \"Move to\" menu.\n */\nexport function keyboardStops<G extends string>(targets: readonly (ToolbarTarget<G> | ToolbarFloatTarget<G>)[], options: KeyboardStopsOptions<G> = {}): KeyboardStop<G>[] {\n const placed: KeyboardStop<G>[] = [];\n const floating: KeyboardStop<G>[] = [];\n for (const t of targets) {\n if (!isFloat(t)) {\n placed.push({ id: t.id, label: t.label, place: t.place, arrangement: t.arrangement, home: false });\n continue;\n }\n if (!options.floats) continue;\n const at = options.floats === true ? centre(t.hit) : options.floats.at;\n const grab = options.floats === true ? { x: 0, y: 0 } : (options.floats.grab ?? { x: 0, y: 0 });\n floating.push({ id: t.id, label: t.label, place: null, arrangement: t.make(at, grab), home: false });\n }\n const h = options.home;\n if (h) placed.push({ id: \"home\", label: h.label ?? `${HOST_LABEL[h.place.host]} · ${zoneLabel(h.place.host, h.place.zone)} · current place`, place: h.place, arrangement: h.arrangement, home: true });\n placed.sort((a, b) => rank(a.place!) - rank(b.place!));\n return [...placed, ...floating];\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"]}
1
+ {"version":3,"sources":["../src/targets/desk.ts","../src/targets/toolbar.ts","../src/targets/stops.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. A place `allows` forbids is no host target either.\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 /** Where the group lands, in stage coordinates: its rect in the host once the drop is made. */\n readonly slot: Rect;\n /** The arrangement a drop here makes. */\n readonly arrangement: Arrangement<G>;\n}\n\n/**\n * Where a group may go: a host's place, or floating. `hostTargets` leaves out a place it refuses; for floating, the\n * consumer adds `floatTarget` only when `allows(group, \"float\")`, so one rule covers both. `place.index` counts the\n * groups in that zone without the dragged one (as `insertGroup` does): 0 is before all of the others.\n */\nexport type Allows<G extends string> = (group: G, place: Place | \"float\") => boolean;\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<G>;\n readonly size: GroupSize<G>;\n /** A group's name in the labels (default: its id). */\n readonly label?: (g: G) => string;\n /** Where the group may go (default: anywhere). A place it may not go is left out. */\n readonly allows?: Allows<G>;\n /**\n * Where this host is, and how long, once a drop has made `arrangement` (a host may grow or appear when it gets a\n * group); default: where it is now. The targets' `slot`s are laid out there.\n */\n readonly hostAfter?: (arrangement: Arrangement<G>) => { readonly origin: Point; readonly spec: HostSpec<G> };\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 slotIn = (after: Arrangement<G>): Rect => {\n const at = input.hostAfter?.(after) ?? { origin: o, spec };\n const r = layoutHost(after[h], h, at.spec, input.size, after.collapsed).slots.get(group)!;\n return rect(at.origin.x + r.x, at.origin.y + r.y, r.width, r.height);\n };\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 if (input.allows && !input.allows(group, place)) continue;\n const after = insertGroup(a, group, h, p.zone, p.index);\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 slot: slotIn(after),\n arrangement: after,\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\nexport interface FloatTargetInput<G extends string> {\n readonly group: G;\n readonly arrangement: Arrangement<G>;\n /** The content the group floats over, in stage coordinates. */\n readonly stage: Rect;\n /** The group's size as it floats. */\n readonly width: number;\n readonly height: number;\n}\n\n/**\n * Floating over the content (`stage`, in stage coordinates): the group's top-left corner kept on the stage. A\n * group that may not float simply gets no float target: add it only when your rule allows it, with the same\n * `allows` you give `hostTargets`: `...(allows(group, \"float\") ? [floatTarget(input)] : [])`.\n */\nexport function floatTarget<G extends string>(input: FloatTargetInput<G>): 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 * Keyboard stops: every place a toolbar group can go, in one list in reading order, for the arrow keys and a\n * \"Move to\" menu alike. A consumer steps through the list; it never parses target ids.\n */\nimport { centre, type Point } from \"../geometry\";\nimport { panelStops, type PanelStop, type PanelStopsOptions, type PanelTarget } from \"../panels/targets\";\nimport { HOST_LABEL, ZONES, zoneLabel, type Arrangement, type HostId, type Place } from \"../toolbar\";\nimport type { ToolbarFloatTarget, ToolbarTarget } from \"./toolbar\";\n\n/** The hosts in reading order: the title bar, the top bar, the left edge, the right edge, the bottom bar. */\nexport const HOST_READING_ORDER: readonly HostId[] = [\"title\", \"top\", \"left\", \"right\", \"bottom\"];\n\nexport interface KeyboardStop<G extends string = string> {\n /** The target's id (\"home\" for the group's own place). */\n readonly id: string;\n readonly label: string;\n /** Where in a host it is; null for floating. */\n readonly place: Place | null;\n /** The arrangement a move here makes (the current one for home). */\n readonly arrangement: Arrangement<G>;\n /** The group's own place: where the keyboard starts, and a move there changes nothing. */\n readonly home: boolean;\n}\n\nexport interface KeyboardStopsOptions<G extends string> {\n /** The group's own place, as a stop of its own in its reading-order position (the targets leave it out). */\n readonly home?: { readonly place: Place; readonly arrangement: Arrangement<G>; readonly label?: string };\n /**\n * Floating targets as stops at the end (default: left out). `at` is where the pointer would drop it and `grab`\n * where it holds the group (default: the float target's middle, the group's top-left corner).\n */\n readonly floats?: boolean | { readonly at: Point; readonly grab?: Point };\n}\n\nconst isFloat = <G extends string>(t: ToolbarTarget<G> | ToolbarFloatTarget<G>): t is ToolbarFloatTarget<G> => t.kind === \"float\";\n\n/** Reading order of a place: host, then zone, then index. */\nconst rank = (p: Place): number => HOST_READING_ORDER.indexOf(p.host) * 3000 + ZONES.indexOf(p.zone) * 1000 + p.index;\n\nconst isPanelTargets = (targets: readonly object[], options: { readonly home?: object }): boolean => targets.some((t) => \"panel\" in t) || (targets.length === 0 && !!options.home && \"state\" in options.home);\n\n/**\n * The places a group can go, in reading order: hosts title → top → left → right → bottom, zones start → centre →\n * end, then each insertion point in order; the group's own place among them when `home` is given; floating targets\n * at the end only when `floats` asks for them. One list serves the arrow keys and a \"Move to\" menu.\n *\n * Given panel targets (`@n-uf/placement/panels`' `panelTargets`), the same for a panel: left to right across the\n * stage (the left rail, the left side's lines and columns outer to inner, the right side's inner to outer, the right\n * rail), floating last when asked; each stop carries the state a move there makes (`panelStops`).\n */\nexport function keyboardStops(targets: readonly PanelTarget[], options?: PanelStopsOptions): PanelStop[];\nexport function keyboardStops<G extends string>(targets: readonly (ToolbarTarget<G> | ToolbarFloatTarget<G>)[], options?: KeyboardStopsOptions<G>): KeyboardStop<G>[];\nexport function keyboardStops<G extends string>(\n targets: readonly (ToolbarTarget<G> | ToolbarFloatTarget<G>)[] | readonly PanelTarget[],\n options: KeyboardStopsOptions<G> | PanelStopsOptions = {},\n): KeyboardStop<G>[] | PanelStop[] {\n if (isPanelTargets(targets, options)) return panelStops(targets as readonly PanelTarget[], options as PanelStopsOptions);\n return toolbarStops(targets as readonly (ToolbarTarget<G> | ToolbarFloatTarget<G>)[], options as KeyboardStopsOptions<G>);\n}\n\nfunction toolbarStops<G extends string>(targets: readonly (ToolbarTarget<G> | ToolbarFloatTarget<G>)[], options: KeyboardStopsOptions<G>): KeyboardStop<G>[] {\n const placed: KeyboardStop<G>[] = [];\n const floating: KeyboardStop<G>[] = [];\n for (const t of targets) {\n if (!isFloat(t)) {\n placed.push({ id: t.id, label: t.label, place: t.place, arrangement: t.arrangement, home: false });\n continue;\n }\n if (!options.floats) continue;\n const at = options.floats === true ? centre(t.hit) : options.floats.at;\n const grab = options.floats === true ? { x: 0, y: 0 } : (options.floats.grab ?? { x: 0, y: 0 });\n floating.push({ id: t.id, label: t.label, place: null, arrangement: t.make(at, grab), home: false });\n }\n const h = options.home;\n if (h) placed.push({ id: \"home\", label: h.label ?? `${HOST_LABEL[h.place.host]} · ${zoneLabel(h.place.host, h.place.zone)} · current place`, place: h.place, arrangement: h.arrangement, home: true });\n placed.sort((a, b) => rank(a.place!) - rank(b.place!));\n return [...placed, ...floating];\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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@n-uf/placement",
3
- "version": "26.11.6",
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.",
3
+ "version": "26.11.8",
4
+ "description": "Where things go: desk docks, rails and palettes, panel columns, 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",
7
7
  "docking",
@@ -21,7 +21,7 @@
21
21
  "url": "git+https://github.com/n-uf/motion.git",
22
22
  "directory": "packages/placement"
23
23
  },
24
- "homepage": "https://github.com/n-uf/motion/tree/main/packages/placement#readme",
24
+ "homepage": "https://motion.n-uf.com",
25
25
  "bugs": {
26
26
  "url": "https://github.com/n-uf/motion/issues"
27
27
  },
@@ -44,6 +44,10 @@
44
44
  "types": "./dist/targets.d.ts",
45
45
  "default": "./dist/targets.js"
46
46
  },
47
+ "./panels": {
48
+ "types": "./dist/panels.d.ts",
49
+ "default": "./dist/panels.js"
50
+ },
47
51
  "./package.json": "./package.json"
48
52
  },
49
53
  "publishConfig": {