@n-uf/placement 26.11.9 → 26.11.11

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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/panels/model.ts","../src/panels/layout.ts","../src/panels/targets.ts"],"sourcesContent":["/**\n * The panels model: plain data and the pure changes on it.\n *\n * Panels have string ids. Each side holds full-height columns (outer edge first), each column one or more panels\n * top to bottom and its own width. Opt-in, the top and bottom edges hold a band each: its panels side by side, left to\n * right, sharing its width, at its own height. A panel may instead float, in page space (it moves with the page) or pinned in\n * view space (it stays put). A logical clock per panel (opened, used) is what give-way reads; every change here that\n * counts as a use moves it on. Nothing here reads a host clock: the next tick is one past the latest in the state.\n */\nimport type { Rect, Size } from \"../geometry\";\n\nexport type Side = \"left\" | \"right\";\nexport const SIDES: readonly Side[] = [\"left\", \"right\"];\n\n/** A band's edge: a horizontal dock along the stage's top or bottom (opt-in, `PanelsOptions.bands`). */\nexport type Edge = \"top\" | \"bottom\";\nexport const EDGES: readonly Edge[] = [\"top\", \"bottom\"];\n/** Where a panel may dock: a side's columns or an edge's band. */\nexport type Place = Side | Edge;\n\n/** A band's height limits and natural height when a def gives none. */\nexport const BAND_SIZE: { readonly min: number; readonly max: number; readonly natural: number } = { min: 120, max: 480, natural: 200 };\n\n/** How an edge's band lies: \"reserved\" shortens the pages, \"overlay\" lies over them; between the columns, or full width. */\nexport interface BandOption {\n readonly mode: \"reserved\" | \"overlay\";\n readonly span: \"between\" | \"full\";\n}\n\n/** Room kept clear along the pages' edges, px. */\nexport type Reserve = Readonly<Partial<Record<\"top\" | \"right\" | \"bottom\" | \"left\", number>>>;\n\n/**\n * What a consumer says about a panel: its width limits docked, its size limits floating, and where it may go. No\n * words: names and titles are the consumer's.\n */\nexport interface PanelDef {\n readonly id: string;\n /** A docked column's width limits and its natural width. */\n readonly width: { readonly min: number; readonly max: number; readonly natural: number };\n /**\n * Its height as a section of a stack column (opt-in): it gets its natural height, the column's last open section\n * takes the rest, and when the column is short sections fold to bars by give-way. Without it a section shares the\n * column's height equally with the others, as before.\n */\n readonly height?: { readonly min: number; readonly natural: number };\n /** A float's size limits and natural size (default: its natural width, 360 px tall, no smaller than 160 × 120). */\n readonly float?: { readonly min: Size; readonly natural: Size };\n /** Where it may dock (default: both sides, and every edge that has a band). */\n readonly sides?: readonly Place[];\n /** A band's height limits and natural height (default `BAND_SIZE`: min 120, max 480, natural 200). */\n readonly band?: { readonly min: number; readonly max: number; readonly natural: number };\n /** May it float (default: yes). */\n readonly floats?: boolean;\n}\n\n/**\n * A full-height column: its panels top to bottom, and its stored width (the layout clamps it to its panels' limits).\n * `show` \"tabs\" shows one panel at a time under a strip of tabs: `active` (default, or when `active` isn't one of\n * them: the first panel in the column that isn't closed).\n */\nexport interface Column {\n readonly panels: readonly string[];\n readonly width: number;\n readonly show?: \"stack\" | \"tabs\";\n readonly active?: string;\n}\n\n/** A floating panel: `rect` in page space, or in view space when `pinned`. */\nexport interface FloatAt {\n readonly id: string;\n readonly rect: Rect;\n readonly pinned?: boolean;\n}\n\n/** A band: its panels left to right, sharing its width, and its stored height (the layout clamps it to their limits). */\nexport interface Band {\n readonly panels: readonly string[];\n readonly height: number;\n}\n\n/** Logical times: when a panel was last opened, and last used (opened, focused, moved or unfolded). */\nexport interface Clock {\n readonly opened: number;\n readonly used: number;\n}\n\nexport interface PanelsState {\n /** Each side's columns, from the outer edge inward. */\n readonly sides: Readonly<Record<Side, readonly Column[]>>;\n /** Floating panels; a later one is on top. */\n readonly floats: readonly FloatAt[];\n /** Folded by hand (give-way never writes this). */\n readonly folded: readonly string[];\n /** Docked panels kept open: their columns give way last. */\n readonly kept: readonly string[];\n /** Not shown at all (they keep their place, for when they open again). */\n readonly closed: readonly string[];\n readonly clock: Readonly<Record<string, Clock>>;\n /** Each edge's band (absent: no band panels). An emptied band goes from the state. */\n readonly bands?: Readonly<Partial<Record<Edge, Band>>>;\n}\n\n/** The page's offset and scale in the view: a page point p shows at `x + p.x * scale`, `y + p.y * scale`. */\nexport interface View {\n readonly x: number;\n readonly y: number;\n readonly scale: number;\n}\nexport const IDENTITY_VIEW: View = { x: 0, y: 0, scale: 1 };\n\n/** Who gives way first: the oldest or the newest, by when they were last used or last opened. */\nexport interface GiveWay {\n readonly order: \"oldest\" | \"newest\";\n readonly by: \"used\" | \"opened\";\n}\n\nexport interface PanelsOptions {\n /** Default: `{ order: \"oldest\", by: \"used\" }`, so the panel used longest ago gives way first. */\n readonly giveWay: GiveWay;\n /** \"clamp\" keeps floats in the view at layout time; \"free\" never moves them. Default \"clamp\". */\n readonly floats: \"clamp\" | \"free\";\n /**\n * Where a column folded by hand goes (default \"rail\"): to its side's rail, or (\"ride\") as title bars on top of the\n * side's first open column, until every column on that side is folded. Give-way's folds always go to the rail.\n */\n readonly fold: \"rail\" | \"ride\";\n /** How much of a float wider than the view stays in it, px (default 48). */\n readonly floatVisible: number;\n /** The pages' minimum width (default 320). */\n readonly pagesMin: number;\n /** The page's offset and scale (default: identity). */\n readonly view: View;\n /**\n * A title bar's height: a panel folded in a column, a folded float, a riding column, and the part of a float the\n * clamp keeps in the view (default 28).\n */\n readonly bar: number;\n /** A rail's width (default 36). */\n readonly rail: number;\n /** A rail segment's height, and the gap above the first one (defaults 36 and 4). */\n readonly segment: number;\n readonly railInset: number;\n /** A tabbed column's strip height (default 28). */\n readonly tabs: number;\n /** Which edges have a band, and how it lies (default: none). */\n readonly bands: Readonly<Partial<Record<Edge, BandOption>>>;\n /** The pages' minimum height; only bands give way to it (default 240). */\n readonly pagesMinHeight: number;\n /** Room kept clear at the pages' edges for a toolbar the app draws, px (default: none). */\n readonly reserve: Reserve;\n}\n\nexport const DEFAULT_PANELS_OPTIONS: PanelsOptions = {\n giveWay: { order: \"oldest\", by: \"used\" },\n floats: \"clamp\",\n fold: \"rail\",\n floatVisible: 48,\n pagesMin: 320,\n view: IDENTITY_VIEW,\n bar: 28,\n rail: 36,\n segment: 36,\n railInset: 4,\n tabs: 28,\n bands: {},\n pagesMinHeight: 240,\n reserve: {},\n};\n\n/** A float's size when its def gives none: this tall, and never smaller than FLOAT_MIN. */\nexport const FLOAT_HEIGHT = 360;\nexport const FLOAT_MIN: Size = { width: 160, height: 120 };\n\n// --- reading the state ---------------------------------------------------------------------------------------------\n\nconst without = <T>(list: readonly T[], x: T): T[] => list.filter((y) => y !== x);\nconst withOnce = <T>(list: readonly T[], x: T): T[] => (list.includes(x) ? [...list] : [...list, x]);\n\n/** Where a panel is: a column (side and index), a band (edge and index, left to right), floating, or nowhere. */\nexport type Where =\n | { readonly kind: \"column\"; readonly side: Side; readonly index: number }\n | { readonly kind: \"band\"; readonly edge: Edge; readonly index: number }\n | { readonly kind: \"float\"; readonly float: FloatAt }\n | { readonly kind: \"none\" };\n\nexport function whereIs(state: PanelsState, id: string): Where {\n for (const side of SIDES) {\n const index = state.sides[side].findIndex((c) => c.panels.includes(id));\n if (index >= 0) return { kind: \"column\", side, index };\n }\n for (const edge of EDGES) {\n const index = state.bands?.[edge]?.panels.indexOf(id) ?? -1;\n if (index >= 0) return { kind: \"band\", edge, index };\n }\n const float = state.floats.find((f) => f.id === id);\n return float ? { kind: \"float\", float } : { kind: \"none\" };\n}\n\n/** One past the latest logical time in the state. */\nexport const tick = (state: PanelsState): number => Object.values(state.clock).reduce((m, c) => Math.max(m, c.opened, c.used), 0) + 1;\n\nconst bump = (state: PanelsState, id: string, opened: boolean): PanelsState => {\n const t = tick(state);\n const was = state.clock[id] ?? { opened: 0, used: 0 };\n return { ...state, clock: { ...state.clock, [id]: { opened: opened ? t : was.opened, used: t } } };\n};\n\nexport const defOf = (defs: readonly PanelDef[], id: string): PanelDef | undefined => defs.find((d) => d.id === id);\n\n/** A float's size limits and natural size from its def. */\nexport function floatSize(def: PanelDef | undefined): { min: Size; natural: Size } {\n if (def?.float) return { min: def.float.min, natural: def.float.natural };\n const width = Math.max(FLOAT_MIN.width, def?.width.natural ?? FLOAT_MIN.width);\n return { min: FLOAT_MIN, natural: { width, height: FLOAT_HEIGHT } };\n}\n\n/** A band's height limits and natural height from a def (`BAND_SIZE` when it gives none). */\nexport const bandSize = (def: PanelDef | undefined): { min: number; max: number; natural: number } => ({ ...(def?.band ?? BAND_SIZE) });\n\n/** A band's height as the layout takes it: its stored height clamped to its panels' limits (the largest min, the smallest max). */\nexport function bandHeight(defs: readonly PanelDef[] | undefined, band: Band): number {\n if (!defs) return band.height;\n const ds = band.panels.map((id) => bandSize(defOf(defs, id)));\n const lo = Math.max(0, ...ds.map((d) => d.min));\n const hi = Math.max(lo, Math.min(...ds.map((d) => d.max)));\n return Math.min(Math.max(Number.isFinite(band.height) ? band.height : lo, lo), hi);\n}\n\n/** The bands with `edge` set to `band`, or without it when null; no `bands` at all once none is left. */\nconst withBand = (state: PanelsState, edge: Edge, band: Band | null): PanelsState => {\n const { bands: _b, ...rest } = state;\n const bands: Partial<Record<Edge, Band>> = { ...state.bands };\n if (band && band.panels.length) bands[edge] = band;\n else delete bands[edge];\n return EDGES.some((e) => bands[e]) ? { ...rest, bands } : rest;\n};\n\n/**\n * A panel's own width, for a new column made for it: the width of the column it is in, clamped to its own limits;\n * in a band, floating or nowhere, its natural width.\n */\nexport function ownWidth(defs: readonly PanelDef[], state: PanelsState, id: string): number {\n const def = defOf(defs, id);\n const w = whereIs(state, id);\n const lo = def?.width.min ?? 0;\n const hi = Math.max(lo, def?.width.max ?? Infinity);\n if (w.kind === \"column\") return Math.min(Math.max(state.sides[w.side][w.index]!.width, lo), hi);\n return def?.width.natural ?? lo;\n}\n\n// --- building one --------------------------------------------------------------------------------------------------\n\nexport interface PanelsStart {\n /** Each side's columns from the outer edge inward, each a list of panel ids top to bottom. */\n readonly left?: readonly (readonly string[])[];\n readonly right?: readonly (readonly string[])[];\n /** Each edge's band, its panels left to right (it takes the tallest natural band height, within their limits). */\n readonly top?: readonly string[];\n readonly bottom?: readonly string[];\n /** Floating panels: where (page space, or view space when pinned); the size defaults to the def's natural size. */\n readonly floats?: readonly { readonly id: string; readonly x: number; readonly y: number; readonly width?: number; readonly height?: number; readonly pinned?: boolean }[];\n readonly folded?: readonly string[];\n readonly kept?: readonly string[];\n readonly closed?: readonly string[];\n}\n\n/**\n * A state from a plain start: each column as wide as the widest natural width of its panels (within their limits),\n * each float its natural size. The clock counts up in the order the panels are listed (left, right, top, bottom,\n * floats), so the last one listed is the newest.\n */\nexport function createPanels(defs: readonly PanelDef[], start: PanelsStart): PanelsState {\n const column = (ids: readonly string[]): Column => {\n const ds = ids.map((id) => defOf(defs, id));\n const lo = Math.max(0, ...ds.map((d) => d?.width.min ?? 0));\n const hi = Math.max(lo, Math.min(...ds.map((d) => d?.width.max ?? Infinity)));\n const natural = Math.max(0, ...ds.map((d) => d?.width.natural ?? 0));\n return { panels: [...ids], width: Math.min(Math.max(natural, lo), hi) };\n };\n const floats = (start.floats ?? []).map((f): FloatAt => {\n const n = floatSize(defOf(defs, f.id)).natural;\n return { id: f.id, rect: { x: f.x, y: f.y, width: f.width ?? n.width, height: f.height ?? n.height }, ...(f.pinned ? { pinned: true } : {}) };\n });\n const sides = { left: (start.left ?? []).map(column), right: (start.right ?? []).map(column) };\n const bands: Partial<Record<Edge, Band>> = {};\n for (const edge of EDGES) {\n const ids = start[edge] ?? [];\n if (!ids.length) continue;\n const natural = Math.max(0, ...ids.map((id) => bandSize(defOf(defs, id)).natural));\n bands[edge] = { panels: [...ids], height: bandHeight(defs, { panels: ids, height: natural }) };\n }\n const order = [...sides.left, ...sides.right]\n .flatMap((c) => c.panels)\n .concat(EDGES.flatMap((e) => bands[e]?.panels ?? []))\n .concat(floats.map((f) => f.id));\n const clock: Record<string, Clock> = {};\n order.forEach((id, i) => (clock[id] = { opened: i + 1, used: i + 1 }));\n const s: PanelsState = { sides, floats, folded: [...(start.folded ?? [])], kept: [...(start.kept ?? [])], closed: [...(start.closed ?? [])], clock };\n return EDGES.some((e) => bands[e]) ? { ...s, bands } : s;\n}\n\n// --- changes -------------------------------------------------------------------------------------------------------\n\n/**\n * The state with `id` taken out of its column (an emptied column goes), its band (an emptied band goes, and its height\n * is forgotten) or the floats. Nothing else changes.\n */\nexport function liftPanel(state: PanelsState, id: string): PanelsState {\n // A tabbed column whose active panel leaves shows its first panel again.\n const out = (c: Column): Column => {\n const { active: _a, ...rest } = c;\n return { ...(c.active === id ? rest : c), panels: without(c.panels, id) };\n };\n const lift = (cols: readonly Column[]): Column[] => cols.map(out).filter((c) => c.panels.length > 0);\n let s: PanelsState = { ...state, sides: { left: lift(state.sides.left), right: lift(state.sides.right) }, floats: state.floats.filter((f) => f.id !== id) };\n for (const edge of EDGES) {\n const b = s.bands?.[edge];\n if (b?.panels.includes(id)) s = withBand(s, edge, { ...b, panels: without(b.panels, id) });\n }\n return s;\n}\n\n/**\n * Open a panel: it shows again where it was, and it is the newest opened and used. A panel placed nowhere goes into\n * a new innermost column on `at.side`, `at.width` wide, or with `at.edge` at the right end of that edge's band (a new\n * band is `at.height` tall, default `BAND_SIZE.natural`; the layout clamps it); without `at` it stays placed nowhere.\n * In a tabbed column it becomes the tab that shows, as a drop into the column does.\n */\nexport function open(state: PanelsState, id: string, at?: { readonly side: Side; readonly width: number } | { readonly edge: Edge; readonly height?: number }): PanelsState {\n let s: PanelsState = { ...state, closed: without(state.closed, id) };\n if (at && whereIs(s, id).kind === \"none\") {\n if (\"edge\" in at) {\n const b = s.bands?.[at.edge];\n const panels = [...(b?.panels ?? []), id];\n // The band shows, as a drop into it does: a band folded by hand unfolds as a whole.\n s = withBand({ ...s, folded: s.folded.filter((x) => !panels.includes(x)) }, at.edge, { panels, height: b?.height ?? at.height ?? BAND_SIZE.natural });\n } else s = { ...s, sides: { ...s.sides, [at.side]: [...s.sides[at.side], { panels: [id], width: at.width }] } };\n }\n const w = whereIs(s, id);\n if (w.kind === \"column\" && s.sides[w.side][w.index]!.show === \"tabs\") s = { ...s, sides: { ...s.sides, [w.side]: s.sides[w.side].map((c, i) => (i === w.index ? { ...c, active: id } : c)) } };\n return bump(s, id, true);\n}\n\n/** Close a panel: it isn't shown, keeps its place, and is no longer kept open. */\nexport const close = (state: PanelsState, id: string): PanelsState => ({ ...state, closed: withOnce(state.closed, id), kept: without(state.kept, id) });\n\n/** Focus a panel: it is the newest used; a float comes to the top. */\nexport function focus(state: PanelsState, id: string): PanelsState {\n const f = state.floats.find((x) => x.id === id);\n const s = f ? { ...state, floats: [...state.floats.filter((x) => x !== f), f] } : state;\n return bump(s, id, false);\n}\n\n/**\n * Fold a panel to its title bar by hand, or unfold it (unfolding is a use). A band folds as a whole: on a band panel\n * all its panels go into `folded`, or (when every shown panel of the band is folded) all come out.\n */\nexport function toggleFold(state: PanelsState, id: string): PanelsState {\n const w = whereIs(state, id);\n if (w.kind === \"band\") {\n const ids = state.bands![w.edge]!.panels;\n // Folded as the layout sees it: every shown panel of the band is folded.\n const shown = ids.filter((x) => !state.closed.includes(x));\n if ((shown.length ? shown : ids).every((x) => state.folded.includes(x))) return bump({ ...state, folded: state.folded.filter((x) => !ids.includes(x)) }, id, false);\n return { ...state, folded: [...state.folded.filter((x) => !ids.includes(x)), ...ids] };\n }\n if (state.folded.includes(id)) return bump({ ...state, folded: without(state.folded, id) }, id, false);\n return { ...state, folded: [...state.folded, id] };\n}\n\n/** Keep a docked panel open (its column or band gives way last), or stop keeping it. A floating panel isn't kept. */\nexport function keep(state: PanelsState, id: string, on: boolean): PanelsState {\n if (!on) return { ...state, kept: without(state.kept, id) };\n const k = whereIs(state, id).kind;\n return k === \"column\" || k === \"band\" ? { ...state, kept: withOnce(state.kept, id) } : state;\n}\n\n/**\n * Dock a panel in the band on `edge`, at `index` (0 the leftmost; past the end, the rightmost). A new band takes the\n * panel's natural band height (with `defs`; else `BAND_SIZE.natural`). It shows (a band folded by hand unfolds), it is\n * the newest used, and it keeps whether it is kept open.\n */\nexport function dockBand(state: PanelsState, id: string, edge: Edge, index: number, defs?: readonly PanelDef[]): PanelsState {\n const s = liftPanel(state, id);\n const b = s.bands?.[edge];\n const panels = [...(b?.panels ?? [])];\n panels.splice(Math.max(0, Math.min(index, panels.length)), 0, id);\n const height = b?.height ?? bandSize(defs ? defOf(defs, id) : undefined).natural;\n const s1 = withBand(s, edge, { panels, height });\n return bump({ ...s1, folded: s1.folded.filter((x) => !panels.includes(x)), closed: without(s1.closed, id) }, id, false);\n}\n\n/** Store a band's height (the layout clamps it to its panels' limits). Resizing is a use, as for a column. */\nexport function resizeBand(state: PanelsState, edge: Edge, height: number): PanelsState {\n const b = state.bands?.[edge];\n if (!b || !Number.isFinite(height)) return state;\n const t = tick(state);\n const clock = { ...state.clock };\n for (const id of b.panels) clock[id] = { opened: clock[id]?.opened ?? 0, used: t };\n return { ...withBand(state, edge, { ...b, height: Math.max(0, height) }), clock };\n}\n\nexport interface DockOptions {\n /** Stack into the column at `index` (at its bottom) instead of making a new column there. */\n readonly into?: boolean;\n /**\n * With `into`: the panel goes before the column's member at this index (0 the top; past the end, or left out, the\n * bottom), counted once the panel is lifted out.\n */\n readonly at?: number;\n /**\n * A new column's width (default: the width of the column the panel leaves, else 0, which the layout clamps to the\n * minimum; from a band, pass `ownWidth` for its natural width, as the drop targets do).\n */\n readonly width?: number;\n}\n\n/**\n * Dock a panel on `side`: a new column at `index` (0 the outer edge; past the end, innermost), or with `into` in the\n * column at `index` (counted once the panel is lifted out), at its bottom or before the member `at`. It shows, it is\n * the newest used, and it keeps whether it is kept open.\n */\nexport function dock(state: PanelsState, id: string, side: Side, index: number, options: DockOptions = {}): PanelsState {\n const w = whereIs(state, id);\n const from = w.kind === \"column\" ? state.sides[w.side][w.index]!.width : 0;\n const s = liftPanel(state, id);\n const cols = [...s.sides[side]];\n // Into a column: at its bottom, or before the member `at`. Into a tabbed column it is also the tab that shows.\n if (options.into && cols[index]) {\n const panels = [...cols[index]!.panels];\n const at = typeof options.at === \"number\" && !Number.isNaN(options.at) ? Math.max(0, Math.min(Math.floor(options.at), panels.length)) : panels.length;\n panels.splice(at, 0, id);\n cols[index] = { ...cols[index]!, panels, ...(cols[index]!.show === \"tabs\" ? { active: id } : {}) };\n } else {\n const at = Math.max(0, Math.min(index, cols.length));\n cols.splice(at, 0, { panels: [id], width: options.width ?? from });\n }\n return bump({ ...s, sides: { ...s.sides, [side]: cols }, closed: without(s.closed, id) }, id, false);\n}\n\n/** Show a column's panels as tabs (one at a time under a strip), or as a stack again. */\nexport function showTabs(state: PanelsState, side: Side, index: number, on: boolean): PanelsState {\n const col = state.sides[side][index];\n if (!col) return state;\n const { show: _s, ...stack } = col;\n return { ...state, sides: { ...state.sides, [side]: state.sides[side].map((c, i) => (i === index ? (on ? { ...col, show: \"tabs\" as const } : stack) : c)) } };\n}\n\n/** Make a docked panel the one its column shows (its tab), and the newest used. */\nexport function activate(state: PanelsState, id: string): PanelsState {\n const w = whereIs(state, id);\n if (w.kind !== \"column\") return state;\n const sides = { ...state.sides, [w.side]: state.sides[w.side].map((c, i) => (i === w.index ? { ...c, active: id } : c)) };\n return bump({ ...state, sides }, id, false);\n}\n\n/**\n * Float a panel at `rect` (page space; view space when pinned). A float stays pinned or not unless `pinned` says;\n * a docked panel floats unpinned. It shows, it is the newest used and on top, and it is no longer kept open.\n */\nexport function float(state: PanelsState, id: string, rect: Rect, pinned?: boolean): PanelsState {\n const was = state.floats.find((f) => f.id === id);\n const on = pinned ?? !!was?.pinned;\n const s = liftPanel(state, id);\n const f: FloatAt = { id, rect: { ...rect }, ...(on ? { pinned: true } : {}) };\n return bump({ ...s, floats: [...s.floats, f], kept: without(s.kept, id), closed: without(s.closed, id) }, id, false);\n}\n\n/** A page-space rect in view space, and back. */\nexport const toView = (r: Rect, v: View): Rect => ({ ...r, x: v.x + r.x * v.scale, y: v.y + r.y * v.scale });\nexport const toPage = (r: Rect, v: View): Rect => ({ ...r, x: (r.x - v.x) / v.scale, y: (r.y - v.y) / v.scale });\n\n/**\n * Pin a float to the view, or unpin it to the page. `view` is where the page is now (default: identity): the float\n * doesn't jump, its rect is converted between the two spaces. A float's size is never scaled.\n *\n * `shown` is where the float shows now, in view space (the layout's placed rect for it). When given, its position is\n * converted instead of the stored one, so a float the clamp moved stays where it shows rather than jumping to its\n * stored place. The size stays the stored one: a float folded to a bar, or shrunk by the clamp, keeps its full size.\n */\nexport function pin(state: PanelsState, id: string, on: boolean, view: View = IDENTITY_VIEW, shown?: Rect): PanelsState {\n return {\n ...state,\n floats: state.floats.map((f): FloatAt => {\n if (f.id !== id || !!f.pinned === on) return f;\n // In view space: where it shows, else where it is stored; at its stored size.\n const seen = shown ? { ...f.rect, x: shown.x, y: shown.y } : f.pinned ? { ...f.rect } : toView(f.rect, view);\n return on ? { id, rect: seen, pinned: true } : { id, rect: toPage(seen, view) };\n }),\n };\n}\n\n/**\n * Store a column's width (the layout clamps it to its panels' limits). Resizing is a use: the column's panels are\n * the newest used, so give-way takes room from the other columns, not from the one being resized.\n */\nexport function resizeColumn(state: PanelsState, side: Side, index: number, width: number): PanelsState {\n const col = state.sides[side][index];\n if (!col || !Number.isFinite(width)) return state;\n const t = tick(state);\n const clock = { ...state.clock };\n for (const id of col.panels) clock[id] = { opened: clock[id]?.opened ?? 0, used: t };\n return { ...state, sides: { ...state.sides, [side]: state.sides[side].map((c, i) => (i === index ? { ...c, width: Math.max(0, width) } : c)) }, clock };\n}\n\n/** Store a float's rect (its own space). Resizing is a use. */\nexport function resizeFloat(state: PanelsState, id: string, rect: Rect): PanelsState {\n if (!state.floats.some((f) => f.id === id)) return state;\n return bump({ ...state, floats: state.floats.map((f) => (f.id === id ? { ...f, rect: { ...rect } } : f)) }, id, false);\n}\n\n/** A column's width as the layout takes it: its stored width clamped to its panels' limits (with `defs`). */\nexport function columnWidth(defs: readonly PanelDef[] | undefined, col: Column): number {\n if (!defs) return col.width;\n const ds = col.panels.map((id) => defOf(defs, id));\n const lo = Math.max(0, ...ds.map((d) => d?.width.min ?? 0));\n const hi = Math.max(lo, Math.min(...ds.map((d) => d?.width.max ?? Infinity)));\n return Math.min(Math.max(Number.isFinite(col.width) ? col.width : lo, lo), hi);\n}\n\n/**\n * Two states place the panels the same (columns, their panels and widths, floats and their rects; the clock aside).\n * With `defs`, widths compare as the layout takes them (clamped to the panels' limits), so a stored width past a\n * column's max is the same place as that max.\n */\nexport function samePlaces(a: PanelsState, b: PanelsState, defs?: readonly PanelDef[]): boolean {\n const cols = (s: PanelsState): string =>\n SIDES.map((side) =>\n s.sides[side]\n .map((c) => `${c.panels.join(\",\")}@${Math.round(columnWidth(defs, c))}${c.show === \"tabs\" ? `/tabs:${c.active ?? c.panels[0]}` : \"\"}`)\n .join(\"|\"),\n ).join(\"‖\");\n const fl = (s: PanelsState): string => s.floats.map((f) => `${f.id}@${Math.round(f.rect.x)},${Math.round(f.rect.y)},${Math.round(f.rect.width)},${Math.round(f.rect.height)}${f.pinned ? \"p\" : \"\"}`).join(\"|\");\n const bs = (s: PanelsState): string =>\n EDGES.map((e) => {\n const b = s.bands?.[e];\n return b ? `${b.panels.join(\",\")}@${Math.round(bandHeight(defs, b))}` : \"\";\n }).join(\"‖\");\n const set = (l: readonly string[]): string => [...l].sort().join(\",\");\n return cols(a) === cols(b) && bs(a) === bs(b) && fl(a) === fl(b) && set(a.folded) === set(b.folded) && set(a.kept) === set(b.kept) && set(a.closed) === set(b.closed);\n}\n","/**\n * `layoutPanels`: the panels' state, a stage and options in; geometry and structure out: every panel's rect, layer\n * and kind, the columns, the rails, the pages' rect, and coded notes on how it gave way. Pure: the same input always\n * lays out the same. How anything looks is the consumer's.\n *\n * - A column is full height and as wide as its stored width, clamped to its panels' limits. Inside it, a panel\n * folded by hand is a title bar (`options.bar` tall) and the open ones share the rest of the height equally.\n * - A column whose panels are all folded is railed: its panels become segments of its side's rail (one rail per\n * side, `options.rail` wide at the outer edge, segments in side order).\n * - With `options.fold` \"ride\", a column folded by hand on a side that still has an open column rides instead: its\n * panels become title bars stacked on top of the side's first open column (outer edge first), as wide as that\n * column, and its open panels share the rest of the height. The folded column keeps its stored place and width, and\n * the open columns lie as if it were gone. Only when every column on the side is folded does the side show its rail.\n * Give-way's folds always go to the rail.\n * - A float folded by hand is a title bar: its own x, y and width, `options.bar` tall, still a float (clamped as a\n * bar, `floating`); unfolding brings its full rect back, as the stored rect never changes.\n * - Give-way: when the open columns, the rails and `pagesMin` don't fit the stage width, columns shrink toward their\n * minimum, then whole columns fold to the rail, in the policy's order, until the pages fit. Columns holding a kept\n * panel come after every other column; if the pages still don't fit, they fold too (`kept-folded`). Folding by\n * give-way never writes `folded`, so a wider stage brings the column back.\n * - Floats: \"clamp\" keeps a float in the view at layout time (the state keeps the stored rect, so a larger view\n * brings it back where it was); \"free\" never moves one. A float's size is never scaled. A pinned float is in view\n * space and clamped against the view; an unpinned one has its position in page space, clamped so that its screen\n * rect at pan 0 fits the view, then moved by the view's offset and scale, so it scrolls with the page.\n */\n/*\n * Also (26.11.9):\n * - A tabbed column (`show` \"tabs\") draws a strip `options.tabs` tall on top (`PlacedColumn.strip`, each panel's\n * `tab` in it, panel order, equal widths); its active panel takes the rest and the others are hidden. With its\n * active panel folded it shows only the strip (the active panel is a \"bar\" there); with every panel folded it goes\n * to the rail (or rides) as a stack column does.\n * - Height give-way, opt-in by `PanelDef.height`: see `sectionHeights` in the layout (note `section-folded`).\n *\n * And (26.11.10), all opt-in by `options.bands` and `options.reserve`:\n * - Bands: a full-span band takes its height from the stage's top or bottom first, across the whole width; the\n * columns and rails lie in what is left. A between-span band runs between the innermost open column (or rail) on\n * each side. A \"reserved\" band shortens the pages; an \"overlay\" band lies over the pages (layer 5) and doesn't.\n * Its panels share its width equally, left to right (\"band\" rects); folded (by hand, or by give-way) it is one bar,\n * `options.bar` tall, and each panel a \"bar\" rect side by side.\n * - Height give-way: when the pages would be shorter than `pagesMinHeight` (counted after the top and bottom\n * reserves), reserved bands shrink toward their min, then fold to a bar, unkept before kept, in the policy's order,\n * bottom before top on a tie (`band-shrunk`, `band-folded`, `kept-folded` with `edge`); they leave the pages room\n * for the overlay bands' bars at least. Then the overlay bands give way the same way, together, until they leave\n * `pagesMinHeight` of the pages uncovered (so a top and a bottom one never meet). Give-way never writes `folded`.\n * Pages still short of the min (their rect's height, which overlay bands don't change): `pages-short`.\n * - Reserve: room kept clear along the pages' edges (`reserved`), inside the pages' area; the pages are what's left.\n * An overlay band lies next to the top or bottom reserve, on the pages' side, never over it; the left and right\n * reserves lie between the overlay bands.\n * - A band in the state on an edge the options don't enable: its panels are left out (`band-off`).\n */\nimport { rect, type Rect, type Size } from \"../geometry\";\nimport { DEFAULT_PANELS_OPTIONS, EDGES, SIDES, bandSize, defOf, floatSize, toView, type Edge, type PanelDef, type PanelsOptions, type PanelsState, type Side } from \"./model\";\n\n/**\n * Where a panel is, structurally: an open part of a column, an open part of a band, a folded title bar (in a column,\n * riding on one, in a folded band, or a folded float), a segment of a rail (the panel itself isn't laid out), or a\n * float.\n */\nexport type PanelKind = \"column\" | \"band\" | \"bar\" | \"segment\" | \"float\";\n\nexport interface PlacedPanel {\n /** Stage px; for a segment, the segment's rect in its rail. */\n readonly rect: Rect;\n readonly kind: PanelKind;\n /** Columns, rails and reserved bands 0, overlay bands 5, floats 10 and up (a later float on top). */\n readonly layer: number;\n /** Not drawn as a panel: in a rail (only its segment shows), or a tab that isn't showing (only its `tab`). */\n readonly hidden: boolean;\n /** Folded by hand (a bar, or a segment of a column folded by hand), or by give-way (a segment). */\n readonly folded: null | \"hand\" | \"auto\";\n /** Kept open. */\n readonly kept: boolean;\n /** A pinned float. */\n readonly pinned: boolean;\n /** It floats (open, or folded to a bar). */\n readonly floating: boolean;\n /** Docked: its side and column index (the state's). */\n readonly side?: Side;\n readonly column?: number;\n /** A riding bar: the index of the column it rides on (`options.fold` \"ride\"). */\n readonly rides?: number;\n /** In a tabbed column: its tab's rect in the strip (panel order, equal widths). */\n readonly tab?: Rect;\n /** A float the clamp moved or resized. */\n readonly clamped?: boolean;\n /** In a band: its edge and its index in the state's band (left to right). */\n readonly edge?: Edge;\n readonly index?: number;\n}\n\n/** A band as laid out. */\nexport interface PlacedBand {\n readonly edge: Edge;\n /** The band's rect (a bar when folded). */\n readonly rect: Rect;\n /** Its stored height clamped to its panels' limits, and those limits. */\n readonly height: number;\n readonly min: number;\n readonly max: number;\n /** null: open; \"hand\": its panels folded by hand; \"auto\": folded by give-way. */\n readonly folded: null | \"hand\" | \"auto\";\n /** Shrunk by give-way below its height. */\n readonly shrunk: boolean;\n /** It holds a kept panel. */\n readonly kept: boolean;\n readonly mode: \"reserved\" | \"overlay\";\n readonly span: \"between\" | \"full\";\n /** The shown panels, left to right. */\n readonly panels: readonly string[];\n}\n\n/** A reserve's edge. */\nexport type ReserveEdge = \"top\" | \"right\" | \"bottom\" | \"left\";\n\nexport interface PlacedColumn {\n readonly side: Side;\n /** The column's index in the state. */\n readonly index: number;\n /** Its rect (zero wide when railed). */\n readonly rect: Rect;\n /** Its stored width clamped to its panels' limits, and those limits. */\n readonly width: number;\n readonly min: number;\n readonly max: number;\n /** null: open; \"hand\": all its panels folded by hand; \"auto\": folded by give-way. */\n readonly folded: null | \"hand\" | \"auto\";\n /** Shrunk by give-way below its width. */\n readonly shrunk: boolean;\n /** It holds a kept panel. */\n readonly kept: boolean;\n /** The shown panels, top to bottom. */\n readonly panels: readonly string[];\n /** Riding: the index of the column its bars ride on; its rect is the bars'. */\n readonly rides?: number;\n /** How it shows its panels (default \"stack\"). */\n readonly show?: \"stack\" | \"tabs\";\n /** Tabbed and laid out: its strip of tabs, and the panel it shows. */\n readonly strip?: Rect;\n readonly active?: string;\n}\n\nexport interface PlacedRail {\n readonly side: Side;\n readonly rect: Rect;\n readonly segments: readonly { readonly id: string; readonly rect: Rect }[];\n}\n\nexport type PanelsNoteCode =\n | \"column-shrunk\"\n | \"column-folded\"\n | \"kept-folded\"\n | \"section-folded\"\n | \"pages-under-min\"\n | \"float-clamped\"\n | \"float-resized\"\n | \"band-shrunk\"\n | \"band-folded\"\n | \"band-off\"\n | \"pages-short\";\n\n/** One note on a layout: a code and its data. `kept-folded` carries `side` and `column` for a column, `edge` for a band. */\nexport type PanelsNote =\n | { readonly code: \"column-shrunk\"; readonly side: Side; readonly column: number; readonly items: readonly string[]; readonly from: number; readonly to: number }\n | { readonly code: \"column-folded\" | \"kept-folded\" | \"section-folded\"; readonly side: Side; readonly column: number; readonly items: readonly string[] }\n | { readonly code: \"pages-under-min\"; readonly width: number; readonly min: number }\n | { readonly code: \"float-clamped\" | \"float-resized\"; readonly items: readonly string[] }\n | { readonly code: \"band-shrunk\"; readonly edge: Edge; readonly items: readonly string[]; readonly from: number; readonly to: number }\n | { readonly code: \"band-folded\" | \"kept-folded\" | \"band-off\"; readonly edge: Edge; readonly items: readonly string[] }\n | { readonly code: \"pages-short\"; readonly height: number; readonly min: number };\n\nexport interface PanelsLayout {\n readonly items: Map<string, PlacedPanel>;\n /** The shown columns in side order (left outer → inner, then right outer → inner). */\n readonly columns: readonly PlacedColumn[];\n readonly rails: Partial<Record<Side, PlacedRail>>;\n readonly notes: readonly PanelsNote[];\n /** What is left for the documents. */\n readonly pages: Rect;\n /** The bands laid out (an enabled edge with shown panels). */\n readonly bands: Readonly<Partial<Record<Edge, PlacedBand>>>;\n /** The room kept clear along the pages' edges (an edge with a reserve over 0). */\n readonly reserved: Readonly<Partial<Record<ReserveEdge, Rect>>>;\n}\n\ninterface BandIn {\n readonly edge: Edge;\n readonly panels: readonly string[];\n /** Its index in the state's band, per shown panel. */\n readonly at: readonly number[];\n readonly min: number;\n readonly max: number;\n readonly height: number;\n readonly hand: boolean;\n readonly kept: boolean;\n readonly age: number;\n readonly mode: \"reserved\" | \"overlay\";\n readonly span: \"between\" | \"full\";\n}\n\ninterface Col {\n readonly side: Side;\n readonly index: number;\n readonly panels: readonly string[];\n readonly min: number;\n readonly max: number;\n readonly width: number;\n readonly hand: boolean;\n readonly kept: boolean;\n readonly age: number;\n readonly show?: \"stack\" | \"tabs\";\n /** Tabbed: the panel it shows (its stored one when shown, else its first). */\n readonly active?: string;\n}\n\nconst clamp = (v: number, lo: number, hi: number): number => Math.min(Math.max(v, lo), Math.max(lo, hi));\n\n/** The order columns give way in: unkept before kept, then the policy (oldest or newest), outer first, left first. */\nexport function giveWayOrder<C extends { readonly side: Side; readonly index: number; readonly kept: boolean; readonly age: number }>(cols: readonly C[], order: \"oldest\" | \"newest\"): C[] {\n return [...cols].sort((a, b) => Number(a.kept) - Number(b.kept) || (order === \"oldest\" ? a.age - b.age : b.age - a.age) || a.index - b.index || SIDES.indexOf(a.side) - SIDES.indexOf(b.side));\n}\n\nexport function layoutPanels(defs: readonly PanelDef[], state: PanelsState, stage: Size, options: Partial<PanelsOptions> = {}): PanelsLayout {\n const opt: PanelsOptions = { ...DEFAULT_PANELS_OPTIONS, ...options };\n const W = stage.width;\n const H = stage.height;\n const closed = new Set(state.closed);\n const folded = new Set(state.folded);\n const kept = new Set(state.kept);\n const by = opt.giveWay.by;\n const ride = opt.fold === \"ride\";\n const px = (v: number | undefined): number => (typeof v === \"number\" && Number.isFinite(v) ? Math.max(0, v) : 0);\n // Options passed as undefined fall back to their defaults.\n const reserveOpt = opt.reserve ?? {};\n const bandOpts = opt.bands ?? {};\n const minH = typeof opt.pagesMinHeight === \"number\" ? opt.pagesMinHeight : DEFAULT_PANELS_OPTIONS.pagesMinHeight;\n const res = { top: px(reserveOpt.top), right: px(reserveOpt.right), bottom: px(reserveOpt.bottom), left: px(reserveOpt.left) };\n\n // The bands: an enabled edge with shown panels. One on an edge the options don't enable is left out.\n const bandsIn: BandIn[] = [];\n const offNotes: PanelsNote[] = [];\n for (const edge of EDGES) {\n const b = state.bands?.[edge];\n if (!b) continue;\n const panels = b.panels.filter((id) => !closed.has(id));\n if (panels.length === 0) continue;\n const o = bandOpts[edge];\n if (!o) {\n offNotes.push({ code: \"band-off\", edge, items: panels });\n continue;\n }\n const ds = panels.map((id) => bandSize(defOf(defs, id)));\n const min = Math.max(0, ...ds.map((d) => d.min));\n const max = Math.max(min, Math.min(...ds.map((d) => d.max)));\n const height = clamp(Number.isFinite(b.height) ? b.height : min, min, max);\n const age = Math.max(...panels.map((id) => state.clock[id]?.[by] ?? 0));\n bandsIn.push({ edge, panels, at: panels.map((id) => b.panels.indexOf(id)), min, max, height, hand: panels.every((id) => folded.has(id)), kept: panels.some((id) => kept.has(id)), age, mode: o.mode, span: o.span });\n }\n\n // Height give-way. The reserved bands and the top and bottom reserves leave the pages at least `pagesMinHeight`: fold\n // the fewest reserved bands in order that let them, shrinking the rest in order toward their min. Then the overlay\n // bands, together, leave that much of the pages they lie over uncovered.\n const bOrder = bandsIn\n .filter((b) => !b.hand)\n .sort((a, b) => Number(a.kept) - Number(b.kept) || (opt.giveWay.order === \"oldest\" ? a.age - b.age : b.age - a.age) || EDGES.indexOf(b.edge) - EDGES.indexOf(a.edge));\n const gh = { auto: new Set<BandIn>(), heights: new Map<BandIn, number>() };\n /** Fit `list` (in give-way order) into `room` px: fold the fewest in order, shrink the rest in order. */\n const fitH = (list: readonly BandIn[], room: number): void => {\n const order = bOrder.filter((b) => list.includes(b));\n const hands = list.length - order.length;\n const fit = (k: number): { auto: Set<BandIn>; heights: Map<BandIn, number>; excess: number } => {\n const auto = new Set(order.slice(0, k));\n const heights = new Map(order.filter((b) => !auto.has(b)).map((b) => [b, b.height]));\n let excess = [...heights.values()].reduce((a, b) => a + b, 0) + (hands + auto.size) * opt.bar - room;\n for (const b of order) {\n if (excess <= 0 || auto.has(b)) continue;\n const take = Math.min(excess, b.height - b.min);\n if (take > 0) {\n heights.set(b, b.height - take);\n excess -= take;\n }\n }\n return { auto, heights, excess };\n };\n let g = fit(0);\n for (let k = 1; g.excess > 0 && k <= order.length; k++) g = fit(k);\n for (const b of g.auto) gh.auto.add(b);\n for (const [b, h] of g.heights) gh.heights.set(b, h);\n };\n const reservedIn = bandsIn.filter((b) => b.mode === \"reserved\");\n const overlayIn = bandsIn.filter((b) => b.mode === \"overlay\");\n // The pages keep at least room for the overlay bands' bars, so a folded overlay band never reaches past them.\n fitH(reservedIn, H - res.top - res.bottom - Math.max(minH, overlayIn.length * opt.bar));\n const bandH = (b: BandIn | undefined): number => (b ? (gh.heights.get(b) ?? opt.bar) : 0);\n // The pages' height: what the reserves and the reserved bands leave.\n const pagesH = H - res.top - res.bottom - reservedIn.reduce((a, b) => a + bandH(b), 0);\n // The overlay bands together, so that a top and a bottom one never meet over the pages.\n fitH(overlayIn, pagesH - minH);\n const topB = bandsIn.find((b) => b.edge === \"top\");\n const botB = bandsIn.find((b) => b.edge === \"bottom\");\n const hT = bandH(topB);\n const hB = bandH(botB);\n // The columns' and rails' height: what the full-span bands (and, under an overlay one, its reserve) leave.\n const colTop = topB?.span === \"full\" ? (topB.mode === \"overlay\" ? res.top : 0) + hT : 0;\n const colBot = botB?.span === \"full\" ? H - (botB.mode === \"overlay\" ? res.bottom : 0) - hB : H;\n const CH = Math.max(0, colBot - colTop);\n\n // The shown columns.\n const cols: Col[] = [];\n for (const side of SIDES) {\n state.sides[side].forEach((c, index) => {\n const panels = c.panels.filter((id) => !closed.has(id));\n if (panels.length === 0) return;\n const ds = panels.map((id) => defOf(defs, id));\n const min = Math.max(0, ...ds.map((d) => d?.width.min ?? 0));\n const max = Math.max(min, Math.min(...ds.map((d) => d?.width.max ?? Infinity)));\n const width = clamp(Number.isFinite(c.width) ? c.width : min, min, max);\n const age = Math.max(...panels.map((id) => state.clock[id]?.[by] ?? 0));\n const tabs = c.show === \"tabs\" ? { show: \"tabs\" as const, active: c.active !== undefined && panels.includes(c.active) ? c.active : panels[0]! } : {};\n cols.push({ side, index, panels, min, max, width, hand: panels.every((id) => folded.has(id)), kept: panels.some((id) => kept.has(id)), age, ...tabs });\n });\n }\n\n /**\n * A stack column's sections, top to bottom, `room` px tall. Without a `height` def among its open sections they\n * share the room equally (bars `opt.bar` tall). With one: each gets its natural height and the last open one the rest\n * (never under its min; sections without a def share what is left). Short of room, open sections fold to bars by\n * give-way (policy order, kept last, never the last open one); their natural heights give way toward their mins\n * before the last one goes under its min.\n */\n const sectionHeights = (c: Col, room: number): Map<string, { height: number; folded: null | \"hand\" | \"auto\" }> => {\n const out = new Map<string, { height: number; folded: null | \"hand\" | \"auto\" }>();\n const open0 = c.panels.filter((id) => !folded.has(id));\n const hOf = (id: string) => defOf(defs, id)?.height;\n const auto = new Set<string>();\n if (open0.some((id) => hOf(id))) {\n const last = open0.at(-1)!;\n // A section without a def never goes under a bar's height: that is its min.\n const minOf = (id: string): number => hOf(id)?.min ?? opt.bar;\n const fits = (): boolean => (c.panels.length - open0.length + auto.size) * opt.bar + open0.filter((id) => !auto.has(id)).reduce((a, id) => a + minOf(id), 0) <= room;\n const rank = (ids: readonly string[]): string[] =>\n [...ids].sort((a, b) => {\n const age = (id: string): number => state.clock[id]?.[by] ?? 0;\n return Number(kept.has(a)) - Number(kept.has(b)) || (opt.giveWay.order === \"oldest\" ? age(a) - age(b) : age(b) - age(a)) || c.panels.indexOf(a) - c.panels.indexOf(b);\n });\n for (const id of rank(open0.filter((x) => x !== last))) {\n if (fits()) break;\n // Folding a section whose min is no more than a bar gains nothing: skip it.\n if (minOf(id) > opt.bar) auto.add(id);\n }\n const open = open0.filter((id) => !auto.has(id));\n const space = room - (c.panels.length - open.length) * opt.bar;\n const fixed = open.filter((id) => id !== last && hOf(id));\n const sharers = open.filter((id) => id === last || !hOf(id));\n const h = new Map(fixed.map((id) => [id, hOf(id)!.natural]));\n let rest = space - fixed.reduce((a, id) => a + h.get(id)!, 0);\n // The sharers (the last section and those without a def) need their mins: the fixed sections' natural heights\n // give way toward their mins first, in policy order.\n const need = sharers.reduce((a, id) => a + minOf(id), 0);\n for (const id of rank(fixed)) {\n if (rest >= need) break;\n const take = Math.min(need - rest, h.get(id)! - minOf(id));\n h.set(id, h.get(id)! - take);\n rest += take;\n }\n if (rest >= need) {\n // Equal shares, raised to each sharer's min where a share falls under it.\n let pool = [...sharers];\n let left = rest;\n for (;;) {\n const share = left / pool.length;\n const under = pool.filter((id) => minOf(id) > share);\n if (under.length === 0) {\n for (const id of pool) h.set(id, share);\n break;\n }\n for (const id of under) h.set(id, minOf(id));\n left -= under.reduce((a, id) => a + minOf(id), 0);\n pool = pool.filter((id) => !under.includes(id));\n }\n } else {\n // Short even for the mins: the last section first, the others share what is left.\n const lastH = Math.max(0, Math.min(minOf(last), rest));\n for (const id of sharers) h.set(id, id === last ? lastH : Math.max(0, rest - lastH) / (sharers.length - 1));\n }\n for (const id of c.panels) out.set(id, folded.has(id) ? { height: opt.bar, folded: \"hand\" } : auto.has(id) ? { height: opt.bar, folded: \"auto\" } : { height: Math.max(0, h.get(id)!), folded: null });\n return out;\n }\n const bars = c.panels.length - open0.length;\n const share = Math.max(0, (room - bars * opt.bar) / open0.length);\n for (const id of c.panels) out.set(id, folded.has(id) ? { height: opt.bar, folded: \"hand\" } : { height: share, folded: null });\n return out;\n };\n\n // Give-way: fold the fewest columns in order that let the pages fit, shrinking the rest in order toward their minimum.\n const order = giveWayOrder(\n cols.filter((c) => !c.hand),\n opt.giveWay.order,\n );\n const fit = (k: number): { auto: Set<Col>; widths: Map<Col, number>; excess: number } => {\n const auto = new Set(order.slice(0, k));\n // Riding, a side's hand-folded columns need no rail while one of its columns stays open.\n const open = (side: Side): boolean => cols.some((c) => c.side === side && !c.hand && !auto.has(c));\n const railed = (side: Side): boolean => cols.some((c) => c.side === side && (auto.has(c) || (c.hand && !(ride && open(side)))));\n const widths = new Map(order.filter((c) => !auto.has(c)).map((c) => [c, c.width]));\n let excess = [...widths.values()].reduce((a, b) => a + b, 0) + SIDES.filter(railed).length * opt.rail + opt.pagesMin + res.left + res.right - W;\n for (const c of order) {\n if (excess <= 0 || auto.has(c)) continue;\n const take = Math.min(excess, c.width - c.min);\n if (take > 0) {\n widths.set(c, c.width - take);\n excess -= take;\n }\n }\n return { auto, widths, excess };\n };\n let g = fit(0);\n for (let k = 1; g.excess > 0 && k <= order.length; k++) g = fit(k);\n\n const notes: PanelsNote[] = [];\n for (const c of order) {\n const w = g.widths.get(c);\n if (w !== undefined && w < c.width) notes.push({ code: \"column-shrunk\", side: c.side, column: c.index, items: c.panels, from: c.width, to: w });\n }\n for (const c of order) if (g.auto.has(c)) notes.push({ code: c.kept ? \"kept-folded\" : \"column-folded\", side: c.side, column: c.index, items: c.panels });\n\n // Positions: rails at the outer edges, open columns inward from them, the pages between.\n const items = new Map<string, PlacedPanel>();\n const placedCols: PlacedColumn[] = [];\n const rails: Partial<Record<Side, PlacedRail>> = {};\n let x0 = 0;\n let x1 = W;\n for (const side of SIDES) {\n const mine = cols.filter((c) => c.side === side);\n const open = mine.filter((c) => !c.hand && !g.auto.has(c));\n // Riding: the side's hand-folded columns, while it has an open column to ride on (the first, outer edge first).\n const host = ride ? open[0] : undefined;\n const riders = host ? mine.filter((c) => c.hand) : [];\n const inRail = mine.filter((c) => (c.hand && !riders.includes(c)) || g.auto.has(c));\n if (inRail.length) {\n const r = side === \"left\" ? rect(0, colTop, opt.rail, CH) : rect(W - opt.rail, colTop, opt.rail, CH);\n const segments = inRail.flatMap((c) => c.panels).map((id, i) => ({ id, rect: rect(r.x, colTop + opt.railInset + i * opt.segment, opt.rail, opt.segment) }));\n rails[side] = { side, rect: r, segments };\n for (const s of segments) {\n const c = inRail.find((x) => x.panels.includes(s.id))!;\n items.set(s.id, { rect: s.rect, kind: \"segment\", layer: 0, hidden: true, folded: c.hand ? \"hand\" : \"auto\", kept: kept.has(s.id), pinned: false, floating: false, side, column: c.index });\n }\n if (side === \"left\") x0 = opt.rail;\n else x1 = W - opt.rail;\n }\n // The open columns first (riding bars need their host's rect), then the folded ones in state order.\n const at = new Map<Col, Rect>();\n for (const c of mine) {\n const w = g.widths.get(c);\n if (w === undefined || riders.includes(c)) continue;\n if (side === \"left\") {\n at.set(c, rect(x0, colTop, w, CH));\n x0 += w;\n } else {\n x1 -= w;\n at.set(c, rect(x1, colTop, w, CH));\n }\n }\n const riding = riders.flatMap((c) => c.panels.map((id) => ({ id, c })));\n const top = riding.length * opt.bar;\n for (const c of mine) {\n const w = g.widths.get(c);\n const folded1 = c.hand ? \"hand\" : g.auto.has(c) ? \"auto\" : null;\n const base = { side, index: c.index, width: c.width, min: c.min, max: c.max, folded: folded1, kept: c.kept, panels: c.panels } as const;\n if (riders.includes(c)) {\n const hr = at.get(host!)!;\n const first = riding.findIndex((x) => x.c === c);\n c.panels.forEach((id, i) =>\n items.set(id, { rect: rect(hr.x, colTop + (first + i) * opt.bar, hr.width, opt.bar), kind: \"bar\", layer: 0, hidden: false, folded: \"hand\", kept: kept.has(id), pinned: false, floating: false, side, column: c.index, rides: host!.index }),\n );\n placedCols.push({ ...base, rect: rect(hr.x, colTop + first * opt.bar, hr.width, c.panels.length * opt.bar), shrunk: false, rides: host!.index });\n continue;\n }\n const r = at.get(c) ?? rect(side === \"left\" ? x0 : x1, colTop, 0, CH);\n // The host shares what the riding bars leave.\n const y0 = colTop + (c === host ? top : 0);\n const tabbed = c.show === \"tabs\";\n const strip = rect(r.x, y0, r.width, opt.tabs);\n const shown = tabbed && w !== undefined ? { strip, active: c.active! } : {};\n placedCols.push({ ...base, rect: r, shrunk: w !== undefined && w < c.width, ...(tabbed ? { show: \"tabs\" as const } : {}), ...shown });\n if (w === undefined) continue;\n const panel = (id: string, to: Rect, kind: PanelKind, f: null | \"hand\" | \"auto\", more: { tab?: Rect; hidden?: boolean } = {}): void => {\n items.set(id, { rect: to, kind, layer: 0, hidden: more.hidden ?? false, folded: f, kept: kept.has(id), pinned: false, floating: false, side, column: c.index, ...(more.tab ? { tab: more.tab } : {}) });\n };\n if (tabbed) {\n // One panel shows under the strip; the others are its hidden tabs. Its active panel folded: only the strip.\n const body = rect(r.x, y0 + opt.tabs, r.width, Math.max(0, colBot - y0 - opt.tabs));\n const shade = folded.has(c.active!);\n const tw = r.width / c.panels.length;\n c.panels.forEach((id, i) => {\n const tab = rect(r.x + i * tw, y0, tw, opt.tabs);\n if (id === c.active) panel(id, shade ? strip : body, shade ? \"bar\" : \"column\", shade ? \"hand\" : null, { tab });\n else panel(id, body, \"column\", folded.has(id) ? \"hand\" : null, { tab, hidden: true });\n });\n continue;\n }\n const hs = sectionHeights(c, colBot - y0);\n let y = y0;\n for (const id of c.panels) {\n const s = hs.get(id)!;\n panel(id, rect(r.x, y, r.width, s.height), s.folded ? \"bar\" : \"column\", s.folded);\n y += s.height;\n }\n for (const id of c.panels) if (hs.get(id)!.folded === \"auto\") notes.push({ code: \"section-folded\", side, column: c.index, items: [id] });\n }\n }\n\n // The bands' notes, in give-way order.\n for (const b of bOrder) {\n const h = gh.heights.get(b);\n if (h !== undefined && h < b.height) notes.push({ code: \"band-shrunk\", edge: b.edge, items: b.panels, from: b.height, to: h });\n }\n for (const b of bOrder) if (gh.auto.has(b)) notes.push({ code: b.kept ? \"kept-folded\" : \"band-folded\", edge: b.edge, items: b.panels });\n\n // The pages' outer edges: a reserved band shortens them, an overlay band doesn't. Then the reserve comes off them:\n // an overlay band lies next to the top or bottom reserve, on the pages' side (never over it), and the left and right\n // reserves lie between the overlay bands.\n const pw = Math.max(0, x1 - x0);\n const pTop = topB?.mode === \"reserved\" ? hT : 0;\n const pBot = botB?.mode === \"reserved\" ? H - hB : H;\n const reserved: Partial<Record<ReserveEdge, Rect>> = {};\n const iTop = pTop + res.top + (topB?.mode === \"overlay\" ? hT : 0);\n const iBot = pBot - res.bottom - (botB?.mode === \"overlay\" ? hB : 0);\n if (res.top > 0) reserved.top = rect(x0, pTop, pw, res.top);\n if (res.right > 0) reserved.right = rect(x0 + pw - res.right, iTop, res.right, Math.max(0, iBot - iTop));\n if (res.bottom > 0) reserved.bottom = rect(x0, pBot - res.bottom, pw, res.bottom);\n if (res.left > 0) reserved.left = rect(x0, iTop, res.left, Math.max(0, iBot - iTop));\n const pages = rect(x0 + res.left, pTop + res.top, Math.max(0, pw - res.left - res.right), Math.max(0, pBot - res.bottom - pTop - res.top));\n if (pages.width < opt.pagesMin) notes.push({ code: \"pages-under-min\", width: pages.width, min: opt.pagesMin });\n // Short: the pages' rect itself (overlay bands don't shorten it; how far one covers the pages is its own\n // band-shrunk or band-folded note).\n if ((bandsIn.length || res.top + res.bottom > 0) && pages.height < minH - 1e-9) notes.push({ code: \"pages-short\", height: pages.height, min: minH });\n\n // The bands' rects and their panels: equal shares of the width, left to right; folded, one bar.\n const bands: Partial<Record<Edge, PlacedBand>> = {};\n for (const b of bandsIn) {\n const h = bandH(b);\n const full = b.span === \"full\";\n const over = b.mode === \"overlay\";\n const y = b.edge === \"top\" ? (over ? res.top : 0) : over ? H - res.bottom - h : H - h;\n const r = full ? rect(0, y, W, h) : rect(x0, y, pw, h);\n const f: null | \"hand\" | \"auto\" = b.hand ? \"hand\" : gh.auto.has(b) ? \"auto\" : null;\n const hh = gh.heights.get(b);\n bands[b.edge] = { edge: b.edge, rect: r, height: b.height, min: b.min, max: b.max, folded: f, shrunk: hh !== undefined && hh < b.height, kept: b.kept, mode: b.mode, span: b.span, panels: b.panels };\n const share = r.width / b.panels.length;\n b.panels.forEach((id, i) =>\n items.set(id, { rect: rect(r.x + i * share, r.y, share, h), kind: f ? \"bar\" : \"band\", layer: over ? 5 : 0, hidden: false, folded: f, kept: kept.has(id), pinned: false, floating: false, edge: b.edge, index: b.at[i]! }),\n );\n }\n\n // Floats, clamped unless free. A float's size is screen px in both spaces (never scaled); only an unpinned float's\n // position is in page space. The clamp keeps the SCREEN rect in the view: a pinned float where it is, an unpinned\n // one as it shows at pan 0, so it still scrolls with the page. In page units (k = the scale, 1 when pinned) a\n // screen interval [lo, hi] is [lo / k, hi / k].\n state.floats.forEach((f, i) => {\n if (closed.has(f.id)) return;\n // Folded by hand: a title bar at its own place and width (the stored rect keeps its height).\n const shaded = folded.has(f.id);\n const at = shaded ? { ...f.rect, height: opt.bar } : f.rect;\n const k = f.pinned ? 1 : opt.view.scale;\n const r = { ...at };\n if (opt.floats === \"clamp\") {\n const lim = floatSize(defOf(defs, f.id)).min;\n r.width = Math.max(lim.width, Math.min(r.width, W));\n if (!shaded) r.height = Math.max(lim.height, Math.min(r.height, H));\n if (r.width !== at.width || r.height !== at.height) notes.push({ code: \"float-resized\", items: [f.id] });\n // Fits: wholly in the view. Too big even at its minimum: its title bar stays in, and `floatVisible` px of its width.\n r.x = r.width <= W ? clamp(r.x, 0, (W - r.width) / k) : clamp(r.x, (opt.floatVisible - r.width) / k, (W - opt.floatVisible) / k);\n r.y = r.height <= H ? clamp(r.y, 0, (H - r.height) / k) : clamp(r.y, 0, (H - opt.bar) / k);\n if (r.x !== at.x || r.y !== at.y) notes.push({ code: \"float-clamped\", items: [f.id] });\n }\n const clamped = r.x !== at.x || r.y !== at.y || r.width !== at.width || r.height !== at.height;\n items.set(f.id, {\n rect: f.pinned ? r : toView(r, opt.view),\n kind: shaded ? \"bar\" : \"float\",\n layer: 10 + i,\n hidden: false,\n folded: shaded ? \"hand\" : null,\n kept: false,\n pinned: !!f.pinned,\n floating: true,\n ...(clamped ? { clamped: true } : {}),\n });\n });\n\n notes.push(...offNotes);\n return { items, columns: placedCols, rails, notes, pages, bands, reserved };\n}\n","/**\n * The drop targets for dragging a panel, in the shape @n-uf/motion/drag takes (`{ id, priority, hit, slot?, free? }`),\n * worked out from the state with the panel lifted out:\n *\n * - `column:<side>:<i>` (priority 2): a band across the line between two columns (or a side's edge): a new column\n * there, as wide as the panel's own width.\n * - `into:<side>:<i>` (2): a column's area: the panel stacks at its bottom.\n * - `into:<side>:<i>:<k>` (2), opt-in (`stackSlots`): before the stacked column's member k. The column's area is split\n * at its members' middles: the top half of member k (and the lower half of the one above) goes before k, and\n * `into:<side>:<i>` keeps only what lies below the last member's middle. `marker` is the line where the panel's top\n * lands after the drop, for the app to draw. k counts closed members too (they keep their place in the column's\n * list); only the members shown get slots. A tabbed column keeps its one `into` target.\n * - `rail:<side>` (1): the side's rail, or its outer edge: the panel docks folded.\n * - `float` (3, free): anywhere; it floats where it is let go, kept in the view as the float option says.\n * - `band:<edge>:<i>` (2), for each edge with a band (`options.bands`): the slots between a band's panels and at both\n * ends (the band's area split at its panels' middles). `band:<edge>` (2): an empty enabled edge, a strip `2 × bar`\n * tall along it inside the pages' area.\n *\n * A place the panel may not take (its def's `sides` and `floats`, and `allows`) is no target, and neither is its own\n * place (a drop there changes nothing). Targets carry a structured `place`, never words: the consumer names them.\n */\nimport { rect, type Point, type Rect, type Size } from \"../geometry\";\nimport type { Target } from \"../targets/target\";\nimport { layoutPanels, type PanelsLayout } from \"./layout\";\nimport { DEFAULT_PANELS_OPTIONS, EDGES, SIDES, defOf, dock, dockBand, float, floatSize, liftPanel, ownWidth, samePlaces, toPage, whereIs, type Edge, type PanelDef, type PanelsOptions, type PanelsState, type Side } from \"./model\";\n\n/** Where a drop puts a panel. `index` is a column (or band panel) index in the state with the panel lifted out. */\nexport type PanelPlace =\n | { readonly kind: \"column\"; readonly side: Side; readonly index: number }\n | {\n readonly kind: \"into\";\n readonly side: Side;\n readonly index: number;\n /** Before the column's member at this index (in the state with the panel lifted out); left out: at its bottom. */\n readonly at?: number;\n }\n | { readonly kind: \"rail\"; readonly side: Side }\n | { readonly kind: \"band\"; readonly edge: Edge; readonly index: number }\n | { readonly kind: \"float\" };\n\nexport interface PanelTarget extends Target {\n /** The panel dragged. */\n readonly panel: string;\n readonly place: PanelPlace;\n /** Its rank in reading order (left to right across the stage, floating last). */\n readonly order: number;\n /** The state a drop here makes, with the pointer at `p` holding the panel at `grab` from its top-left corner. */\n readonly make: (p: Point, grab: Point) => PanelsState;\n /**\n * With `stackSlots`, on `into` targets of a stacked column: the line where the panel's top lands after the drop (the\n * column re-shares its height, so this is the drop's layout, not today's gap), as a rect zero tall and as wide as\n * the column. `panelDrop(...).slot` is the whole rect.\n */\n readonly marker?: Rect;\n}\n\nexport interface PanelTargetInput {\n readonly defs: readonly PanelDef[];\n /** The state as it is, the panel still in its place. */\n readonly state: PanelsState;\n readonly id: string;\n readonly stage: Size;\n readonly options?: Partial<PanelsOptions>;\n /** Places the panel may go beyond its def's rules (default: all of them). */\n readonly allows?: (id: string, place: PanelPlace) => boolean;\n /** Drops into a stacked column may go before any of its members (`into` targets with `at`); default: the bottom only. */\n readonly stackSlots?: boolean;\n}\n\n/** How far a column band reaches on each side of its line, px; how wide a side's edge takes a rail drop when it has no rail. */\nexport const COLUMN_REACH = 22;\nexport const RAIL_EDGE = 10;\n\n/**\n * A place's rank in reading order: the left side outer to inner, the right side inner to outer, then the top band and\n * the bottom band left to right, floating last.\n */\nexport function placeRank(place: PanelPlace): number {\n switch (place.kind) {\n case \"float\":\n return 3000;\n case \"band\":\n return (place.edge === \"top\" ? 2000 : 2500) + Math.min(place.index, 499);\n case \"rail\":\n return place.side === \"left\" ? 0 : 1999;\n case \"column\":\n return place.side === \"left\" ? 1 + 2 * place.index : 1998 - 2 * place.index;\n case \"into\": {\n const base = place.side === \"left\" ? 2 + 2 * place.index : 1997 - 2 * place.index;\n // Before a member: top to bottom, ahead of the column's bottom.\n return place.at === undefined ? base : base - 0.5 + Math.min(Math.max(0, place.at), 499) / 1000;\n }\n }\n}\n\n/**\n * Where a panel is now, as a place (a float, a column of its own, or stacked in one); null when placed nowhere. With\n * `stackSlots`, a panel stacked in a column says its position there as `at` (a tabbed column's panel never does).\n */\nexport function homePlace(state: PanelsState, id: string, options: { readonly stackSlots?: boolean } = {}): PanelPlace | null {\n const w = whereIs(state, id);\n if (w.kind === \"float\") return { kind: \"float\" };\n if (w.kind === \"none\") return null;\n if (w.kind === \"band\") return { kind: \"band\", edge: w.edge, index: w.index };\n const col = state.sides[w.side][w.index]!;\n if (col.panels.length === 1) return { kind: \"column\", side: w.side, index: w.index };\n return options.stackSlots && col.show !== \"tabs\" ? { kind: \"into\", side: w.side, index: w.index, at: col.panels.indexOf(id) } : { kind: \"into\", side: w.side, index: w.index };\n}\n\nconst cut = (x0: number, x1: number, lo: number, hi: number): [number, number] => [Math.max(x0, lo), Math.min(x1, hi)];\n\n/** The targets for dragging `input.id`, in reading order. */\nexport function panelTargets(input: PanelTargetInput): PanelTarget[] {\n const { defs, state, id, stage } = input;\n const opt: PanelsOptions = { ...DEFAULT_PANELS_OPTIONS, ...input.options };\n const def = defOf(defs, id);\n const s0 = liftPanel(state, id);\n const l0 = layoutPanels(defs, s0, stage, opt);\n const width = ownWidth(defs, state, id);\n const W = stage.width;\n const H = stage.height;\n const R = COLUMN_REACH;\n // Options passed as undefined fall back to their defaults.\n const bandOpts = opt.bands ?? {};\n const reserve = opt.reserve ?? {};\n const px = (v: number | undefined): number => (typeof v === \"number\" && Number.isFinite(v) ? Math.max(0, v) : 0);\n const out: PanelTarget[] = [];\n const idOf = (place: PanelPlace): string => {\n switch (place.kind) {\n case \"float\":\n return \"float\";\n case \"rail\":\n return `rail:${place.side}`;\n case \"band\":\n return s0.bands?.[place.edge] ? `band:${place.edge}:${place.index}` : `band:${place.edge}`;\n case \"into\":\n return place.at === undefined ? `into:${place.side}:${place.index}` : `into:${place.side}:${place.index}:${place.at}`;\n default:\n return `${place.kind}:${place.side}:${place.index}`;\n }\n };\n const add = (place: PanelPlace, priority: 1 | 2 | 3, hit: Rect, make: PanelTarget[\"make\"], free = false, marker?: Rect): void => {\n if (hit.width <= 0 || hit.height <= 0) return;\n if (input.allows && !input.allows(id, place)) return;\n // Its own place: a drop there changes nothing, so it is no target (the drag's home covers it).\n // Widths compare as laid out: a stored width past the column's limits is the same place as the limit.\n if (place.kind !== \"float\" && samePlaces(make({ x: 0, y: 0 }, { x: 0, y: 0 }), state, defs)) return;\n out.push({ id: idOf(place), priority, hit, panel: id, place, order: placeRank(place), make, ...(free ? { free: true } : {}), ...(marker ? { marker } : {}) });\n };\n\n // The columns' height: what the full-span bands leave (the whole stage without them).\n const fullTop = l0.bands.top?.span === \"full\" ? l0.bands.top.rect : null;\n const fullBot = l0.bands.bottom?.span === \"full\" ? l0.bands.bottom.rect : null;\n const top = fullTop ? fullTop.y + fullTop.height : 0;\n const CH = Math.max(0, (fullBot ? fullBot.y : H) - top);\n\n for (const side of SIDES) {\n if (def?.sides && !def.sides.includes(side)) continue;\n const left = side === \"left\";\n const rail = l0.rails[side];\n const edge = rail ? rail.rect.width : RAIL_EDGE;\n // The rail (or the bare edge): dock folded, as the outermost column.\n const railHit = rail ? rail.rect : left ? rect(0, top, RAIL_EDGE, CH) : rect(W - RAIL_EDGE, top, RAIL_EDGE, CH);\n add({ kind: \"rail\", side }, 1, railHit, () => {\n const s = dock(state, id, side, 0, { width });\n return { ...s, folded: [...s.folded.filter((x) => x !== id), id] };\n });\n // The lines between the open columns, outer to inner, and each column's area.\n const open = l0.columns.filter((c) => c.side === side && c.folded === null);\n const lo = left ? edge : 0;\n const hi = left ? W : W - edge;\n const band = (x: number, outer: boolean, i: number): void => {\n // The outermost line reaches inward only: outward is the rail's.\n const [a, b] = outer ? (left ? cut(x, x + 2 * R, lo, hi) : cut(x - 2 * R, x, lo, hi)) : cut(x - R, x + R, lo, hi);\n add({ kind: \"column\", side, index: i }, 2, rect(a, top, b - a, CH), () => dock(state, id, side, i, { width }));\n };\n // No open column: the line where a new one would start, the stage side of the pages' reserve.\n if (open.length === 0) band(left ? l0.pages.x - px(reserve.left) : l0.pages.x + l0.pages.width + px(reserve.right), true, s0.sides[side].length);\n open.forEach((c, k) => {\n band(left ? c.rect.x : c.rect.x + c.rect.width, k === 0, c.index);\n const col = s0.sides[side][c.index]!;\n const into = () => dock(state, id, side, c.index, { into: true });\n // The members shown, top to bottom, as laid out (a stacked column only; each a section or a title bar). A closed\n // member stays in the column's list but isn't laid out: `at` counts it, so a drop keeps it where it was.\n const members =\n input.stackSlots && col.show !== \"tabs\"\n ? col.panels.flatMap((p, at) => {\n const r = l0.items.get(p)?.rect;\n return r ? [{ at, rect: r }] : [];\n })\n : [];\n if (members.length === 0) {\n add({ kind: \"into\", side, index: c.index }, 2, c.rect, into);\n return;\n }\n const mid = (r: Rect): number => r.y + r.height / 2;\n // Where the panel's top lands after the drop (the column re-shares its height), as a line across the column.\n const marker = (make: () => PanelsState): Rect => {\n const r = layoutPanels(defs, make(), stage, opt).items.get(id)?.rect;\n return rect(c.rect.x, r ? r.y : c.rect.y, c.rect.width, 0);\n };\n const bottom = c.rect.y + c.rect.height;\n members.forEach(({ at, rect: r }, k) => {\n const prev = members[k - 1];\n const y0 = prev ? mid(prev.rect) : c.rect.y;\n const make = () => dock(state, id, side, c.index, { into: true, at });\n add({ kind: \"into\", side, index: c.index, at }, 2, rect(c.rect.x, y0, c.rect.width, mid(r) - y0), make, false, marker(make));\n });\n const last = members.at(-1)!.rect;\n add({ kind: \"into\", side, index: c.index }, 2, rect(c.rect.x, mid(last), c.rect.width, bottom - mid(last)), into, false, marker(into));\n });\n const last = open.at(-1);\n if (last) band(left ? last.rect.x + last.rect.width : last.rect.x, false, last.index + 1);\n }\n\n // The bands: a slot between each two panels and at both ends, the band's area split at its panels' middles; an\n // empty enabled edge, a strip along it inside the pages.\n const home = whereIs(state, id);\n for (const e of EDGES) {\n if (!bandOpts[e] || (def?.sides && !def.sides.includes(e))) continue;\n const pb = l0.bands[e];\n const list = s0.bands?.[e]?.panels ?? [];\n const make = (i: number) => () => dockBand(state, id, e, i, defs);\n if (!pb) {\n // The panel's own band, emptied by lifting it: a drop there would only make the same band again (at its natural\n // height, not the one stored), so it is the drag's home, not a target.\n if (home.kind === \"band\" && home.edge === e && !s0.bands?.[e]) continue;\n const p = l0.pages;\n const h = Math.min(2 * opt.bar, p.height);\n add({ kind: \"band\", edge: e, index: list.length }, 2, rect(p.x, e === \"top\" ? p.y : p.y + p.height - h, p.width, h), make(list.length));\n continue;\n }\n const m = pb.panels.length;\n const share = pb.rect.width / m;\n for (let k = 0; k <= m; k++) {\n const i = k < m ? list.indexOf(pb.panels[k]!) : list.length;\n const a = pb.rect.x + Math.max(0, k - 0.5) * share;\n const b = pb.rect.x + Math.min(m, k + 0.5) * share;\n add({ kind: \"band\", edge: e, index: i }, 2, rect(a, pb.rect.y, b - a, pb.rect.height), make(i));\n }\n }\n\n if (def?.floats !== false) {\n const was = state.floats.find((f) => f.id === id);\n const size = was ? { width: was.rect.width, height: was.rect.height } : floatSize(def).natural;\n const pinned = !!was?.pinned;\n add(\n { kind: \"float\" },\n 3,\n rect(0, 0, W, H),\n (p, grab) => {\n // Let go at p (view space); stored where it shows once the float option has had its say.\n const at = rect(p.x - grab.x, p.y - grab.y, size.width, size.height);\n const s = float(state, id, pinned ? at : toPage(at, opt.view), pinned);\n const laid = layoutPanels(defs, s, stage, opt).items.get(id)!.rect;\n // A folded float shows as a bar: it moves to where the bar shows and keeps its full size for unfolding.\n const shown = s.folded.includes(id) ? { ...laid, width: at.width, height: at.height } : laid;\n return float(state, id, pinned ? shown : toPage(shown, opt.view), pinned);\n },\n true,\n );\n }\n return out.sort((a, b) => a.order - b.order);\n}\n\n/** A target's drop, laid out: where the panel lands. */\nexport interface PanelDrop {\n readonly target: string;\n readonly place: PanelPlace;\n /** Same key, same place (a float's key carries where it lands). */\n readonly key: string;\n readonly state: PanelsState;\n readonly layout: PanelsLayout;\n /** Where the panel lands (its rail segment when it docks folded). */\n readonly slot: Rect;\n /** It lands in a rail. */\n readonly hidden: boolean;\n /** It floats where it is let go: no room is made for it. */\n readonly free: boolean;\n}\n\n/** The drop on `target` with the pointer at `p` holding the panel at `grab`, laid out. */\nexport function panelDrop(input: PanelTargetInput, target: PanelTarget, p: Point, grab: Point): PanelDrop {\n const opt: PanelsOptions = { ...DEFAULT_PANELS_OPTIONS, ...input.options };\n const state = target.make(p, grab);\n const layout = layoutPanels(input.defs, state, input.stage, opt);\n const placed = layout.items.get(input.id)!;\n const key = target.free ? `float:${Math.round(placed.rect.x)},${Math.round(placed.rect.y)}` : target.id;\n return { target: target.id, place: target.place, key, state, layout, slot: placed.rect, hidden: placed.hidden, free: !!target.free };\n}\n\n// --- keyboard stops ------------------------------------------------------------------------------------------------\n\nexport interface PanelStop {\n /** The target's id (\"home\" for the panel's own place). */\n readonly id: string;\n readonly place: PanelPlace;\n /** The state a move here makes (the current one for home). */\n readonly state: PanelsState;\n readonly home: boolean;\n}\n\nexport interface PanelStopsOptions {\n /** The panel's own place (`homePlace`) and the state as it is: a stop of its own in its reading-order position. */\n readonly home?: { readonly place: PanelPlace; readonly state: PanelsState };\n /** Floating as a stop at the end (default: left out); `at` and `grab` as for a drop (default: the stage's middle, the corner). */\n readonly floats?: boolean | { readonly at: Point; readonly grab?: Point };\n}\n\n/** The panel's places in reading order, for the arrow keys and a \"Move to\" menu (`keyboardStops` calls this). */\nexport function panelStops(targets: readonly PanelTarget[], options: PanelStopsOptions = {}): PanelStop[] {\n const stops: (PanelStop & { order: number })[] = [];\n for (const t of targets) {\n if (t.place.kind === \"float\") {\n if (!options.floats) continue;\n const at = options.floats === true ? { x: t.hit.x + t.hit.width / 2, y: t.hit.y + t.hit.height / 2 } : options.floats.at;\n const grab = options.floats === true ? { x: 0, y: 0 } : (options.floats.grab ?? { x: 0, y: 0 });\n stops.push({ id: t.id, place: t.place, state: t.make(at, grab), home: false, order: t.order });\n continue;\n }\n stops.push({ id: t.id, place: t.place, state: t.make({ x: 0, y: 0 }, { x: 0, y: 0 }), home: false, order: t.order });\n }\n const h = options.home;\n // A float's home sits with the floats: last, after any float stop. A home that says its position in a column sits at\n // that position among the column's slots.\n const after = h?.place.kind === \"float\" ? 1 : h?.place.kind === \"into\" && h.place.at !== undefined ? 0.0005 : 0.5;\n if (h) stops.push({ id: \"home\", place: h.place, state: h.state, home: true, order: placeRank(h.place) + after });\n return stops.sort((a, b) => a.order - b.order).map(({ order: _order, ...s }) => s);\n}\n"],"mappings":"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","names":["float","rect","f","b","order","fit","g","open","share","open","k","last"]}
package/dist/desk.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { P as PanelsOptions, a as PanelDef, b as PanelsState, c as PanelTargetInput, d as PanelTarget, p as panelDrop, e as PanelDrop, l as layoutPanels, f as PanelsLayout } from './targets-DwOTs4UC.js';
1
+ import { P as PanelsOptions, a as PanelDef, b as PanelsState, c as PanelTargetInput, d as PanelTarget, p as panelDrop, e as PanelDrop, l as layoutPanels, f as PanelsLayout } from './targets-B_U2Zf7x.js';
2
2
  import './geometry-mL-GTRti.js';
