@n-uf/placement 26.11.7 → 26.11.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/panels.js CHANGED
@@ -1,3 +1,7 @@
1
+ import {
2
+ readPanels,
3
+ storePanels
4
+ } from "./chunk-XUV6MJ2P.js";
1
5
  import {
2
6
  COLUMN_REACH,
3
7
  DEFAULT_PANELS_OPTIONS,
@@ -6,6 +10,7 @@ import {
6
10
  IDENTITY_VIEW,
7
11
  RAIL_EDGE,
8
12
  SIDES,
13
+ activate,
9
14
  close,
10
15
  columnWidth,
11
16
  createPanels,
@@ -29,130 +34,14 @@ import {
29
34
  resizeColumn,
30
35
  resizeFloat,
31
36
  samePlaces,
37
+ showTabs,
32
38
  tick,
33
39
  toPage,
34
40
  toView,
35
41
  toggleFold,
36
42
  whereIs
37
- } from "./chunk-NNFNMIW4.js";
43
+ } from "./chunk-PWQWD2CS.js";
38
44
  import "./chunk-QMTNB2C3.js";
39
-
40
- // src/panels/store.ts
41
- function storePanels(state) {
42
- const sides = Object.fromEntries(SIDES.map((s) => [s, state.sides[s].map((c) => ({ panels: [...c.panels], width: c.width }))]));
43
- return {
44
- v: 1,
45
- sides,
46
- floats: state.floats.map((f) => ({ id: f.id, rect: { x: f.rect.x, y: f.rect.y, width: f.rect.width, height: f.rect.height }, pinned: !!f.pinned })),
47
- folded: [...state.folded],
48
- kept: [...state.kept],
49
- closed: [...state.closed],
50
- clock: Object.fromEntries(Object.entries(state.clock).map(([k, c]) => [k, { opened: c.opened, used: c.used }]))
51
- };
52
- }
53
- var isObject = (x) => typeof x === "object" && x !== null && !Array.isArray(x);
54
- var finite = (x) => typeof x === "number" && Number.isFinite(x);
55
- function readPanels(data, defs) {
56
- try {
57
- return read(data, defs);
58
- } catch (e) {
59
- return { ok: false, error: `unreadable: ${e instanceof Error ? e.message : typeof e}` };
60
- }
61
- }
62
- function read(data, defs) {
63
- if (!isObject(data)) return { ok: false, error: "not an object" };
64
- if (data.v !== 1) return { ok: false, error: `unknown version ${typeof data.v === "number" || typeof data.v === "string" ? String(data.v) : typeof data.v} (this reads version 1)` };
65
- if (!isObject(data.sides)) return { ok: false, error: "sides is missing" };
66
- const dropped = [];
67
- const drop = (what) => {
68
- if (!dropped.includes(what)) dropped.push(what);
69
- };
70
- const seen = /* @__PURE__ */ new Set();
71
- const take = (x) => {
72
- if (typeof x !== "string") {
73
- drop(`a ${typeof x} where an id goes`);
74
- return null;
75
- }
76
- if (defs && !defOf(defs, x) || seen.has(x)) {
77
- drop(x);
78
- return null;
79
- }
80
- seen.add(x);
81
- return x;
82
- };
83
- const extra = (o, known, prefix) => {
84
- for (const k of Object.keys(o)) if (!known.includes(k)) drop(`${prefix}${k}`);
85
- };
86
- extra(data, ["v", "sides", "floats", "folded", "kept", "closed", "clock"], "");
87
- extra(data.sides, SIDES, "sides.");
88
- const sides = { left: [], right: [] };
89
- for (const side of SIDES) {
90
- const cols = data.sides[side];
91
- if (cols === void 0) continue;
92
- if (!Array.isArray(cols)) {
93
- drop(`sides.${side}`);
94
- continue;
95
- }
96
- for (const c of cols) {
97
- if (!isObject(c) || !Array.isArray(c.panels)) {
98
- drop(`a column on the ${side}`);
99
- continue;
100
- }
101
- extra(c, ["panels", "width"], "column.");
102
- const panels = c.panels.map(take).filter((x) => x !== null);
103
- if (panels.length === 0) continue;
104
- const ds = defs ? panels.map((id) => defOf(defs, id)) : [];
105
- const lo = Math.max(0, ...ds.map((d) => d.width.min));
106
- const hi = Math.max(lo, Math.min(...ds.map((d) => d.width.max)));
107
- const natural = ds.length ? Math.max(...ds.map((d) => d.width.natural)) : 0;
108
- const width = finite(c.width) ? c.width : natural;
109
- sides[side].push({ panels, width: defs ? Math.min(Math.max(width, lo), hi) : Math.max(0, width) });
110
- }
111
- }
112
- const floats = [];
113
- for (const f of Array.isArray(data.floats) ? data.floats : []) {
114
- const r = isObject(f) ? f.rect : void 0;
115
- if (!isObject(f) || !isObject(r) || !finite(r.x) || !finite(r.y) || !finite(r.width) || !finite(r.height)) {
116
- drop(isObject(f) && typeof f.id === "string" ? f.id : "a float");
117
- continue;
118
- }
119
- extra(f, ["id", "rect", "pinned"], "float.");
120
- const id = take(f.id);
121
- if (id === null) continue;
122
- const min = defs ? floatSize(defOf(defs, id)).min : { width: 0, height: 0 };
123
- floats.push({ id, rect: { x: r.x, y: r.y, width: Math.max(min.width, r.width), height: Math.max(min.height, r.height) }, ...f.pinned === true ? { pinned: true } : {} });
124
- }
125
- if (data.floats !== void 0 && !Array.isArray(data.floats)) drop("floats");
126
- const placed = (key) => {
127
- const x = data[key];
128
- if (x === void 0) return [];
129
- if (!Array.isArray(x)) {
130
- drop(key);
131
- return [];
132
- }
133
- const out = [];
134
- for (const id of x) {
135
- if (typeof id === "string" && seen.has(id)) {
136
- if (!out.includes(id)) out.push(id);
137
- } else drop(typeof id === "string" ? id : `a ${typeof id} in ${key}`);
138
- }
139
- return out;
140
- };
141
- const floating = new Set(floats.map((f) => f.id));
142
- const kept = placed("kept").filter((id) => {
143
- if (floating.has(id)) drop(id);
144
- return !floating.has(id);
145
- });
146
- const clock = {};
147
- if (isObject(data.clock)) {
148
- for (const id of Object.keys(data.clock)) if (!seen.has(id)) drop(`clock.${id}`);
149
- for (const id of seen) {
150
- const c = data.clock[id];
151
- clock[id] = isObject(c) && finite(c.opened) && finite(c.used) ? { opened: c.opened, used: c.used } : { opened: 0, used: 0 };
152
- }
153
- }
154
- return { ok: true, state: { sides, floats, folded: placed("folded"), kept, closed: placed("closed"), clock }, dropped };
155
- }
156
45
  export {
157
46
  COLUMN_REACH,
158
47
  DEFAULT_PANELS_OPTIONS,
@@ -161,6 +50,7 @@ export {
161
50
  IDENTITY_VIEW,
162
51
  RAIL_EDGE,
163
52
  SIDES,
53
+ activate,
164
54
  close,
165
55
  columnWidth,
166
56
  createPanels,
@@ -185,6 +75,7 @@ export {
185
75
  resizeColumn,
186
76
  resizeFloat,
187
77
  samePlaces,
78
+ showTabs,
188
79
  storePanels,
189
80
  tick,
190
81
  toPage,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/panels/store.ts"],"sourcesContent":["/**\n * The panels' stored form: `storePanels(state)` gives plain JSON-safe data (`{ v: 1, … }`); `readPanels(data, defs?)`\n * reads parsed data back and never throws. As with the toolbar's `readArrangement`: anything but an object of\n * version 1 is `{ ok: false, error }`. Inside one, it is lenient: an unknown id (with `defs`), a repeated one or a\n * malformed entry is dropped and listed in `dropped`; widths and float sizes are clamped to the defs. A panel the\n * consumer has but the stored state lacks is no error: the consumer places it (`open` with a place, say).\n *\n * Version 1 only gains optional fields. A field this reader doesn't know (a newer writer's, say) is no error either:\n * it is skipped and reported in `dropped` (`\"<field>\"` at the top, `\"sides.<key>\"`, `\"column.<field>\"`,\n * `\"float.<field>\"`; a clock entry for a panel that isn't placed as `\"clock.<id>\"`), so a consumer can tell that\n * something was left out.\n */\nimport type { Rect } from \"../geometry\";\nimport { SIDES, defOf, floatSize, type Clock, type Column, type FloatAt, type PanelDef, type PanelsState, type Side } from \"./model\";\n\nexport interface StoredPanels {\n readonly v: 1;\n readonly sides: Record<Side, { panels: string[]; width: number }[]>;\n readonly floats: { id: string; rect: Rect; pinned: boolean }[];\n readonly folded: string[];\n readonly kept: string[];\n readonly closed: string[];\n readonly clock: Record<string, Clock>;\n}\n\nexport type PanelsRead = { readonly ok: true; readonly state: PanelsState; readonly dropped: readonly string[] } | { readonly ok: false; readonly error: string };\n\nexport function storePanels(state: PanelsState): StoredPanels {\n const sides = Object.fromEntries(SIDES.map((s) => [s, state.sides[s].map((c) => ({ panels: [...c.panels], width: c.width }))])) as StoredPanels[\"sides\"];\n return {\n v: 1,\n sides,\n floats: state.floats.map((f) => ({ id: f.id, rect: { x: f.rect.x, y: f.rect.y, width: f.rect.width, height: f.rect.height }, pinned: !!f.pinned })),\n folded: [...state.folded],\n kept: [...state.kept],\n closed: [...state.closed],\n clock: Object.fromEntries(Object.entries(state.clock).map(([k, c]) => [k, { opened: c.opened, used: c.used }])),\n };\n}\n\nconst isObject = (x: unknown): x is Record<string, unknown> => typeof x === \"object\" && x !== null && !Array.isArray(x);\nconst finite = (x: unknown): x is number => typeof x === \"number\" && Number.isFinite(x);\n\nexport function readPanels(data: unknown, defs?: readonly PanelDef[]): PanelsRead {\n try {\n return read(data, defs);\n } catch (e) {\n // A getter that throws, a proxy: still no throw.\n return { ok: false, error: `unreadable: ${e instanceof Error ? e.message : typeof e}` };\n }\n}\n\nfunction read(data: unknown, defs?: readonly PanelDef[]): PanelsRead {\n if (!isObject(data)) return { ok: false, error: \"not an object\" };\n // Named without serialising it: a BigInt or a circular value must not throw.\n if (data.v !== 1) return { ok: false, error: `unknown version ${typeof data.v === \"number\" || typeof data.v === \"string\" ? String(data.v) : typeof data.v} (this reads version 1)` };\n if (!isObject(data.sides)) return { ok: false, error: \"sides is missing\" };\n const dropped: string[] = [];\n const drop = (what: string): void => {\n if (!dropped.includes(what)) dropped.push(what);\n };\n const seen = new Set<string>();\n // An id the consumer has, not placed yet.\n const take = (x: unknown): string | null => {\n if (typeof x !== \"string\") {\n drop(`a ${typeof x} where an id goes`);\n return null;\n }\n if ((defs && !defOf(defs, x)) || seen.has(x)) {\n drop(x);\n return null;\n }\n seen.add(x);\n return x;\n };\n // Fields this version doesn't know: skipped, and reported.\n const extra = (o: Record<string, unknown>, known: readonly string[], prefix: string): void => {\n for (const k of Object.keys(o)) if (!known.includes(k)) drop(`${prefix}${k}`);\n };\n extra(data, [\"v\", \"sides\", \"floats\", \"folded\", \"kept\", \"closed\", \"clock\"], \"\");\n extra(data.sides, SIDES, \"sides.\");\n const sides = { left: [] as Column[], right: [] as Column[] };\n for (const side of SIDES) {\n const cols = data.sides[side];\n if (cols === undefined) continue;\n if (!Array.isArray(cols)) {\n drop(`sides.${side}`);\n continue;\n }\n for (const c of cols as unknown[]) {\n if (!isObject(c) || !Array.isArray(c.panels)) {\n drop(`a column on the ${side}`);\n continue;\n }\n extra(c, [\"panels\", \"width\"], \"column.\");\n const panels = (c.panels as unknown[]).map(take).filter((x): x is string => x !== null);\n if (panels.length === 0) continue;\n const ds = defs ? panels.map((id) => defOf(defs, id)!) : [];\n const lo = Math.max(0, ...ds.map((d) => d.width.min));\n const hi = Math.max(lo, Math.min(...ds.map((d) => d.width.max)));\n const natural = ds.length ? Math.max(...ds.map((d) => d.width.natural)) : 0;\n const width = finite(c.width) ? c.width : natural;\n sides[side].push({ panels, width: defs ? Math.min(Math.max(width, lo), hi) : Math.max(0, width) });\n }\n }\n const floats: FloatAt[] = [];\n for (const f of Array.isArray(data.floats) ? (data.floats as unknown[]) : []) {\n const r = isObject(f) ? f.rect : undefined;\n if (!isObject(f) || !isObject(r) || !finite(r.x) || !finite(r.y) || !finite(r.width) || !finite(r.height)) {\n drop(isObject(f) && typeof f.id === \"string\" ? f.id : \"a float\");\n continue;\n }\n extra(f, [\"id\", \"rect\", \"pinned\"], \"float.\");\n const id = take(f.id);\n if (id === null) continue;\n const min = defs ? floatSize(defOf(defs, id)).min : { width: 0, height: 0 };\n floats.push({ id, rect: { x: r.x, y: r.y, width: Math.max(min.width, r.width), height: Math.max(min.height, r.height) }, ...(f.pinned === true ? { pinned: true } : {}) });\n }\n if (data.floats !== undefined && !Array.isArray(data.floats)) drop(\"floats\");\n // The lists keep only ids that are placed (a closed panel keeps its place).\n const placed = (key: \"folded\" | \"kept\" | \"closed\"): string[] => {\n const x = data[key];\n if (x === undefined) return [];\n if (!Array.isArray(x)) {\n drop(key);\n return [];\n }\n const out: string[] = [];\n for (const id of x as unknown[]) {\n if (typeof id === \"string\" && seen.has(id)) {\n if (!out.includes(id)) out.push(id);\n } else drop(typeof id === \"string\" ? id : `a ${typeof id} in ${key}`);\n }\n return out;\n };\n const floating = new Set(floats.map((f) => f.id));\n // Only a docked panel is kept open.\n const kept = placed(\"kept\").filter((id) => {\n if (floating.has(id)) drop(id);\n return !floating.has(id);\n });\n const clock: Record<string, Clock> = {};\n if (isObject(data.clock)) {\n for (const id of Object.keys(data.clock)) if (!seen.has(id)) drop(`clock.${id}`);\n for (const id of seen) {\n const c = data.clock[id];\n clock[id] = isObject(c) && finite(c.opened) && finite(c.used) ? { opened: c.opened, used: c.used } : { opened: 0, used: 0 };\n }\n }\n return { ok: true, state: { sides, floats, folded: placed(\"folded\"), kept, closed: placed(\"closed\"), clock }, dropped };\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -23,6 +23,15 @@ interface PanelDef {
23
23
  readonly max: number;
24
24
  readonly natural: number;
25
25
  };
26
+ /**
27
+ * Its height as a section of a stack column (opt-in): it gets its natural height, the column's last open section
28
+ * takes the rest, and when the column is short sections fold to bars by give-way. Without it a section shares the
29
+ * column's height equally with the others, as before.
30
+ */
31
+ readonly height?: {
32
+ readonly min: number;
33
+ readonly natural: number;
34
+ };
26
35
  /** A float's size limits and natural size (default: its natural width, 360 px tall, no smaller than 160 × 120). */
27
36
  readonly float?: {
28
37
  readonly min: Size;
@@ -33,10 +42,16 @@ interface PanelDef {
33
42
  /** May it float (default: yes). */
34
43
  readonly floats?: boolean;
35
44
  }
36
- /** A full-height column: its panels top to bottom, and its stored width (the layout clamps it to its panels' limits). */
45
+ /**
46
+ * A full-height column: its panels top to bottom, and its stored width (the layout clamps it to its panels' limits).
47
+ * `show` "tabs" shows one panel at a time under a strip of tabs: `active` (default, or when `active` isn't one of
48
+ * them: the first panel in the column that isn't closed).
49
+ */
37
50
  interface Column {
38
51
  readonly panels: readonly string[];
39
52
  readonly width: number;
53
+ readonly show?: "stack" | "tabs";
54
+ readonly active?: string;
40
55
  }
41
56
  /** A floating panel: `rect` in page space, or in view space when `pinned`. */
42
57
  interface FloatAt {
@@ -79,19 +94,29 @@ interface PanelsOptions {
79
94
  readonly giveWay: GiveWay;
80
95
  /** "clamp" keeps floats in the view at layout time; "free" never moves them. Default "clamp". */
81
96
  readonly floats: "clamp" | "free";
97
+ /**
98
+ * Where a column folded by hand goes (default "rail"): to its side's rail, or ("ride") as title bars on top of the
99
+ * side's first open column, until every column on that side is folded. Give-way's folds always go to the rail.
100
+ */
101
+ readonly fold: "rail" | "ride";
82
102
  /** How much of a float wider than the view stays in it, px (default 48). */
83
103
  readonly floatVisible: number;
84
104
  /** The pages' minimum width (default 320). */
85
105
  readonly pagesMin: number;
86
106
  /** The page's offset and scale (default: identity). */
87
107
  readonly view: View;
88
- /** A title bar's height: a panel folded in a column, and the part of a float the clamp keeps in the view (default 28). */
108
+ /**
109
+ * A title bar's height: a panel folded in a column, a folded float, a riding column, and the part of a float the
110
+ * clamp keeps in the view (default 28).
111
+ */
89
112
  readonly bar: number;
90
113
  /** A rail's width (default 36). */
91
114
  readonly rail: number;
92
115
  /** A rail segment's height, and the gap above the first one (defaults 36 and 4). */
93
116
  readonly segment: number;
94
117
  readonly railInset: number;
118
+ /** A tabbed column's strip height (default 28). */
119
+ readonly tabs: number;
95
120
  }
96
121
  declare const DEFAULT_PANELS_OPTIONS: PanelsOptions;
97
122
  /** A float's size when its def gives none: this tall, and never smaller than FLOAT_MIN. */
@@ -149,7 +174,8 @@ declare function createPanels(defs: readonly PanelDef[], start: PanelsStart): Pa
149
174
  declare function liftPanel(state: PanelsState, id: string): PanelsState;
150
175
  /**
151
176
  * Open a panel: it shows again where it was, and it is the newest opened and used. A panel placed nowhere goes into
152
- * a new innermost column on `at.side`, `at.width` wide; without `at` it stays placed nowhere.
177
+ * a new innermost column on `at.side`, `at.width` wide; without `at` it stays placed nowhere. In a tabbed column it
178
+ * becomes the tab that shows, as a drop into the column does.
153
179
  */
154
180
  declare function open(state: PanelsState, id: string, at?: {
155
181
  readonly side: Side;
@@ -175,6 +201,10 @@ interface DockOptions {
175
201
  * keeps whether it is kept open.
176
202
  */
177
203
  declare function dock(state: PanelsState, id: string, side: Side, index: number, options?: DockOptions): PanelsState;
204
+ /** Show a column's panels as tabs (one at a time under a strip), or as a stack again. */
205
+ declare function showTabs(state: PanelsState, side: Side, index: number, on: boolean): PanelsState;
206
+ /** Make a docked panel the one its column shows (its tab), and the newest used. */
207
+ declare function activate(state: PanelsState, id: string): PanelsState;
178
208
  /**
179
209
  * Float a panel at `rect` (page space; view space when pinned). A float stays pinned or not unless `pinned` says;
180
210
  * a docked panel floats unpinned. It shows, it is the newest used and on top, and it is no longer kept open.
@@ -187,8 +217,9 @@ declare const toPage: (r: Rect, v: View) => Rect;
187
217
  * Pin a float to the view, or unpin it to the page. `view` is where the page is now (default: identity): the float
188
218
  * doesn't jump, its rect is converted between the two spaces. A float's size is never scaled.
189
219
  *
190
- * `shown` is where the float shows now, in view space (the layout's placed rect for it). When given, it is converted
191
- * instead of the stored rect, so a float the clamp moved stays where it shows rather than jumping to its stored place.
220
+ * `shown` is where the float shows now, in view space (the layout's placed rect for it). When given, its position is
221
+ * converted instead of the stored one, so a float the clamp moved stays where it shows rather than jumping to its
222
+ * stored place. The size stays the stored one: a float folded to a bar, or shrunk by the clamp, keeps its full size.
192
223
  */
193
224
  declare function pin(state: PanelsState, id: string, on: boolean, view?: View, shown?: Rect): PanelsState;
194
225
  /**
@@ -216,6 +247,13 @@ declare function samePlaces(a: PanelsState, b: PanelsState, defs?: readonly Pane
216
247
  * folded by hand is a title bar (`options.bar` tall) and the open ones share the rest of the height equally.
217
248
  * - A column whose panels are all folded is railed: its panels become segments of its side's rail (one rail per
218
249
  * side, `options.rail` wide at the outer edge, segments in side order).
250
+ * - With `options.fold` "ride", a column folded by hand on a side that still has an open column rides instead: its
251
+ * panels become title bars stacked on top of the side's first open column (outer edge first), as wide as that
252
+ * column, and its open panels share the rest of the height. The folded column keeps its stored place and width, and
253
+ * the open columns lie as if it were gone. Only when every column on the side is folded does the side show its rail.
254
+ * Give-way's folds always go to the rail.
255
+ * - A float folded by hand is a title bar: its own x, y and width, `options.bar` tall, still a float (clamped as a
256
+ * bar, `floating`); unfolding brings its full rect back, as the stored rect never changes.
219
257
  * - Give-way: when the open columns, the rails and `pagesMin` don't fit the stage width, columns shrink toward their
220
258
  * minimum, then whole columns fold to the rail, in the policy's order, until the pages fit. Columns holding a kept
221
259
  * panel come after every other column; if the pages still don't fit, they fold too (`kept-folded`). Folding by
@@ -227,8 +265,8 @@ declare function samePlaces(a: PanelsState, b: PanelsState, defs?: readonly Pane
227
265
  */
228
266
 
229
267
  /**
230
- * Where a panel is, structurally: an open part of a column, a folded title bar in a column, a segment of a rail
231
- * (the panel itself isn't laid out), or a float.
268
+ * Where a panel is, structurally: an open part of a column, a folded title bar (in a column, riding on one, or a
269
+ * folded float), a segment of a rail (the panel itself isn't laid out), or a float.
232
270
  */
233
271
  type PanelKind = "column" | "bar" | "segment" | "float";
234
272
  interface PlacedPanel {
@@ -237,7 +275,7 @@ interface PlacedPanel {
237
275
  readonly kind: PanelKind;
238
276
  /** Columns and rails 0, floats 10 and up (a later float on top). */
239
277
  readonly layer: number;
240
- /** In a rail: there is no panel to lay out, only its segment. */
278
+ /** Not drawn as a panel: in a rail (only its segment shows), or a tab that isn't showing (only its `tab`). */
241
279
  readonly hidden: boolean;
242
280
  /** Folded by hand (a bar, or a segment of a column folded by hand), or by give-way (a segment). */
243
281
  readonly folded: null | "hand" | "auto";
@@ -245,9 +283,15 @@ interface PlacedPanel {
245
283
  readonly kept: boolean;
246
284
  /** A pinned float. */
247
285
  readonly pinned: boolean;
286
+ /** It floats (open, or folded to a bar). */
287
+ readonly floating: boolean;
248
288
  /** Docked: its side and column index (the state's). */
249
289
  readonly side?: Side;
250
290
  readonly column?: number;
291
+ /** A riding bar: the index of the column it rides on (`options.fold` "ride"). */
292
+ readonly rides?: number;
293
+ /** In a tabbed column: its tab's rect in the strip (panel order, equal widths). */
294
+ readonly tab?: Rect;
251
295
  /** A float the clamp moved or resized. */
252
296
  readonly clamped?: boolean;
253
297
  }
@@ -269,6 +313,13 @@ interface PlacedColumn {
269
313
  readonly kept: boolean;
270
314
  /** The shown panels, top to bottom. */
271
315
  readonly panels: readonly string[];
316
+ /** Riding: the index of the column its bars ride on; its rect is the bars'. */
317
+ readonly rides?: number;
318
+ /** How it shows its panels (default "stack"). */
319
+ readonly show?: "stack" | "tabs";
320
+ /** Tabbed and laid out: its strip of tabs, and the panel it shows. */
321
+ readonly strip?: Rect;
322
+ readonly active?: string;
272
323
  }
273
324
  interface PlacedRail {
274
325
  readonly side: Side;
@@ -278,7 +329,7 @@ interface PlacedRail {
278
329
  readonly rect: Rect;
279
330
  }[];
280
331
  }
281
- type PanelsNoteCode = "column-shrunk" | "column-folded" | "kept-folded" | "pages-under-min" | "float-clamped" | "float-resized";
332
+ type PanelsNoteCode = "column-shrunk" | "column-folded" | "kept-folded" | "section-folded" | "pages-under-min" | "float-clamped" | "float-resized";
282
333
  /** One note on a layout: a code and its data. */
283
334
  type PanelsNote = {
284
335
  readonly code: "column-shrunk";
@@ -288,7 +339,7 @@ type PanelsNote = {
288
339
  readonly from: number;
289
340
  readonly to: number;
290
341
  } | {
291
- readonly code: "column-folded" | "kept-folded";
342
+ readonly code: "column-folded" | "kept-folded" | "section-folded";
292
343
  readonly side: Side;
293
344
  readonly column: number;
294
345
  readonly items: readonly string[];
@@ -429,4 +480,4 @@ interface PanelStopsOptions {
429
480
  /** The panel's places in reading order, for the arrow keys and a "Move to" menu (`keyboardStops` calls this). */
430
481
  declare function panelStops(targets: readonly PanelTarget[], options?: PanelStopsOptions): PanelStop[];
431
482
 
432
- export { resizeFloat as $, dock as A, float as B, type Clock as C, DEFAULT_PANELS_OPTIONS as D, floatSize as E, FLOAT_HEIGHT as F, type GiveWay as G, focus as H, IDENTITY_VIEW as I, giveWayOrder as J, homePlace as K, keep as L, layoutPanels as M, liftPanel as N, open as O, type PanelsState as P, ownWidth as Q, RAIL_EDGE as R, type Side as S, panelDrop as T, panelStops as U, type View as V, type Where as W, panelTargets as X, pin as Y, placeRank as Z, resizeColumn as _, type PanelDef as a, samePlaces as a0, tick as a1, toPage as a2, toView as a3, toggleFold as a4, whereIs as a5, type Target as a6, COLUMN_REACH as b, type Column as c, type DockOptions as d, FLOAT_MIN as e, type FloatAt as f, type PanelDrop as g, type PanelKind as h, type PanelPlace as i, type PanelStop as j, type PanelStopsOptions as k, type PanelTarget as l, type PanelTargetInput as m, type PanelsLayout as n, type PanelsNote as o, type PanelsNoteCode as p, type PanelsOptions as q, type PanelsStart as r, type PlacedColumn as s, type PlacedPanel as t, type PlacedRail as u, SIDES as v, close as w, columnWidth as x, createPanels as y, defOf as z };
483
+ export { resizeColumn as $, columnWidth as A, createPanels as B, type Clock as C, DEFAULT_PANELS_OPTIONS as D, defOf as E, FLOAT_HEIGHT as F, type GiveWay as G, dock as H, IDENTITY_VIEW as I, float as J, floatSize as K, focus as L, giveWayOrder as M, homePlace as N, keep as O, type PanelsOptions as P, liftPanel as Q, RAIL_EDGE as R, type Side as S, open as T, ownWidth as U, type View as V, type Where as W, panelStops as X, panelTargets as Y, pin as Z, placeRank as _, type PanelDef as a, resizeFloat as a0, samePlaces as a1, showTabs as a2, tick as a3, toPage as a4, toView as a5, toggleFold as a6, whereIs as a7, type Target as a8, type PanelsState as b, type PanelTargetInput as c, type PanelTarget as d, type PanelDrop as e, type PanelsLayout as f, COLUMN_REACH as g, type Column as h, type DockOptions as i, FLOAT_MIN as j, type FloatAt as k, layoutPanels as l, type PanelKind as m, type PanelPlace as n, type PanelStop as o, panelDrop as p, type PanelStopsOptions as q, type PanelsNote as r, type PanelsNoteCode as s, type PanelsStart as t, type PlacedColumn as u, type PlacedPanel as v, type PlacedRail as w, SIDES as x, activate as y, close as z };
package/dist/targets.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { a6 as Target, l as PanelTarget, k as PanelStopsOptions, j as PanelStop } from './targets-BEqoVKbF.js';
1
+ import { a8 as Target, d as PanelTarget, q as PanelStopsOptions, o as PanelStop } from './targets-DwOTs4UC.js';
2
2
  import { R as Rect, P as Point, S as Size } from './geometry-mL-GTRti.js';
3
3
  import { D as DeskState, g as Layout, a as Construction, O as Options } from './constructions-VDK_mwmz.js';
4
4
  import { Place, Arrangement, HostId, HostSpec, GroupSize } from './toolbar.js';
package/dist/targets.js CHANGED
@@ -38,7 +38,7 @@ import {
38
38
  } from "./chunk-WLMJ6JGO.js";
39
39
  import {
40
40
  panelStops
41
- } from "./chunk-NNFNMIW4.js";
41
+ } from "./chunk-PWQWD2CS.js";
42
42
  import {
43
43
  centre,
44
44
  overlap,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@n-uf/placement",
3
- "version": "26.11.7",
4
- "description": "Where things go: desk docks, rails and palettes, toolbar groups, and the drop targets for each. Pure state in, rects out. No DOM, no framework, no motion.",
3
+ "version": "26.11.9",
4
+ "description": "Where things go: desk docks, rails and palettes, panel columns, toolbar groups, and the drop targets for each. Pure state in, rects out. No DOM, no framework, no motion.",
5
5
  "keywords": [
6
6
  "layout",
7
7
  "docking",
@@ -48,6 +48,10 @@
48
48
  "types": "./dist/panels.d.ts",
49
49
  "default": "./dist/panels.js"
50
50
  },
51
+ "./desk": {
52
+ "types": "./dist/desk.d.ts",
53
+ "default": "./dist/desk.js"
54
+ },
51
55
  "./package.json": "./package.json"
52
56
  },
53
57
  "publishConfig": {
@@ -1 +0,0 @@
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. 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/**\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 /** 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). */\n readonly sides?: readonly Side[];\n /** May it float (default: yes). */\n readonly floats?: boolean;\n}\n\n/** A full-height column: its panels top to bottom, and its stored width (the layout clamps it to its panels' limits). */\nexport interface Column {\n readonly panels: readonly string[];\n readonly width: number;\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/** 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}\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 /** 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 /** A title bar's height: a panel folded in a column, and the part of a float the clamp keeps in the view (default 28). */\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}\n\nexport const DEFAULT_PANELS_OPTIONS: PanelsOptions = {\n giveWay: { order: \"oldest\", by: \"used\" },\n floats: \"clamp\",\n floatVisible: 48,\n pagesMin: 320,\n view: IDENTITY_VIEW,\n bar: 28,\n rail: 36,\n segment: 36,\n railInset: 4,\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), floating, or nowhere. */\nexport type Where = { readonly kind: \"column\"; readonly side: Side; readonly index: number } | { readonly kind: \"float\"; readonly float: FloatAt } | { 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 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/**\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 * 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 /** 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, floats), so the\n * 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 order = [...sides.left, ...sides.right].flatMap((c) => c.panels).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 return { sides, floats, folded: [...(start.folded ?? [])], kept: [...(start.kept ?? [])], closed: [...(start.closed ?? [])], clock };\n}\n\n// --- changes -------------------------------------------------------------------------------------------------------\n\n/** The state with `id` taken out of its column (an emptied column goes) or the floats. Nothing else changes. */\nexport function liftPanel(state: PanelsState, id: string): PanelsState {\n const lift = (cols: readonly Column[]): Column[] => cols.map((c) => ({ ...c, panels: without(c.panels, id) })).filter((c) => c.panels.length > 0);\n return { ...state, sides: { left: lift(state.sides.left), right: lift(state.sides.right) }, floats: state.floats.filter((f) => f.id !== id) };\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; without `at` it stays placed nowhere.\n */\nexport function open(state: PanelsState, id: string, at?: { readonly side: Side; readonly width: number }): PanelsState {\n let s: PanelsState = { ...state, closed: without(state.closed, id) };\n if (at && whereIs(s, id).kind === \"none\") s = { ...s, sides: { ...s.sides, [at.side]: [...s.sides[at.side], { panels: [id], width: at.width }] } };\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/** Fold a panel to its title bar by hand, or unfold it (unfolding is a use). */\nexport function toggleFold(state: PanelsState, id: string): PanelsState {\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 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 return whereIs(state, id).kind === \"column\" ? { ...state, kept: withOnce(state.kept, id) } : state;\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 /** A new column's width (default: the width of the column the panel leaves, else 0, which the layout clamps to the minimum). */\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` at the\n * bottom of the column at `index` (counted once the panel is lifted out). It shows, it is the newest used, and it\n * 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 if (options.into && cols[index]) cols[index] = { ...cols[index]!, panels: [...cols[index]!.panels, 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/**\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, it is converted\n * instead of the stored rect, so a float the clamp moved stays where it shows rather than jumping to its stored place.\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.\n const seen = shown ? { ...shown } : 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 => SIDES.map((side) => s.sides[side].map((c) => `${c.panels.join(\",\")}@${Math.round(columnWidth(defs, c))}`).join(\"|\")).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 set = (l: readonly string[]): string => [...l].sort().join(\",\");\n return cols(a) === cols(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 * - 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 */\nimport { rect, type Rect, type Size } from \"../geometry\";\nimport { DEFAULT_PANELS_OPTIONS, SIDES, defOf, floatSize, toView, type PanelDef, type PanelsOptions, type PanelsState, type Side } from \"./model\";\n\n/**\n * Where a panel is, structurally: an open part of a column, a folded title bar in a column, a segment of a rail\n * (the panel itself isn't laid out), or a float.\n */\nexport type PanelKind = \"column\" | \"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 and rails 0, floats 10 and up (a later float on top). */\n readonly layer: number;\n /** In a rail: there is no panel to lay out, only its segment. */\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 /** Docked: its side and column index (the state's). */\n readonly side?: Side;\n readonly column?: number;\n /** A float the clamp moved or resized. */\n readonly clamped?: boolean;\n}\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}\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 = \"column-shrunk\" | \"column-folded\" | \"kept-folded\" | \"pages-under-min\" | \"float-clamped\" | \"float-resized\";\n\n/** One note on a layout: a code and its data. */\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\"; 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\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}\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}\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\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 cols.push({ side, index, panels, min, max, width, hand: panels.every((id) => folded.has(id)), kept: panels.some((id) => kept.has(id)), age });\n });\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 const railed = (side: Side): boolean => cols.some((c) => c.side === side && (c.hand || auto.has(c)));\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 - 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 inRail = mine.filter((c) => c.hand || g.auto.has(c));\n if (inRail.length) {\n const r = side === \"left\" ? rect(0, 0, opt.rail, H) : rect(W - opt.rail, 0, opt.rail, H);\n const segments = inRail.flatMap((c) => c.panels).map((id, i) => ({ id, rect: rect(r.x, 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, side, column: c.index });\n }\n if (side === \"left\") x0 = opt.rail;\n else x1 = W - opt.rail;\n }\n for (const c of mine) {\n const w = g.widths.get(c);\n let r: Rect;\n if (w === undefined) r = rect(side === \"left\" ? x0 : x1, 0, 0, H);\n else if (side === \"left\") {\n r = rect(x0, 0, w, H);\n x0 += w;\n } else {\n x1 -= w;\n r = rect(x1, 0, w, H);\n }\n placedCols.push({ side, index: c.index, rect: r, width: c.width, min: c.min, max: c.max, folded: c.hand ? \"hand\" : g.auto.has(c) ? \"auto\" : null, shrunk: w !== undefined && w < c.width, kept: c.kept, panels: c.panels });\n if (w === undefined) continue;\n const bars = c.panels.filter((id) => folded.has(id)).length;\n const share = (H - bars * opt.bar) / (c.panels.length - bars);\n let y = 0;\n for (const id of c.panels) {\n const bar = folded.has(id);\n const h = bar ? opt.bar : share;\n items.set(id, { rect: rect(r.x, y, r.width, h), kind: bar ? \"bar\" : \"column\", layer: 0, hidden: false, folded: bar ? \"hand\" : null, kept: kept.has(id), pinned: false, side, column: c.index });\n y += h;\n }\n }\n }\n const pages = rect(x0, 0, Math.max(0, x1 - x0), H);\n if (pages.width < opt.pagesMin) notes.push({ code: \"pages-under-min\", width: pages.width, min: opt.pagesMin });\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 const at = 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 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, { rect: f.pinned ? r : toView(r, opt.view), kind: \"float\", layer: 10 + i, hidden: false, folded: null, kept: false, pinned: !!f.pinned, ...(clamped ? { clamped: true } : {}) });\n });\n\n return { items, columns: placedCols, rails, notes, pages };\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 * - `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 *\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, SIDES, defOf, dock, float, floatSize, liftPanel, ownWidth, samePlaces, toPage, whereIs, type PanelDef, type PanelsOptions, type PanelsState, type Side } from \"./model\";\n\n/** Where a drop puts a panel. `index` is a column index in the state with the panel lifted out. */\nexport type PanelPlace =\n | { readonly kind: \"column\"; readonly side: Side; readonly index: number }\n | { readonly kind: \"into\"; readonly side: Side; readonly index: number }\n | { readonly kind: \"rail\"; readonly side: Side }\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\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}\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/** A place's rank in reading order: the left side outer to inner, the right side inner to outer, floating last. */\nexport function placeRank(place: PanelPlace): number {\n switch (place.kind) {\n case \"float\":\n return 3000;\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 return place.side === \"left\" ? 2 + 2 * place.index : 1997 - 2 * place.index;\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. */\nexport function homePlace(state: PanelsState, id: string): PanelPlace | null {\n const w = whereIs(state, id);\n if (w.kind === \"float\") return { kind: \"float\" };\n if (w.kind === \"none\") return null;\n return state.sides[w.side][w.index]!.panels.length === 1 ? { kind: \"column\", side: w.side, index: w.index } : { 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 const out: PanelTarget[] = [];\n const add = (place: PanelPlace, priority: 1 | 2 | 3, hit: Rect, make: PanelTarget[\"make\"], free = false): 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: place.kind === \"float\" ? \"float\" : place.kind === \"rail\" ? `rail:${place.side}` : `${place.kind}:${place.side}:${place.index}`, priority, hit, panel: id, place, order: placeRank(place), make, ...(free ? { free: true } : {}) });\n };\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, 0, RAIL_EDGE, H) : rect(W - RAIL_EDGE, 0, RAIL_EDGE, H);\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, 0, b - a, H), () => dock(state, id, side, i, { width }));\n };\n if (open.length === 0) band(left ? l0.pages.x : l0.pages.x + l0.pages.width, 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 add({ kind: \"into\", side, index: c.index }, 2, c.rect, () => dock(state, id, side, c.index, { into: true }));\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 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 shown = layoutPanels(defs, s, stage, opt).items.get(id)!.rect;\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.\n if (h) stops.push({ id: \"home\", place: h.place, state: h.state, home: true, order: placeRank(h.place) + (h.place.kind === \"float\" ? 1 : 0.5) });\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","open"]}