3
3
 
4
4
  /**
@@ -6,17 +6,23 @@ import './geometry-mL-GTRti.js';
6
6
  * and a start state; it carries no titles, no words and no toolbar wiring (the app names presets and wires its
7
7
  * toolbar). It imports only the panels entry's public index, so an app that imports only `./panels` loads none of it.
8
8
  *
9
- * - `docks`: one stack column per side; sections at their natural heights when the defs give `height`; short of width a
10
- * column folds to its side's rail. No floats.
9
+ * - `docks`: one stack column per side and a bottom band between them (reserved: it shortens the pages); sections at
10
+ * their natural heights when the defs give `height`; short of width a column folds to its side's rail, short of
11
+ * height the band folds to a bar. No floats.
12
+ * - `docksFull`: as docks, with the bottom band full width (the columns stand on it).
11
13
  * - `dockTear`: as docks, and panels may float (tear-off and dock-back); one panel floats in the start state.
12
- * - `navigator`: a tabbed column on the left, a stack column on the right. No floats.
14
+ * - `navigator`: a tabbed column on the left, a stack column on the right. No band, no floats.
15
+ *
16
+ * The bottom band starts with the hint's `bottom` panels, else the last def whose `sides` names "bottom" (a def
17
+ * without `sides` may be dropped there, but doesn't start there).
13
18
  */
14
19
 
15
- type PresetId = "docks" | "dockTear" | "navigator";
16
- /** Which panels start on which side (ids in order); the others are placed by the preset. */
20
+ type PresetId = "docks" | "docksFull" | "dockTear" | "navigator";
21
+ /** Which panels start on which side (ids in order), and in the bottom band (a preset with one); the others are placed by the preset. */
17
22
  interface DeskHint {
18
23
  readonly left?: readonly string[];
19
24
  readonly right?: readonly string[];
25
+ readonly bottom?: readonly string[];
20
26
  }
21
27
  interface DeskPreset {
22
28
  readonly id: PresetId;
package/dist/desk.js CHANGED
@@ -1,4 +1,4 @@
1
- import "./chunk-XUV6MJ2P.js";
1
+ import "./chunk-2H3CSPEH.js";
2
2
  import {
3
3
  createPanels,
4
4
  floatSize,
@@ -6,7 +6,7 @@ import {
6
6
  panelDrop,
7
7
  panelTargets,
8
8
  showTabs
9
- } from "./chunk-PWQWD2CS.js";
9
+ } from "./chunk-CJA6LRHN.js";
10
10
  import "./chunk-QMTNB2C3.js";
11
11
 
12
12
  // src/desk/index.ts
@@ -26,17 +26,45 @@ function split(defs, hint = {}) {
26
26
  return { left, right };
27
27
  }
28
28
  var columns = (ids) => ids.length ? [[...ids]] : [];
29
+ function bottomOf(defs, hint = {}) {
30
+ const known = new Set(defs.map((d) => d.id));
31
+ if (hint.bottom) return hint.bottom.filter((id) => known.has(id));
32
+ const last = [...defs].reverse().find((d) => d.sides?.includes("bottom"));
33
+ return last ? [last.id] : [];
34
+ }
35
+ var sidesOnly = (defs, hint, band) => [
36
+ defs.filter((d) => !band.includes(d.id)),
37
+ hint && { ...hint, left: hint.left?.filter((id) => !band.includes(id)), right: hint.right?.filter((id) => !band.includes(id)) }
38
+ ];
39
+ var banded = (start) => (defs, hint) => {
40
+ const bottom = bottomOf(defs, hint);
41
+ const [rest, h] = sidesOnly(defs, hint, bottom);
42
+ const s = start(rest, h);
43
+ return bottom.length ? createPanels(defs, { ...startOf(s), bottom }) : s;
44
+ };
45
+ function startOf(s) {
46
+ return {
47
+ left: s.sides.left.map((c) => c.panels),
48
+ right: s.sides.right.map((c) => c.panels),
49
+ floats: s.floats.map((f) => ({ id: f.id, x: f.rect.x, y: f.rect.y, width: f.rect.width, height: f.rect.height, ...f.pinned ? { pinned: true } : {} })),
50
+ folded: s.folded,
51
+ kept: s.kept,
52
+ closed: s.closed
53
+ };
54
+ }
29
55
  var docksStart = (defs, hint) => {
30
56
  const { left, right } = split(defs, hint);
31
57
  return createPanels(defs, { left: columns(left), right: columns(right) });
32
58
  };
33
- var docks = { id: "docks", options: { fold: "rail" }, floats: false, start: docksStart };
59
+ var BOTTOM = { mode: "reserved", span: "between" };
60
+ var docks = { id: "docks", options: { fold: "rail", bands: { bottom: BOTTOM } }, floats: false, start: banded(docksStart) };
61
+ var docksFull = { id: "docksFull", options: { fold: "rail", bands: { bottom: { ...BOTTOM, span: "full" } } }, floats: false, start: banded(docksStart) };
34
62
  var dockTear = {
35
63
  id: "dockTear",
36
- options: { fold: "rail", floats: "clamp" },
64
+ options: { fold: "rail", floats: "clamp", bands: { bottom: BOTTOM } },
37
65
  floats: true,
38
66
  // As docks, with the right side's last panel that may float torn off, next to the left column.
39
- start(defs, hint) {
67
+ start: banded((defs, hint) => {
40
68
  const { left, right } = split(defs, hint);
41
69
  const can = (id) => defs.find((d) => d.id === id)?.floats !== false;
42
70
  const torn = [...right].reverse().find(can) ?? [...left].reverse().find(can);
@@ -48,7 +76,7 @@ var dockTear = {
48
76
  right: columns(keep(right)),
49
77
  ...torn ? { floats: [{ id: torn, x: leftW + 24, y: 24, width: size.natural.width, height: size.natural.height }] } : {}
50
78
  });
51
- }
79
+ })
52
80
  };
53
81
  var navigator = {
54
82
  id: "navigator",
@@ -59,7 +87,7 @@ var navigator = {
59
87
  return s.sides.left.length ? showTabs(s, "left", 0, true) : s;
60
88
  }
61
89
  };
62
- var PRESETS = { docks, dockTear, navigator };
90
+ var PRESETS = { docks, docksFull, dockTear, navigator };
63
91
  function presetLayout(preset, defs, state, stage, options = {}) {
64
92
  return layoutPanels(defs, state, stage, { ...preset.options, ...options });
65
93
  }
package/dist/desk.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/desk/index.ts"],"sourcesContent":["/**\n * @n-uf/placement/desk: desk presets as data on `@n-uf/placement/panels`. A preset is options for the panels engine\n * and a start state; it carries no titles, no words and no toolbar wiring (the app names presets and wires its\n * toolbar). It imports only the panels entry's public index, so an app that imports only `./panels` loads none of it.\n *\n * - `docks`: one stack column per side; sections at their natural heights when the defs give `height`; short of width a\n * column folds to its side's rail. No floats.\n * - `dockTear`: as docks, and panels may float (tear-off and dock-back); one panel floats in the start state.\n * - `navigator`: a tabbed column on the left, a stack column on the right. No floats.\n */\nimport {\n createPanels,\n floatSize,\n layoutPanels,\n panelDrop,\n panelTargets,\n showTabs,\n type PanelDef,\n type PanelDrop,\n type PanelPlace,\n type PanelTarget,\n type PanelTargetInput,\n type PanelsLayout,\n type PanelsOptions,\n type PanelsState,\n} from \"../panels\";\n\nexport type PresetId = \"docks\" | \"dockTear\" | \"navigator\";\n\n/** Which panels start on which side (ids in order); the others are placed by the preset. */\nexport interface DeskHint {\n readonly left?: readonly string[];\n readonly right?: readonly string[];\n}\n\nexport interface DeskPreset {\n readonly id: PresetId;\n /** The panels options the preset lays out with (the caller's own options go over them). */\n readonly options: Partial<PanelsOptions>;\n /** Whether its panels may float: when not, `presetTargets` offers no float target. */\n readonly floats: boolean;\n /** Its start state for these panels. */\n start(defs: readonly PanelDef[], hint?: DeskHint): PanelsState;\n}\n\ntype Stage = Parameters<typeof layoutPanels>[2];\ntype Point = Parameters<typeof panelDrop>[2];\n\n/**\n * Split the panels between the sides: the hint's first, then the rest in order, each to a side it may dock on, the\n * left side taking the first half of them.\n */\nfunction split(defs: readonly PanelDef[], hint: DeskHint = {}): { left: string[]; right: string[] } {\n const known = new Set(defs.map((d) => d.id));\n const left = (hint.left ?? []).filter((id) => known.has(id));\n const right = (hint.right ?? []).filter((id) => known.has(id) && !left.includes(id));\n const rest = defs.filter((d) => !left.includes(d.id) && !right.includes(d.id));\n const half = Math.ceil(defs.length / 2);\n for (const d of rest) {\n const mayL = !d.sides || d.sides.includes(\"left\");\n const mayR = !d.sides || d.sides.includes(\"right\");\n if (mayL && (left.length < half || !mayR)) left.push(d.id);\n else if (mayR) right.push(d.id);\n else left.push(d.id);\n }\n return { left, right };\n}\n\nconst columns = (ids: readonly string[]): string[][] => (ids.length ? [[...ids]] : []);\n\nconst docksStart = (defs: readonly PanelDef[], hint?: DeskHint): PanelsState => {\n const { left, right } = split(defs, hint);\n return createPanels(defs, { left: columns(left), right: columns(right) });\n};\n\nconst docks: DeskPreset = { id: \"docks\", options: { fold: \"rail\" }, floats: false, start: docksStart };\n\nconst dockTear: DeskPreset = {\n id: \"dockTear\",\n options: { fold: \"rail\", floats: \"clamp\" },\n floats: true,\n // As docks, with the right side's last panel that may float torn off, next to the left column.\n start(defs, hint) {\n const { left, right } = split(defs, hint);\n const can = (id: string): boolean => defs.find((d) => d.id === id)?.floats !== false;\n const torn = [...right].reverse().find(can) ?? [...left].reverse().find(can);\n const keep = (ids: readonly string[]): string[] => ids.filter((id) => id !== torn);\n const leftW = Math.max(0, ...keep(left).map((id) => defs.find((d) => d.id === id)!.width.natural));\n const size = floatSize(defs.find((d) => d.id === torn));\n return createPanels(defs, {\n left: columns(keep(left)),\n right: columns(keep(right)),\n ...(torn ? { floats: [{ id: torn, x: leftW + 24, y: 24, width: size.natural.width, height: size.natural.height }] } : {}),\n });\n },\n};\n\nconst navigator: DeskPreset = {\n id: \"navigator\",\n options: { fold: \"rail\" },\n floats: false,\n start(defs, hint) {\n const s = docksStart(defs, hint);\n return s.sides.left.length ? showTabs(s, \"left\", 0, true) : s;\n },\n};\n\nexport const PRESETS: Readonly<Record<PresetId, DeskPreset>> = { docks, dockTear, navigator };\n\n/** `layoutPanels` with the preset's options under the caller's. */\nexport function presetLayout(preset: DeskPreset, defs: readonly PanelDef[], state: PanelsState, stage: Stage, options: Partial<PanelsOptions> = {}): PanelsLayout {\n return layoutPanels(defs, state, stage, { ...preset.options, ...options });\n}\n\n/** The target input with the preset's options under the caller's, and only the places the preset allows. */\nexport function presetInput(preset: DeskPreset, input: PanelTargetInput): PanelTargetInput {\n const allows = (id: string, place: PanelPlace): boolean => (place.kind !== \"float\" || preset.floats) && (input.allows?.(id, place) ?? true);\n return { ...input, options: { ...preset.options, ...input.options }, allows };\n}\n\n/** `panelTargets` with the preset's options under the caller's, and only the places the preset allows. */\nexport function presetTargets(preset: DeskPreset, input: PanelTargetInput): PanelTarget[] {\n return panelTargets(presetInput(preset, input));\n}\n\n/** `panelDrop` laid out with the preset's options (so the slot is where the preset lays the panel). */\nexport function presetDrop(preset: DeskPreset, input: PanelTargetInput, target: PanelTarget, point: Point, grab: Point): PanelDrop {\n return panelDrop(presetInput(preset, input), target, point, grab);\n}\n"],"mappings":";;;;;;;;;;;;AAoDA,SAAS,MAAM,MAA2B,OAAiB,CAAC,GAAwC;AAClG,QAAM,QAAQ,IAAI,IAAI,KAAK,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;AAC3C,QAAM,QAAQ,KAAK,QAAQ,CAAC,GAAG,OAAO,CAAC,OAAO,MAAM,IAAI,EAAE,CAAC;AAC3D,QAAM,SAAS,KAAK,SAAS,CAAC,GAAG,OAAO,CAAC,OAAO,MAAM,IAAI,EAAE,KAAK,CAAC,KAAK,SAAS,EAAE,CAAC;AACnF,QAAM,OAAO,KAAK,OAAO,CAAC,MAAM,CAAC,KAAK,SAAS,EAAE,EAAE,KAAK,CAAC,MAAM,SAAS,EAAE,EAAE,CAAC;AAC7E,QAAM,OAAO,KAAK,KAAK,KAAK,SAAS,CAAC;AACtC,aAAW,KAAK,MAAM;AACpB,UAAM,OAAO,CAAC,EAAE,SAAS,EAAE,MAAM,SAAS,MAAM;AAChD,UAAM,OAAO,CAAC,EAAE,SAAS,EAAE,MAAM,SAAS,OAAO;AACjD,QAAI,SAAS,KAAK,SAAS,QAAQ,CAAC,MAAO,MAAK,KAAK,EAAE,EAAE;AAAA,aAChD,KAAM,OAAM,KAAK,EAAE,EAAE;AAAA,QACzB,MAAK,KAAK,EAAE,EAAE;AAAA,EACrB;AACA,SAAO,EAAE,MAAM,MAAM;AACvB;AAEA,IAAM,UAAU,CAAC,QAAwC,IAAI,SAAS,CAAC,CAAC,GAAG,GAAG,CAAC,IAAI,CAAC;AAEpF,IAAM,aAAa,CAAC,MAA2B,SAAiC;AAC9E,QAAM,EAAE,MAAM,MAAM,IAAI,MAAM,MAAM,IAAI;AACxC,SAAO,aAAa,MAAM,EAAE,MAAM,QAAQ,IAAI,GAAG,OAAO,QAAQ,KAAK,EAAE,CAAC;AAC1E;AAEA,IAAM,QAAoB,EAAE,IAAI,SAAS,SAAS,EAAE,MAAM,OAAO,GAAG,QAAQ,OAAO,OAAO,WAAW;AAErG,IAAM,WAAuB;AAAA,EAC3B,IAAI;AAAA,EACJ,SAAS,EAAE,MAAM,QAAQ,QAAQ,QAAQ;AAAA,EACzC,QAAQ;AAAA;AAAA,EAER,MAAM,MAAM,MAAM;AAChB,UAAM,EAAE,MAAM,MAAM,IAAI,MAAM,MAAM,IAAI;AACxC,UAAM,MAAM,CAAC,OAAwB,KAAK,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,GAAG,WAAW;AAC/E,UAAM,OAAO,CAAC,GAAG,KAAK,EAAE,QAAQ,EAAE,KAAK,GAAG,KAAK,CAAC,GAAG,IAAI,EAAE,QAAQ,EAAE,KAAK,GAAG;AAC3E,UAAM,OAAO,CAAC,QAAqC,IAAI,OAAO,CAAC,OAAO,OAAO,IAAI;AACjF,UAAM,QAAQ,KAAK,IAAI,GAAG,GAAG,KAAK,IAAI,EAAE,IAAI,CAAC,OAAO,KAAK,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,EAAG,MAAM,OAAO,CAAC;AACjG,UAAM,OAAO,UAAU,KAAK,KAAK,CAAC,MAAM,EAAE,OAAO,IAAI,CAAC;AACtD,WAAO,aAAa,MAAM;AAAA,MACxB,MAAM,QAAQ,KAAK,IAAI,CAAC;AAAA,MACxB,OAAO,QAAQ,KAAK,KAAK,CAAC;AAAA,MAC1B,GAAI,OAAO,EAAE,QAAQ,CAAC,EAAE,IAAI,MAAM,GAAG,QAAQ,IAAI,GAAG,IAAI,OAAO,KAAK,QAAQ,OAAO,QAAQ,KAAK,QAAQ,OAAO,CAAC,EAAE,IAAI,CAAC;AAAA,IACzH,CAAC;AAAA,EACH;AACF;AAEA,IAAM,YAAwB;AAAA,EAC5B,IAAI;AAAA,EACJ,SAAS,EAAE,MAAM,OAAO;AAAA,EACxB,QAAQ;AAAA,EACR,MAAM,MAAM,MAAM;AAChB,UAAM,IAAI,WAAW,MAAM,IAAI;AAC/B,WAAO,EAAE,MAAM,KAAK,SAAS,SAAS,GAAG,QAAQ,GAAG,IAAI,IAAI;AAAA,EAC9D;AACF;AAEO,IAAM,UAAkD,EAAE,OAAO,UAAU,UAAU;AAGrF,SAAS,aAAa,QAAoB,MAA2B,OAAoB,OAAc,UAAkC,CAAC,GAAiB;AAChK,SAAO,aAAa,MAAM,OAAO,OAAO,EAAE,GAAG,OAAO,SAAS,GAAG,QAAQ,CAAC;AAC3E;AAGO,SAAS,YAAY,QAAoB,OAA2C;AACzF,QAAM,SAAS,CAAC,IAAY,WAAgC,MAAM,SAAS,WAAW,OAAO,YAAY,MAAM,SAAS,IAAI,KAAK,KAAK;AACtI,SAAO,EAAE,GAAG,OAAO,SAAS,EAAE,GAAG,OAAO,SAAS,GAAG,MAAM,QAAQ,GAAG,OAAO;AAC9E;AAGO,SAAS,cAAc,QAAoB,OAAwC;AACxF,SAAO,aAAa,YAAY,QAAQ,KAAK,CAAC;AAChD;AAGO,SAAS,WAAW,QAAoB,OAAyB,QAAqB,OAAc,MAAwB;AACjI,SAAO,UAAU,YAAY,QAAQ,KAAK,GAAG,QAAQ,OAAO,IAAI;AAClE;","names":[]}
1
+ {"version":3,"sources":["../src/desk/index.ts"],"sourcesContent":["/**\n * @n-uf/placement/desk: desk presets as data on `@n-uf/placement/panels`. A preset is options for the panels engine\n * and a start state; it carries no titles, no words and no toolbar wiring (the app names presets and wires its\n * toolbar). It imports only the panels entry's public index, so an app that imports only `./panels` loads none of it.\n *\n * - `docks`: one stack column per side and a bottom band between them (reserved: it shortens the pages); sections at\n * their natural heights when the defs give `height`; short of width a column folds to its side's rail, short of\n * height the band folds to a bar. No floats.\n * - `docksFull`: as docks, with the bottom band full width (the columns stand on it).\n * - `dockTear`: as docks, and panels may float (tear-off and dock-back); one panel floats in the start state.\n * - `navigator`: a tabbed column on the left, a stack column on the right. No band, no floats.\n *\n * The bottom band starts with the hint's `bottom` panels, else the last def whose `sides` names \"bottom\" (a def\n * without `sides` may be dropped there, but doesn't start there).\n */\nimport {\n createPanels,\n floatSize,\n layoutPanels,\n panelDrop,\n panelTargets,\n showTabs,\n type PanelDef,\n type PanelDrop,\n type PanelPlace,\n type PanelTarget,\n type PanelTargetInput,\n type PanelsLayout,\n type PanelsOptions,\n type PanelsState,\n} from \"../panels\";\n\nexport type PresetId = \"docks\" | \"docksFull\" | \"dockTear\" | \"navigator\";\n\n/** Which panels start on which side (ids in order), and in the bottom band (a preset with one); the others are placed by the preset. */\nexport interface DeskHint {\n readonly left?: readonly string[];\n readonly right?: readonly string[];\n readonly bottom?: readonly string[];\n}\n\nexport interface DeskPreset {\n readonly id: PresetId;\n /** The panels options the preset lays out with (the caller's own options go over them). */\n readonly options: Partial<PanelsOptions>;\n /** Whether its panels may float: when not, `presetTargets` offers no float target. */\n readonly floats: boolean;\n /** Its start state for these panels. */\n start(defs: readonly PanelDef[], hint?: DeskHint): PanelsState;\n}\n\ntype Stage = Parameters<typeof layoutPanels>[2];\ntype Point = Parameters<typeof panelDrop>[2];\n\n/**\n * Split the panels between the sides: the hint's first, then the rest in order, each to a side it may dock on, the\n * left side taking the first half of them.\n */\nfunction split(defs: readonly PanelDef[], hint: DeskHint = {}): { left: string[]; right: string[] } {\n const known = new Set(defs.map((d) => d.id));\n const left = (hint.left ?? []).filter((id) => known.has(id));\n const right = (hint.right ?? []).filter((id) => known.has(id) && !left.includes(id));\n const rest = defs.filter((d) => !left.includes(d.id) && !right.includes(d.id));\n const half = Math.ceil(defs.length / 2);\n for (const d of rest) {\n const mayL = !d.sides || d.sides.includes(\"left\");\n const mayR = !d.sides || d.sides.includes(\"right\");\n if (mayL && (left.length < half || !mayR)) left.push(d.id);\n else if (mayR) right.push(d.id);\n else left.push(d.id);\n }\n return { left, right };\n}\n\nconst columns = (ids: readonly string[]): string[][] => (ids.length ? [[...ids]] : []);\n\n/** The bottom band's start: the hint's, else the last def whose `sides` names \"bottom\". */\nfunction bottomOf(defs: readonly PanelDef[], hint: DeskHint = {}): string[] {\n const known = new Set(defs.map((d) => d.id));\n if (hint.bottom) return hint.bottom.filter((id) => known.has(id));\n const last = [...defs].reverse().find((d) => d.sides?.includes(\"bottom\"));\n return last ? [last.id] : [];\n}\n\n/** The defs and hint with the band's panels taken out, so the sides split the rest. */\nconst sidesOnly = (defs: readonly PanelDef[], hint: DeskHint | undefined, band: readonly string[]): [PanelDef[], DeskHint | undefined] => [\n defs.filter((d) => !band.includes(d.id)),\n hint && { ...hint, left: hint.left?.filter((id) => !band.includes(id)), right: hint.right?.filter((id) => !band.includes(id)) },\n];\n\nconst banded = (start: (defs: readonly PanelDef[], hint?: DeskHint) => PanelsState) => (defs: readonly PanelDef[], hint?: DeskHint): PanelsState => {\n const bottom = bottomOf(defs, hint);\n const [rest, h] = sidesOnly(defs, hint, bottom);\n const s = start(rest, h);\n return bottom.length ? createPanels(defs, { ...startOf(s), bottom }) : s;\n};\n\n/** A plain start back from a state (columns, floats and lists; the clock is rebuilt in listing order). */\nfunction startOf(s: PanelsState): Parameters<typeof createPanels>[1] {\n return {\n left: s.sides.left.map((c) => c.panels),\n right: s.sides.right.map((c) => c.panels),\n floats: s.floats.map((f) => ({ id: f.id, x: f.rect.x, y: f.rect.y, width: f.rect.width, height: f.rect.height, ...(f.pinned ? { pinned: true } : {}) })),\n folded: s.folded,\n kept: s.kept,\n closed: s.closed,\n };\n}\n\nconst docksStart = (defs: readonly PanelDef[], hint?: DeskHint): PanelsState => {\n const { left, right } = split(defs, hint);\n return createPanels(defs, { left: columns(left), right: columns(right) });\n};\n\nconst BOTTOM = { mode: \"reserved\", span: \"between\" } as const;\n\nconst docks: DeskPreset = { id: \"docks\", options: { fold: \"rail\", bands: { bottom: BOTTOM } }, floats: false, start: banded(docksStart) };\n\nconst docksFull: DeskPreset = { id: \"docksFull\", options: { fold: \"rail\", bands: { bottom: { ...BOTTOM, span: \"full\" } } }, floats: false, start: banded(docksStart) };\n\nconst dockTear: DeskPreset = {\n id: \"dockTear\",\n options: { fold: \"rail\", floats: \"clamp\", bands: { bottom: BOTTOM } },\n floats: true,\n // As docks, with the right side's last panel that may float torn off, next to the left column.\n start: banded((defs, hint) => {\n const { left, right } = split(defs, hint);\n const can = (id: string): boolean => defs.find((d) => d.id === id)?.floats !== false;\n const torn = [...right].reverse().find(can) ?? [...left].reverse().find(can);\n const keep = (ids: readonly string[]): string[] => ids.filter((id) => id !== torn);\n const leftW = Math.max(0, ...keep(left).map((id) => defs.find((d) => d.id === id)!.width.natural));\n const size = floatSize(defs.find((d) => d.id === torn));\n return createPanels(defs, {\n left: columns(keep(left)),\n right: columns(keep(right)),\n ...(torn ? { floats: [{ id: torn, x: leftW + 24, y: 24, width: size.natural.width, height: size.natural.height }] } : {}),\n });\n }),\n};\n\nconst navigator: DeskPreset = {\n id: \"navigator\",\n options: { fold: \"rail\" },\n floats: false,\n start(defs, hint) {\n const s = docksStart(defs, hint);\n return s.sides.left.length ? showTabs(s, \"left\", 0, true) : s;\n },\n};\n\nexport const PRESETS: Readonly<Record<PresetId, DeskPreset>> = { docks, docksFull, dockTear, navigator };\n\n/** `layoutPanels` with the preset's options under the caller's. */\nexport function presetLayout(preset: DeskPreset, defs: readonly PanelDef[], state: PanelsState, stage: Stage, options: Partial<PanelsOptions> = {}): PanelsLayout {\n return layoutPanels(defs, state, stage, { ...preset.options, ...options });\n}\n\n/** The target input with the preset's options under the caller's, and only the places the preset allows. */\nexport function presetInput(preset: DeskPreset, input: PanelTargetInput): PanelTargetInput {\n const allows = (id: string, place: PanelPlace): boolean => (place.kind !== \"float\" || preset.floats) && (input.allows?.(id, place) ?? true);\n return { ...input, options: { ...preset.options, ...input.options }, allows };\n}\n\n/** `panelTargets` with the preset's options under the caller's, and only the places the preset allows. */\nexport function presetTargets(preset: DeskPreset, input: PanelTargetInput): PanelTarget[] {\n return panelTargets(presetInput(preset, input));\n}\n\n/** `panelDrop` laid out with the preset's options (so the slot is where the preset lays the panel). */\nexport function presetDrop(preset: DeskPreset, input: PanelTargetInput, target: PanelTarget, point: Point, grab: Point): PanelDrop {\n return panelDrop(presetInput(preset, input), target, point, grab);\n}\n"],"mappings":"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","names":[]}
package/dist/panels.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { b as PanelsState, S as Side, C as Clock, a as PanelDef } from './targets-DwOTs4UC.js';
2
- export { g as COLUMN_REACH, h as Column, D as DEFAULT_PANELS_OPTIONS, i as DockOptions, F as FLOAT_HEIGHT, j as FLOAT_MIN, k as FloatAt, G as GiveWay, I as IDENTITY_VIEW, e as PanelDrop, m as PanelKind, n as PanelPlace, o as PanelStop, q as PanelStopsOptions, d as PanelTarget, c as PanelTargetInput, f as PanelsLayout, r as PanelsNote, s as PanelsNoteCode, P as PanelsOptions, t as PanelsStart, u as PlacedColumn, v as PlacedPanel, w as PlacedRail, R as RAIL_EDGE, x as SIDES, V as View, W as Where, y as activate, z as close, A as columnWidth, B as createPanels, E as defOf, H as dock, J as float, K as floatSize, L as focus, M as giveWayOrder, N as homePlace, O as keep, l as layoutPanels, Q as liftPanel, T as open, U as ownWidth, p as panelDrop, X as panelStops, Y as panelTargets, Z as pin, _ as placeRank, $ as resizeColumn, a0 as resizeFloat, a1 as samePlaces, a2 as showTabs, a3 as tick, a4 as toPage, a5 as toView, a6 as toggleFold, a7 as whereIs } from './targets-DwOTs4UC.js';
1
+ import { b as PanelsState, S as Side, E as Edge, C as Clock, a as PanelDef } from './targets-B_U2Zf7x.js';
2
+ export { B as BAND_SIZE, g as Band, h as BandOption, i as COLUMN_REACH, j as Column, D as DEFAULT_PANELS_OPTIONS, k as DockOptions, m as EDGES, F as FLOAT_HEIGHT, n as FLOAT_MIN, o as FloatAt, G as GiveWay, I as IDENTITY_VIEW, e as PanelDrop, q as PanelKind, r as PanelPlace, s as PanelStop, t as PanelStopsOptions, d as PanelTarget, c as PanelTargetInput, f as PanelsLayout, u as PanelsNote, v as PanelsNoteCode, P as PanelsOptions, w as PanelsStart, x as Place, y as PlacedBand, z as PlacedColumn, A as PlacedPanel, H as PlacedRail, R as RAIL_EDGE, J as Reserve, K as ReserveEdge, L as SIDES, V as View, W as Where, M as activate, N as bandHeight, O as bandSize, Q as close, T as columnWidth, U as createPanels, X as defOf, Y as dock, Z as dockBand, _ as float, $ as floatSize, a0 as focus, a1 as giveWayOrder, a2 as homePlace, a3 as keep, l as layoutPanels, a4 as liftPanel, a5 as open, a6 as ownWidth, p as panelDrop, a7 as panelStops, a8 as panelTargets, a9 as pin, aa as placeRank, ab as resizeBand, ac as resizeColumn, ad as resizeFloat, ae as samePlaces, af as showTabs, ag as tick, ah as toPage, ai as toView, aj as toggleFold, ak as whereIs } from './targets-B_U2Zf7x.js';
3
3
  import { R as Rect } from './geometry-mL-GTRti.js';
4
4
 
5
5
  /**
@@ -14,6 +14,10 @@ import { R as Rect } from './geometry-mL-GTRti.js';
14
14
  * `"float.<field>"`; a clock entry for a panel that isn't placed as `"clock.<id>"`), so a consumer can tell that
15
15
  * something was left out. A column's `show` ("tabs") and `active` are such optional fields: an unknown `show` is
16
16
  * dropped as `"column.show"`, an `active` that isn't one of the column's panels as `"column.active:<id>"`.
17
+ *
18
+ * `bands` (26.11.10) is such an optional field too: `{ top?, bottom? }`, each `{ panels, height }`. An unknown edge is
19
+ * dropped as `"bands.<key>"`, a band that isn't an object with a panels list and a numeric height (or whose panels are
20
+ * all dropped) as `"bands.<edge>"`, an unknown field in one as `"band.<field>"`. Heights are clamped to the defs.
17
21
  */
18
22
 
19
23
  interface StoredPanels {
@@ -25,6 +29,11 @@ interface StoredPanels {
25
29
  show?: "tabs";
26
30
  active?: string;
27
31
  }[]>;
32
+ /** The bands, only when the state has one (an optional field of v1). */
33
+ readonly bands?: Partial<Record<Edge, {
34
+ panels: string[];
35
+ height: number;
36
+ }>>;
28
37
  readonly floats: {
29
38
  id: string;
30
39
  rect: Rect;
@@ -46,4 +55,4 @@ type PanelsRead = {
46
55
  declare function storePanels(state: PanelsState): StoredPanels;
47
56
  declare function readPanels(data: unknown, defs?: readonly PanelDef[]): PanelsRead;
48
57
 
49
- export { Clock, PanelDef, type PanelsRead, PanelsState, Side, type StoredPanels, readPanels, storePanels };
58
+ export { Clock, Edge, PanelDef, type PanelsRead, PanelsState, Side, type StoredPanels, readPanels, storePanels };
package/dist/panels.js CHANGED
@@ -1,21 +1,26 @@
1
1
  import {
2
2
  readPanels,
3
3
  storePanels
4
- } from "./chunk-XUV6MJ2P.js";
4
+ } from "./chunk-2H3CSPEH.js";
5
5
  import {
6
+ BAND_SIZE,
6
7
  COLUMN_REACH,
7
8
  DEFAULT_PANELS_OPTIONS,
9
+ EDGES,
8
10
  FLOAT_HEIGHT,
9
11
  FLOAT_MIN,
10
12
  IDENTITY_VIEW,
11
13
  RAIL_EDGE,
12
14
  SIDES,
13
15
  activate,
16
+ bandHeight,
17
+ bandSize,
14
18
  close,
15
19
  columnWidth,
16
20
  createPanels,
17
21
  defOf,
18
22
  dock,
23
+ dockBand,
19
24
  float,
20
25
  floatSize,
21
26
  focus,
@@ -31,6 +36,7 @@ import {
31
36
  panelTargets,
32
37
  pin,
33
38
  placeRank,
39
+ resizeBand,
34
40
  resizeColumn,
35
41
  resizeFloat,
36
42
  samePlaces,
@@ -40,22 +46,27 @@ import {
40
46
  toView,
41
47
  toggleFold,
42
48
  whereIs
43
- } from "./chunk-PWQWD2CS.js";
49
+ } from "./chunk-CJA6LRHN.js";
44
50
  import "./chunk-QMTNB2C3.js";
45
51
  export {
52
+ BAND_SIZE,
46
53
  COLUMN_REACH,
47
54
  DEFAULT_PANELS_OPTIONS,
55
+ EDGES,
48
56
  FLOAT_HEIGHT,
49
57
  FLOAT_MIN,
50
58
  IDENTITY_VIEW,
51
59
  RAIL_EDGE,
52
60
  SIDES,
53
61
  activate,
62
+ bandHeight,
63
+ bandSize,
54
64
  close,
55
65
  columnWidth,
56
66
  createPanels,
57
67
  defOf,
58
68
  dock,
69
+ dockBand,
59
70
  float,
60
71
  floatSize,
61
72
  focus,
@@ -72,6 +83,7 @@ export {
72
83
  pin,
73
84
  placeRank,
74
85
  readPanels,
86
+ resizeBand,
75
87
  resizeColumn,
76
88
  resizeFloat,
77
89
  samePlaces,