@n-uf/placement 26.11.8 → 26.11.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +55 -0
- package/README.md +142 -6
- package/dist/chunk-7R5H2ABL.js +172 -0
- package/dist/chunk-7R5H2ABL.js.map +1 -0
- package/dist/chunk-PJD5HKYX.js +759 -0
- package/dist/chunk-PJD5HKYX.js.map +1 -0
- package/dist/desk.d.ts +48 -0
- package/dist/desk.js +111 -0
- package/dist/desk.js.map +1 -0
- package/dist/panels.d.ts +17 -4
- package/dist/panels.js +21 -118
- package/dist/panels.js.map +1 -1
- package/dist/{targets-DqhZf3XZ.d.ts → targets-CLV69zMw.d.ts} +181 -24
- package/dist/targets.d.ts +1 -1
- package/dist/targets.js +1 -1
- package/package.json +5 -1
- package/dist/chunk-QR7MGDX6.js +0 -448
- package/dist/chunk-QR7MGDX6.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,61 @@
|
|
|
3
3
|
Versions are calendar versions, `YY.M.R` (year, month of the release, counter within the month), shared with
|
|
4
4
|
`@n-uf/motion`: both packages carry the same version, and a release bumps both.
|
|
5
5
|
|
|
6
|
+
## 26.11.10
|
|
7
|
+
|
|
8
|
+
- `@n-uf/placement/panels`, bands and reserved room (all opt-in; a state and options without them lay out as before,
|
|
9
|
+
and the store stays v1):
|
|
10
|
+
- Bands: a top and a bottom dock (`options.bands`, `{ top?, bottom? }`, each `{ mode: "reserved" | "overlay",
|
|
11
|
+
span: "between" | "full" }`). Its panels sit side by side and share its width (`kind` `"band"`, `edge`, `index`);
|
|
12
|
+
a stored height clamped to `PanelDef.band` (default `BAND_SIZE`, min 120, max 480, natural 200). It folds as a
|
|
13
|
+
whole, to one bar. `layout.bands` (`PlacedBand`). New: `Edge`, `EDGES`, `Place`, `Band`, `BandOption`,
|
|
14
|
+
`PanelsState.bands`, `PanelsStart.top` / `bottom`, `dockBand`, `resizeBand`, `bandSize`, `bandHeight`;
|
|
15
|
+
`open(state, id, { edge, height? })`; `Where` and `PanelPlace` gain a `band` kind; `PanelDef.sides` may name
|
|
16
|
+
edges.
|
|
17
|
+
- Height give-way for bands: `options.pagesMinHeight` (default 240). Reserved bands shrink, then fold to a bar,
|
|
18
|
+
unkept before kept, policy order, bottom first on a tie, until the pages keep the min; then the overlay bands,
|
|
19
|
+
together, until they leave the min of the pages uncovered. Notes `band-shrunk`, `band-folded`, `kept-folded` with
|
|
20
|
+
`edge`; `pages-short` when the pages' rect is still under the min (overlay bands never cause it); `band-off` for a
|
|
21
|
+
band on an edge the options don't enable.
|
|
22
|
+
- Reserved room: `options.reserve` (`{ top?, right?, bottom?, left? }`) keeps px clear along the pages' edges for an
|
|
23
|
+
app's toolbar; `layout.reserved` has the rects. `pagesMin` and `pagesMinHeight` count after it. An overlay band
|
|
24
|
+
lies next to the reserve on its edge, on the pages' side, never over it.
|
|
25
|
+
- Targets `band:<edge>:<i>` and `band:<edge>` (an empty enabled edge). The stored form carries `bands` (an optional
|
|
26
|
+
v1 field).
|
|
27
|
+
- Typing: `PanelKind`, `PanelPlace`, `Where` and `PanelsNote` gain members, and `@n-uf/placement/desk`'s `PresetId`
|
|
28
|
+
gains `"docksFull"` (so `PRESETS` has a fourth key), so an exhaustive `switch` over them, or a `Record` keyed by
|
|
29
|
+
`PresetId`, in a consumer needs the new cases.
|
|
30
|
+
- `@n-uf/placement/desk`: `docks` and `dockTear` get a bottom band (reserved, between the columns); a new preset
|
|
31
|
+
`docksFull` (the bottom band full width). `DeskHint.bottom` starts the band; else the last def whose `sides` names
|
|
32
|
+
`"bottom"`. `navigator` has no band. Because the band is enabled, `docks` and `dockTear` now always offer a
|
|
33
|
+
`band:bottom` drop strip along the pages' bottom, even when the band is empty (a drop there used to be a float in
|
|
34
|
+
`dockTear`, and no drop in `docks`).
|
|
35
|
+
- Known limit: with `pagesMinHeight` below about 100 px on a very short stage, a column can be shorter than its title
|
|
36
|
+
bars, which then run past it (column bars were always a fixed `options.bar` tall). Keep the default 240, or at least
|
|
37
|
+
a few bars' height, when bands are on.
|
|
38
|
+
|
|
39
|
+
## 26.11.9
|
|
40
|
+
|
|
41
|
+
- `@n-uf/placement/panels`:
|
|
42
|
+
- Tabs: `Column.show` (`"stack"`, the default, or `"tabs"`) and `Column.active`. A tabbed column draws a strip
|
|
43
|
+
`options.tabs` tall (new chrome size, default 28; `PlacedColumn.strip`); its active panel takes the rest and the
|
|
44
|
+
others are `hidden`, each with its `tab` rect in the strip. It folds as a whole: its active panel folded shows only
|
|
45
|
+
the strip, every panel folded goes to the rail (or rides). `showTabs(state, side, index, on)`, `activate(state, id)`
|
|
46
|
+
(a use). A drop `into` a tabbed column adds a tab at the end and shows it, and so does `open` on a panel in one; a
|
|
47
|
+
panel that leaves takes its `active` mark with it. With no `active` (or one that isn't there), the column shows its
|
|
48
|
+
first panel that isn't closed.
|
|
49
|
+
- Height give-way, opt-in: `PanelDef.height` (`{ min, natural }`). In a stack column where an open section has one,
|
|
50
|
+
sections get their natural heights and the last open one the rest (never under its min); sections without one
|
|
51
|
+
share what is left, never under a bar's height. The others' natural heights give way toward their mins first;
|
|
52
|
+
still short of room, open sections fold to bars in give-way policy order (kept last, never the last open one, never
|
|
53
|
+
one whose min is no more than a bar), note `section-folded`. It never writes `folded`. Columns without `height`
|
|
54
|
+
defs are unchanged.
|
|
55
|
+
- The stored form carries a column's `show` and `active` (optional v1 fields); an `active` that isn't in its column
|
|
56
|
+
is dropped as `"column.active:<id>"`, an unknown `show` as `"column.show"`.
|
|
57
|
+
- New entry `@n-uf/placement/desk`: presets as data on `./panels` (`docks`, `dockTear`, `navigator`; `PRESETS`,
|
|
58
|
+
`presetLayout`, `presetTargets`, `presetDrop`, `presetInput`). It imports only `./panels`' public index (a guard test
|
|
59
|
+
holds it to that) and carries no titles, words or toolbar wiring. `./dock` is unchanged.
|
|
60
|
+
|
|
6
61
|
## 26.11.8
|
|
7
62
|
|
|
8
63
|
- `@n-uf/placement/panels`:
|
package/README.md
CHANGED
|
@@ -34,9 +34,11 @@ without importing each other: a target list from `@n-uf/placement/targets` is ex
|
|
|
34
34
|
- **`/targets`**: drop targets (`{ id, priority, hit, slot?, label?, free? }`) for the desk's constructions,
|
|
35
35
|
toolbar hosts (each with its `slot`, and `allows` to leave out places a group may not take) and pane zones; and
|
|
36
36
|
`keyboardStops`, one ordered list of places for the arrow keys and a "Move to" menu.
|
|
37
|
-
- **`/panels`**: tool panels with string ids: full-height columns per side, each with its own width
|
|
38
|
-
title bar or a rail; give-way by age when the pages run out of room
|
|
39
|
-
their drop targets; and a
|
|
37
|
+
- **`/panels`**: tool panels with string ids: full-height columns per side, each with its own width, shown as a
|
|
38
|
+
stack of sections or as tabs; folding to a title bar or a rail; give-way by age when the pages run out of room (and,
|
|
39
|
+
opt-in, when a column runs out of height); resizable floats, some pinned to the view; their drop targets; and a
|
|
40
|
+
stored form.
|
|
41
|
+
- **`/desk`**: desk presets (`docks`, `dockTear`, `navigator`) as data on `/panels`: options and a start state.
|
|
40
42
|
|
|
41
43
|
Rendering stays in the app: it draws the rects, measures its groups, and feeds pointer samples to a drag intent.
|
|
42
44
|
|
|
@@ -210,9 +212,96 @@ gain its room), and its stored place and width are untouched, so unfolding puts
|
|
|
210
212
|
every column on a side is folded does the side show its rail. Give-way's folds (`column-folded`, `kept-folded`) go to
|
|
211
213
|
the rail in both modes.
|
|
212
214
|
|
|
215
|
+
**Tabs**: a column with `show: "tabs"` shows one panel at a time, its `active` one (default, or when `active` isn't
|
|
216
|
+
one of them: the first panel in the column that isn't closed), under a strip
|
|
217
|
+
`options.tabs` tall (default 28). The strip is `PlacedColumn.strip`, and each panel's `tab` is its header's rect in it
|
|
218
|
+
(panel order, equal widths); the others are `hidden`. A tabbed column folds as a whole: with its active panel in
|
|
219
|
+
`folded` it shows only its strip (the active panel is a `"bar"` there); with every panel folded it goes to the rail,
|
|
220
|
+
or rides, as a stack column does. `showTabs(state, side, index, on)` switches a column; `activate(state, id)` shows a
|
|
221
|
+
tab and counts as a use. A drop `into` a tabbed column adds a tab at the end and shows it, and `open` on a panel in a
|
|
222
|
+
tabbed column shows its tab too.
|
|
223
|
+
|
|
224
|
+
**Section heights** (opt-in): a `PanelDef.height` (`{ min, natural }`) gives a section of a stack column its natural
|
|
225
|
+
height; the column's last open section takes the rest, never under its min, and sections without one share what is
|
|
226
|
+
left equally, never under a bar's height (`options.bar`). The others' natural heights give way toward their mins
|
|
227
|
+
first. When the open sections' mins and the bars still don't fit, open sections fold to bars by the give-way policy
|
|
228
|
+
(kept last, never the last open one, and never one whose min is no more than a bar, since folding it gains nothing),
|
|
229
|
+
each with a `section-folded` note; that never writes `folded`, so a taller stage unfolds them. Columns without
|
|
230
|
+
`height` defs lay out as before.
|
|
231
|
+
|
|
213
232
|
**Changes** are pure: `open`, `close`, `focus`, `toggleFold`, `keep`, `dock(state, id, side, index, { into?, width? })`,
|
|
214
233
|
`float`, `pin(state, id, on, view?, shown?)` (pass the layout's rect as `shown` so a clamped float pins where it
|
|
215
|
-
shows), `resizeColumn`, `resizeFloat`.
|
|
234
|
+
shows), `resizeColumn`, `resizeFloat`, `showTabs`, `activate`, and for bands `dockBand`, `resizeBand`.
|
|
235
|
+
|
|
236
|
+
### Bands
|
|
237
|
+
|
|
238
|
+
A band is a horizontal dock along the stage's top or bottom edge (opt-in: `options.bands`, default none). Its panels
|
|
239
|
+
sit side by side, left to right, and share its width equally; it has one stored height, clamped to its panels' limits
|
|
240
|
+
(`PanelDef.band`, default `BAND_SIZE`: min 120, max 480, natural 200; the largest min and the smallest max win, as a
|
|
241
|
+
column's width does). Each enabled edge says how its band lies:
|
|
242
|
+
|
|
243
|
+
- `mode: "reserved"` shortens the pages; `"overlay"` lies over the pages' upper or lower part (layer 5, over columns'
|
|
244
|
+
layer 0 and under floats) and leaves the pages' rect as it is.
|
|
245
|
+
- `span: "full"` takes its height from the stage first, across the whole width, and the columns and rails stand on it
|
|
246
|
+
(or hang from it); `"between"` runs between the innermost open column (or rail) on each side.
|
|
247
|
+
|
|
248
|
+
A band's open panels are `kind` `"band"` (with `edge` and `index`); `layout.bands` has each band as laid out
|
|
249
|
+
(`PlacedBand`: `rect`, `height`, `min`, `max`, `folded`, `shrunk`, `kept`, `mode`, `span`, `panels`). It folds as a
|
|
250
|
+
whole: `toggleFold` on any of its panels folds or unfolds them all, and a folded band is one bar, `options.bar` tall,
|
|
251
|
+
each panel a `"bar"` side by side. `keep` works on band panels.
|
|
252
|
+
|
|
253
|
+
**Height give-way**: when the pages would be shorter than `pagesMinHeight` (default 240; counted after the top and
|
|
254
|
+
bottom reserves), reserved bands shrink toward their min, then fold to a bar, unkept before kept, in the give-way
|
|
255
|
+
policy's order, bottom before top on a tie (`band-shrunk`, `band-folded`, or `kept-folded` with `edge`); they leave the
|
|
256
|
+
pages room for the overlay bands' bars at least. Then the overlay bands give way the same way, together, until they leave
|
|
257
|
+
`pagesMinHeight` of the pages uncovered, so a top and a bottom one never meet. Give-way never writes `folded`, so a
|
|
258
|
+
taller stage brings a band back. If the pages' rect is still under the min: `pages-short` (overlay bands don't change
|
|
259
|
+
the pages' rect, so they never cause it; how far one covers the pages is its own `band-shrunk` or `band-folded`).
|
|
260
|
+
Columns never give way by height to a band.
|
|
261
|
+
|
|
262
|
+
`dockBand(state, id, edge, index, defs?)` puts a panel into a band (0 the leftmost, past the end the rightmost; a new
|
|
263
|
+
band takes the panel's natural band height); `open(state, id, { edge, height? })` puts a panel placed nowhere at a
|
|
264
|
+
band's right end; `liftPanel`, `dock` and `float` take a panel out, and an emptied band goes from the state.
|
|
265
|
+
`createPanels` takes `top` and `bottom` (the clock counts left, right, top, bottom, floats). A band in the state on an
|
|
266
|
+
edge the options don't enable is left out of `items` (`band-off`). A def's `sides` may name edges: without `sides` a
|
|
267
|
+
panel may go to every enabled edge; with them, only where they say. The drop targets add `band:<edge>:<i>` (the slots
|
|
268
|
+
at a band's ends and between its panels, the band split at its panels' middles) and, on an empty enabled edge,
|
|
269
|
+
`band:<edge>` (a strip `2 × bar` tall along it inside the pages); a drop's `slot` is the panel's share of the band.
|
|
270
|
+
|
|
271
|
+
```ts
|
|
272
|
+
import { createPanels, layoutPanels, panelTargets, type PanelDef } from "@n-uf/placement/panels";
|
|
273
|
+
|
|
274
|
+
const defs: PanelDef[] = [
|
|
275
|
+
{ id: "files", width: { min: 180, natural: 220, max: 360 } },
|
|
276
|
+
{ id: "history", width: { min: 200, natural: 240, max: 360 }, band: { min: 100, max: 400, natural: 180 } },
|
|
277
|
+
];
|
|
278
|
+
const state = createPanels(defs, { left: [["files"]], bottom: ["history"] });
|
|
279
|
+
const options = { bands: { bottom: { mode: "reserved", span: "between" } } } as const;
|
|
280
|
+
const tall = layoutPanels(defs, state, { width: 1200, height: 700 }, options);
|
|
281
|
+
console.log(tall.bands.bottom!.rect, tall.pages); // { x: 220, y: 520, width: 980, height: 180 } { x: 220, y: 0, width: 980, height: 520 }
|
|
282
|
+
const short = layoutPanels(defs, state, { width: 1200, height: 300 }, options);
|
|
283
|
+
console.log(short.notes.map((n) => n.code), short.items.get("history")!.kind); // [ 'band-folded' ] bar
|
|
284
|
+
const targets = panelTargets({ defs, state, id: "files", stage: { width: 1200, height: 700 }, options });
|
|
285
|
+
console.log(targets.filter((t) => t.place.kind === "band").map((t) => t.id)); // [ 'band:bottom:0', 'band:bottom:1' ]
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
### Reserved room
|
|
289
|
+
|
|
290
|
+
`options.reserve` (`{ top?, right?, bottom?, left? }`, px, default none) keeps room clear along the pages' edges for a
|
|
291
|
+
toolbar the app draws; `./toolbar` stays the toolbar's model, and placement neither draws nor names it. The reserve
|
|
292
|
+
comes off the pages' area after the columns and bands: `layout.reserved.top` is the pages' full width and `reserve.top`
|
|
293
|
+
tall at their top (bottom likewise), and the left and right reserves are as tall as what the top and bottom reserves
|
|
294
|
+
(and overlay bands) leave. `pagesMin` counts after the left and right reserves, `pagesMinHeight` after the top and
|
|
295
|
+
bottom ones; a reserve never shrinks or folds. An overlay band lies next to the reserve on its edge, on the pages' side, never over it.
|
|
296
|
+
|
|
297
|
+
```ts
|
|
298
|
+
// The defs and state above; without band options the band is off (a `band-off` note).
|
|
299
|
+
const l = layoutPanels(defs, state, { width: 1200, height: 700 }, { reserve: { top: 40 } });
|
|
300
|
+
console.log(l.reserved.top, l.pages); // { x: 220, y: 0, width: 980, height: 40 } { x: 220, y: 40, width: 980, height: 660 }
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
Without band options, no `bands` in the state and no reserve, every layout, target and note is what it was before
|
|
304
|
+
bands.
|
|
216
305
|
|
|
217
306
|
**Drop targets**: `panelTargets({ defs, state, id, stage, options?, allows? })` gives `column:<side>:<i>` (a new
|
|
218
307
|
column as wide as the panel's own width), `into:<side>:<i>` (stack into a column), `rail:<side>` (dock folded) and
|
|
@@ -243,17 +332,64 @@ console.log(stops.map((s) => (s.home ? "home" : s.id))); // [ 'rail:left', 'colu
|
|
|
243
332
|
parsed data back and never throws. Anything but an object of version 1 is `{ ok: false, error }`; inside one, unknown
|
|
244
333
|
or repeated ids and malformed entries are dropped and listed in `dropped`, and widths and float sizes are clamped to
|
|
245
334
|
the defs. Version 1 only gains optional fields: a field this reader doesn't know is skipped and listed in `dropped`
|
|
246
|
-
too (`"theme"`, `"sides.bottom"`, `"column.<field>"`, `"float.<field>"`, `"clock.<id>"`).
|
|
247
|
-
|
|
335
|
+
too (`"theme"`, `"sides.bottom"`, `"column.<field>"`, `"float.<field>"`, `"clock.<id>"`). A column's `show` and
|
|
336
|
+
`active` are carried; an `active` that isn't one of the column's panels is dropped as `"column.active:<id>"`. `bands`
|
|
337
|
+
is carried too, only when the state has one: an unknown edge is dropped as `"bands.<key>"`, a band without a panels
|
|
338
|
+
list or a numeric height (or whose panels are all dropped) as `"bands.<edge>"`, an unknown field in one as
|
|
339
|
+
`"band.<field>"`, and heights are clamped to the defs. The note codes (`PanelsNoteCode`):
|
|
248
340
|
|
|
249
341
|
| Code | Says | Also |
|
|
250
342
|
|---|---|---|
|
|
251
343
|
| `column-shrunk` | a column narrowed toward its minimum | `side`, `column`, `items`, `from`, `to` |
|
|
252
344
|
| `column-folded` | a column folded to its side's rail | `side`, `column`, `items` |
|
|
253
345
|
| `kept-folded` | a kept column folded: the pages needed the room | `side`, `column`, `items` |
|
|
346
|
+
| `section-folded` | a section of a stack column folded to a bar: the column was short | `side`, `column`, `items` |
|
|
254
347
|
| `pages-under-min` | the pages are under `pagesMin` with every column folded | `width`, `min` |
|
|
255
348
|
| `float-resized` | a float shrank to fit the view | `items` |
|
|
256
349
|
| `float-clamped` | a float moved to stay in the view | `items` |
|
|
350
|
+
| `band-shrunk` | a band lowered toward its min: the pages needed the height | `edge`, `items`, `from`, `to` |
|
|
351
|
+
| `band-folded` | a band folded to a bar: the pages needed the height | `edge`, `items` |
|
|
352
|
+
| `kept-folded` | (on a band) a kept band folded, last | `edge`, `items` |
|
|
353
|
+
| `band-off` | a band on an edge the options don't enable: its panels aren't laid out | `edge`, `items` |
|
|
354
|
+
| `pages-short` | the pages' rect is under `pagesMinHeight` with every reserved band folded (or by the reserves alone) | `height`, `min` |
|
|
355
|
+
|
|
356
|
+
## Desk presets
|
|
357
|
+
|
|
358
|
+
`@n-uf/placement/desk` holds desk presets as data on `./panels`: each is panels options and a start state. It imports
|
|
359
|
+
only the panels entry, carries no titles or words and wires no toolbar; the app names the presets and draws them.
|
|
360
|
+
|
|
361
|
+
| Preset | Columns, bands and floats |
|
|
362
|
+
|---|---|
|
|
363
|
+
| `docks` | one stack column per side, sections at their natural heights when the defs give `height`, folding to the rail; a bottom band between the columns (reserved), folding to a bar on a short stage; no floats |
|
|
364
|
+
| `docksFull` | as `docks`, with the bottom band full width: the columns stand on it |
|
|
365
|
+
| `dockTear` | as `docks` (with its bottom band), and panels may float (tear-off and dock-back); one panel floats at the start |
|
|
366
|
+
| `navigator` | a tabbed column on the left, a stack column on the right; no band, no floats |
|
|
367
|
+
|
|
368
|
+
The bottom band starts with the hint's `bottom` panels (`start(defs, { bottom: [...] })`), else with the last def whose
|
|
369
|
+
`sides` names `"bottom"`; a def without `sides` may be dropped into the band but doesn't start there. `presetTargets`
|
|
370
|
+
and `presetDrop` include the band's targets.
|
|
371
|
+
|
|
372
|
+
```ts
|
|
373
|
+
import { PRESETS, presetLayout, presetTargets } from "@n-uf/placement/desk";
|
|
374
|
+
import type { PanelDef } from "@n-uf/placement/panels";
|
|
375
|
+
|
|
376
|
+
const defs: PanelDef[] = [
|
|
377
|
+
{ id: "files", width: { min: 200, natural: 240, max: 360 }, height: { min: 80, natural: 160 } },
|
|
378
|
+
{ id: "outline", width: { min: 200, natural: 240, max: 360 }, height: { min: 80, natural: 200 } },
|
|
379
|
+
{ id: "history", width: { min: 200, natural: 240, max: 360 } },
|
|
380
|
+
];
|
|
381
|
+
const nav = PRESETS.navigator;
|
|
382
|
+
const state = nav.start(defs, { left: ["files", "outline"] });
|
|
383
|
+
const layout = presetLayout(nav, defs, state, { width: 1200, height: 600 });
|
|
384
|
+
console.log(layout.columns[0]!.strip, layout.items.get("outline")!.hidden); // { x: 0, y: 0, width: 240, height: 28 } true
|
|
385
|
+
const targets = presetTargets(nav, { defs, state, id: "history", stage: { width: 1200, height: 600 } });
|
|
386
|
+
console.log(targets.some((t) => t.id === "float")); // false
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
`presetLayout(preset, defs, state, stage, options?)` is `layoutPanels` with the preset's options under the caller's;
|
|
390
|
+
`presetTargets(preset, input)` and `presetDrop(preset, input, target, point, grab)` are `panelTargets` and `panelDrop`
|
|
391
|
+
the same way, offering only the places the preset allows (`presetInput` gives that input). `./dock` stays as it is for
|
|
392
|
+
now.
|
|
257
393
|
|
|
258
394
|
## Pane zones
|
|
259
395
|
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import {
|
|
2
|
+
EDGES,
|
|
3
|
+
SIDES,
|
|
4
|
+
bandSize,
|
|
5
|
+
defOf,
|
|
6
|
+
floatSize
|
|
7
|
+
} from "./chunk-PJD5HKYX.js";
|
|
8
|
+
|
|
9
|
+
// src/panels/store.ts
|
|
10
|
+
function storePanels(state) {
|
|
11
|
+
const column = (c) => ({
|
|
12
|
+
panels: [...c.panels],
|
|
13
|
+
width: c.width,
|
|
14
|
+
...c.show === "tabs" ? { show: "tabs" } : {},
|
|
15
|
+
...c.active !== void 0 ? { active: c.active } : {}
|
|
16
|
+
});
|
|
17
|
+
const sides = Object.fromEntries(SIDES.map((s) => [s, state.sides[s].map(column)]));
|
|
18
|
+
const bands = {};
|
|
19
|
+
for (const e of EDGES) {
|
|
20
|
+
const b = state.bands?.[e];
|
|
21
|
+
if (b) bands[e] = { panels: [...b.panels], height: b.height };
|
|
22
|
+
}
|
|
23
|
+
return {
|
|
24
|
+
v: 1,
|
|
25
|
+
sides,
|
|
26
|
+
...EDGES.some((e) => bands[e]) ? { bands } : {},
|
|
27
|
+
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 })),
|
|
28
|
+
folded: [...state.folded],
|
|
29
|
+
kept: [...state.kept],
|
|
30
|
+
closed: [...state.closed],
|
|
31
|
+
clock: Object.fromEntries(Object.entries(state.clock).map(([k, c]) => [k, { opened: c.opened, used: c.used }]))
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
var isObject = (x) => typeof x === "object" && x !== null && !Array.isArray(x);
|
|
35
|
+
var finite = (x) => typeof x === "number" && Number.isFinite(x);
|
|
36
|
+
function readPanels(data, defs) {
|
|
37
|
+
try {
|
|
38
|
+
return read(data, defs);
|
|
39
|
+
} catch (e) {
|
|
40
|
+
return { ok: false, error: `unreadable: ${e instanceof Error ? e.message : typeof e}` };
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
function read(data, defs) {
|
|
44
|
+
if (!isObject(data)) return { ok: false, error: "not an object" };
|
|
45
|
+
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)` };
|
|
46
|
+
if (!isObject(data.sides)) return { ok: false, error: "sides is missing" };
|
|
47
|
+
const dropped = [];
|
|
48
|
+
const drop = (what) => {
|
|
49
|
+
if (!dropped.includes(what)) dropped.push(what);
|
|
50
|
+
};
|
|
51
|
+
const seen = /* @__PURE__ */ new Set();
|
|
52
|
+
const take = (x) => {
|
|
53
|
+
if (typeof x !== "string") {
|
|
54
|
+
drop(`a ${typeof x} where an id goes`);
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
if (defs && !defOf(defs, x) || seen.has(x)) {
|
|
58
|
+
drop(x);
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
seen.add(x);
|
|
62
|
+
return x;
|
|
63
|
+
};
|
|
64
|
+
const extra = (o, known, prefix) => {
|
|
65
|
+
for (const k of Object.keys(o)) if (!known.includes(k)) drop(`${prefix}${k}`);
|
|
66
|
+
};
|
|
67
|
+
extra(data, ["v", "sides", "bands", "floats", "folded", "kept", "closed", "clock"], "");
|
|
68
|
+
extra(data.sides, SIDES, "sides.");
|
|
69
|
+
const sides = { left: [], right: [] };
|
|
70
|
+
for (const side of SIDES) {
|
|
71
|
+
const cols = data.sides[side];
|
|
72
|
+
if (cols === void 0) continue;
|
|
73
|
+
if (!Array.isArray(cols)) {
|
|
74
|
+
drop(`sides.${side}`);
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
for (const c of cols) {
|
|
78
|
+
if (!isObject(c) || !Array.isArray(c.panels)) {
|
|
79
|
+
drop(`a column on the ${side}`);
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
extra(c, ["panels", "width", "show", "active"], "column.");
|
|
83
|
+
const panels = c.panels.map(take).filter((x) => x !== null);
|
|
84
|
+
if (panels.length === 0) continue;
|
|
85
|
+
const ds = defs ? panels.map((id) => defOf(defs, id)) : [];
|
|
86
|
+
const lo = Math.max(0, ...ds.map((d) => d.width.min));
|
|
87
|
+
const hi = Math.max(lo, Math.min(...ds.map((d) => d.width.max)));
|
|
88
|
+
const natural = ds.length ? Math.max(...ds.map((d) => d.width.natural)) : 0;
|
|
89
|
+
const width = finite(c.width) ? c.width : natural;
|
|
90
|
+
if (c.show !== void 0 && c.show !== "tabs" && c.show !== "stack") drop("column.show");
|
|
91
|
+
if (c.active !== void 0 && !(typeof c.active === "string" && panels.includes(c.active))) drop(`column.active:${typeof c.active === "string" ? c.active : typeof c.active}`);
|
|
92
|
+
const tabs = c.show === "tabs" ? { show: "tabs" } : {};
|
|
93
|
+
const active = typeof c.active === "string" && panels.includes(c.active) ? { active: c.active } : {};
|
|
94
|
+
sides[side].push({ panels, width: defs ? Math.min(Math.max(width, lo), hi) : Math.max(0, width), ...tabs, ...active });
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
const bands = {};
|
|
98
|
+
if (data.bands !== void 0) {
|
|
99
|
+
if (!isObject(data.bands)) drop("bands");
|
|
100
|
+
else {
|
|
101
|
+
extra(data.bands, EDGES, "bands.");
|
|
102
|
+
for (const e of EDGES) {
|
|
103
|
+
const b = data.bands[e];
|
|
104
|
+
if (b === void 0) continue;
|
|
105
|
+
if (!isObject(b) || !Array.isArray(b.panels) || !finite(b.height)) {
|
|
106
|
+
drop(`bands.${e}`);
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
extra(b, ["panels", "height"], "band.");
|
|
110
|
+
const panels = b.panels.map(take).filter((x) => x !== null);
|
|
111
|
+
if (panels.length === 0) {
|
|
112
|
+
drop(`bands.${e}`);
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
const ds = defs ? panels.map((id) => bandSize(defOf(defs, id))) : [];
|
|
116
|
+
const lo = Math.max(0, ...ds.map((d) => d.min));
|
|
117
|
+
const hi = Math.max(lo, Math.min(...ds.map((d) => d.max)));
|
|
118
|
+
bands[e] = { panels, height: defs ? Math.min(Math.max(b.height, lo), hi) : Math.max(0, b.height) };
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
const floats = [];
|
|
123
|
+
for (const f of Array.isArray(data.floats) ? data.floats : []) {
|
|
124
|
+
const r = isObject(f) ? f.rect : void 0;
|
|
125
|
+
if (!isObject(f) || !isObject(r) || !finite(r.x) || !finite(r.y) || !finite(r.width) || !finite(r.height)) {
|
|
126
|
+
drop(isObject(f) && typeof f.id === "string" ? f.id : "a float");
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
extra(f, ["id", "rect", "pinned"], "float.");
|
|
130
|
+
const id = take(f.id);
|
|
131
|
+
if (id === null) continue;
|
|
132
|
+
const min = defs ? floatSize(defOf(defs, id)).min : { width: 0, height: 0 };
|
|
133
|
+
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 } : {} });
|
|
134
|
+
}
|
|
135
|
+
if (data.floats !== void 0 && !Array.isArray(data.floats)) drop("floats");
|
|
136
|
+
const placed = (key) => {
|
|
137
|
+
const x = data[key];
|
|
138
|
+
if (x === void 0) return [];
|
|
139
|
+
if (!Array.isArray(x)) {
|
|
140
|
+
drop(key);
|
|
141
|
+
return [];
|
|
142
|
+
}
|
|
143
|
+
const out = [];
|
|
144
|
+
for (const id of x) {
|
|
145
|
+
if (typeof id === "string" && seen.has(id)) {
|
|
146
|
+
if (!out.includes(id)) out.push(id);
|
|
147
|
+
} else drop(typeof id === "string" ? id : `a ${typeof id} in ${key}`);
|
|
148
|
+
}
|
|
149
|
+
return out;
|
|
150
|
+
};
|
|
151
|
+
const floating = new Set(floats.map((f) => f.id));
|
|
152
|
+
const kept = placed("kept").filter((id) => {
|
|
153
|
+
if (floating.has(id)) drop(id);
|
|
154
|
+
return !floating.has(id);
|
|
155
|
+
});
|
|
156
|
+
const clock = {};
|
|
157
|
+
if (isObject(data.clock)) {
|
|
158
|
+
for (const id of Object.keys(data.clock)) if (!seen.has(id)) drop(`clock.${id}`);
|
|
159
|
+
for (const id of seen) {
|
|
160
|
+
const c = data.clock[id];
|
|
161
|
+
clock[id] = isObject(c) && finite(c.opened) && finite(c.used) ? { opened: c.opened, used: c.used } : { opened: 0, used: 0 };
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
const state = { sides, floats, folded: placed("folded"), kept, closed: placed("closed"), clock };
|
|
165
|
+
return { ok: true, state: EDGES.some((e) => bands[e]) ? { ...state, bands } : state, dropped };
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
export {
|
|
169
|
+
storePanels,
|
|
170
|
+
readPanels
|
|
171
|
+
};
|
|
172
|
+
//# sourceMappingURL=chunk-7R5H2ABL.js.map
|
|
@@ -0,0 +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. A column's `show` (\"tabs\") and `active` are such optional fields: an unknown `show` is\n * dropped as `\"column.show\"`, an `active` that isn't one of the column's panels as `\"column.active:<id>\"`.\n *\n * `bands` (26.11.10) is such an optional field too: `{ top?, bottom? }`, each `{ panels, height }`. An unknown edge is\n * dropped as `\"bands.<key>\"`, a band that isn't an object with a panels list and a numeric height (or whose panels are\n * all dropped) as `\"bands.<edge>\"`, an unknown field in one as `\"band.<field>\"`. Heights are clamped to the defs.\n */\nimport type { Rect } from \"../geometry\";\nimport { EDGES, SIDES, bandSize, defOf, floatSize, type Band, type Clock, type Column, type Edge, type FloatAt, type PanelDef, type PanelsState, type Side } from \"./model\";\n\nexport interface StoredPanels {\n readonly v: 1;\n /** A column's `show` and `active` only when it is tabbed / has one (optional fields of v1). */\n readonly sides: Record<Side, { panels: string[]; width: number; show?: \"tabs\"; active?: string }[]>;\n /** The bands, only when the state has one (an optional field of v1). */\n readonly bands?: Partial<Record<Edge, { panels: string[]; height: 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 column = (c: Column): StoredPanels[\"sides\"][\"left\"][number] => ({\n panels: [...c.panels],\n width: c.width,\n ...(c.show === \"tabs\" ? { show: \"tabs\" as const } : {}),\n ...(c.active !== undefined ? { active: c.active } : {}),\n });\n const sides = Object.fromEntries(SIDES.map((s) => [s, state.sides[s].map(column)])) as StoredPanels[\"sides\"];\n const bands: NonNullable<StoredPanels[\"bands\"]> = {};\n for (const e of EDGES) {\n const b = state.bands?.[e];\n if (b) bands[e] = { panels: [...b.panels], height: b.height };\n }\n return {\n v: 1,\n sides,\n ...(EDGES.some((e) => bands[e]) ? { bands } : {}),\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\", \"bands\", \"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\", \"show\", \"active\"], \"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 // `show`: \"tabs\" or \"stack\" (a stack is the default, so not kept); `active`: a panel of this column.\n if (c.show !== undefined && c.show !== \"tabs\" && c.show !== \"stack\") drop(\"column.show\");\n if (c.active !== undefined && !(typeof c.active === \"string\" && panels.includes(c.active))) drop(`column.active:${typeof c.active === \"string\" ? c.active : typeof c.active}`);\n const tabs = c.show === \"tabs\" ? { show: \"tabs\" as const } : {};\n const active = typeof c.active === \"string\" && panels.includes(c.active) ? { active: c.active } : {};\n sides[side].push({ panels, width: defs ? Math.min(Math.max(width, lo), hi) : Math.max(0, width), ...tabs, ...active });\n }\n }\n const bands: Partial<Record<Edge, Band>> = {};\n if (data.bands !== undefined) {\n if (!isObject(data.bands)) drop(\"bands\");\n else {\n extra(data.bands, EDGES, \"bands.\");\n for (const e of EDGES) {\n const b = data.bands[e];\n if (b === undefined) continue;\n if (!isObject(b) || !Array.isArray(b.panels) || !finite(b.height)) {\n drop(`bands.${e}`);\n continue;\n }\n extra(b, [\"panels\", \"height\"], \"band.\");\n const panels = (b.panels as unknown[]).map(take).filter((x): x is string => x !== null);\n if (panels.length === 0) {\n drop(`bands.${e}`);\n continue;\n }\n const ds = defs ? 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 bands[e] = { panels, height: defs ? Math.min(Math.max(b.height, lo), hi) : Math.max(0, b.height) };\n }\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 const state: PanelsState = { sides, floats, folded: placed(\"folded\"), kept, closed: placed(\"closed\"), clock };\n return { ok: true, state: EDGES.some((e) => bands[e]) ? { ...state, bands } : state, dropped };\n}\n"],"mappings":";;;;;;;;;AAmCO,SAAS,YAAY,OAAkC;AAC5D,QAAM,SAAS,CAAC,OAAsD;AAAA,IACpE,QAAQ,CAAC,GAAG,EAAE,MAAM;AAAA,IACpB,OAAO,EAAE;AAAA,IACT,GAAI,EAAE,SAAS,SAAS,EAAE,MAAM,OAAgB,IAAI,CAAC;AAAA,IACrD,GAAI,EAAE,WAAW,SAAY,EAAE,QAAQ,EAAE,OAAO,IAAI,CAAC;AAAA,EACvD;AACA,QAAM,QAAQ,OAAO,YAAY,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,MAAM,MAAM,CAAC,EAAE,IAAI,MAAM,CAAC,CAAC,CAAC;AAClF,QAAM,QAA4C,CAAC;AACnD,aAAW,KAAK,OAAO;AACrB,UAAM,IAAI,MAAM,QAAQ,CAAC;AACzB,QAAI,EAAG,OAAM,CAAC,IAAI,EAAE,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,QAAQ,EAAE,OAAO;AAAA,EAC9D;AACA,SAAO;AAAA,IACL,GAAG;AAAA,IACH;AAAA,IACA,GAAI,MAAM,KAAK,CAAC,MAAM,MAAM,CAAC,CAAC,IAAI,EAAE,MAAM,IAAI,CAAC;AAAA,IAC/C,QAAQ,MAAM,OAAO,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,MAAM,EAAE,GAAG,EAAE,KAAK,GAAG,GAAG,EAAE,KAAK,GAAG,OAAO,EAAE,KAAK,OAAO,QAAQ,EAAE,KAAK,OAAO,GAAG,QAAQ,CAAC,CAAC,EAAE,OAAO,EAAE;AAAA,IAClJ,QAAQ,CAAC,GAAG,MAAM,MAAM;AAAA,IACxB,MAAM,CAAC,GAAG,MAAM,IAAI;AAAA,IACpB,QAAQ,CAAC,GAAG,MAAM,MAAM;AAAA,IACxB,OAAO,OAAO,YAAY,OAAO,QAAQ,MAAM,KAAK,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,EAAE,QAAQ,EAAE,QAAQ,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC;AAAA,EAChH;AACF;AAEA,IAAM,WAAW,CAAC,MAA6C,OAAO,MAAM,YAAY,MAAM,QAAQ,CAAC,MAAM,QAAQ,CAAC;AACtH,IAAM,SAAS,CAAC,MAA4B,OAAO,MAAM,YAAY,OAAO,SAAS,CAAC;AAE/E,SAAS,WAAW,MAAe,MAAwC;AAChF,MAAI;AACF,WAAO,KAAK,MAAM,IAAI;AAAA,EACxB,SAAS,GAAG;AAEV,WAAO,EAAE,IAAI,OAAO,OAAO,eAAe,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC,GAAG;AAAA,EACxF;AACF;AAEA,SAAS,KAAK,MAAe,MAAwC;AACnE,MAAI,CAAC,SAAS,IAAI,EAAG,QAAO,EAAE,IAAI,OAAO,OAAO,gBAAgB;AAEhE,MAAI,KAAK,MAAM,EAAG,QAAO,EAAE,IAAI,OAAO,OAAO,mBAAmB,OAAO,KAAK,MAAM,YAAY,OAAO,KAAK,MAAM,WAAW,OAAO,KAAK,CAAC,IAAI,OAAO,KAAK,CAAC,0BAA0B;AACnL,MAAI,CAAC,SAAS,KAAK,KAAK,EAAG,QAAO,EAAE,IAAI,OAAO,OAAO,mBAAmB;AACzE,QAAM,UAAoB,CAAC;AAC3B,QAAM,OAAO,CAAC,SAAuB;AACnC,QAAI,CAAC,QAAQ,SAAS,IAAI,EAAG,SAAQ,KAAK,IAAI;AAAA,EAChD;AACA,QAAM,OAAO,oBAAI,IAAY;AAE7B,QAAM,OAAO,CAAC,MAA8B;AAC1C,QAAI,OAAO,MAAM,UAAU;AACzB,WAAK,KAAK,OAAO,CAAC,mBAAmB;AACrC,aAAO;AAAA,IACT;AACA,QAAK,QAAQ,CAAC,MAAM,MAAM,CAAC,KAAM,KAAK,IAAI,CAAC,GAAG;AAC5C,WAAK,CAAC;AACN,aAAO;AAAA,IACT;AACA,SAAK,IAAI,CAAC;AACV,WAAO;AAAA,EACT;AAEA,QAAM,QAAQ,CAAC,GAA4B,OAA0B,WAAyB;AAC5F,eAAW,KAAK,OAAO,KAAK,CAAC,EAAG,KAAI,CAAC,MAAM,SAAS,CAAC,EAAG,MAAK,GAAG,MAAM,GAAG,CAAC,EAAE;AAAA,EAC9E;AACA,QAAM,MAAM,CAAC,KAAK,SAAS,SAAS,UAAU,UAAU,QAAQ,UAAU,OAAO,GAAG,EAAE;AACtF,QAAM,KAAK,OAAO,OAAO,QAAQ;AACjC,QAAM,QAAQ,EAAE,MAAM,CAAC,GAAe,OAAO,CAAC,EAAc;AAC5D,aAAW,QAAQ,OAAO;AACxB,UAAM,OAAO,KAAK,MAAM,IAAI;AAC5B,QAAI,SAAS,OAAW;AACxB,QAAI,CAAC,MAAM,QAAQ,IAAI,GAAG;AACxB,WAAK,SAAS,IAAI,EAAE;AACpB;AAAA,IACF;AACA,eAAW,KAAK,MAAmB;AACjC,UAAI,CAAC,SAAS,CAAC,KAAK,CAAC,MAAM,QAAQ,EAAE,MAAM,GAAG;AAC5C,aAAK,mBAAmB,IAAI,EAAE;AAC9B;AAAA,MACF;AACA,YAAM,GAAG,CAAC,UAAU,SAAS,QAAQ,QAAQ,GAAG,SAAS;AACzD,YAAM,SAAU,EAAE,OAAqB,IAAI,IAAI,EAAE,OAAO,CAAC,MAAmB,MAAM,IAAI;AACtF,UAAI,OAAO,WAAW,EAAG;AACzB,YAAM,KAAK,OAAO,OAAO,IAAI,CAAC,OAAO,MAAM,MAAM,EAAE,CAAE,IAAI,CAAC;AAC1D,YAAM,KAAK,KAAK,IAAI,GAAG,GAAG,GAAG,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,CAAC;AACpD,YAAM,KAAK,KAAK,IAAI,IAAI,KAAK,IAAI,GAAG,GAAG,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,CAAC,CAAC;AAC/D,YAAM,UAAU,GAAG,SAAS,KAAK,IAAI,GAAG,GAAG,IAAI,CAAC,MAAM,EAAE,MAAM,OAAO,CAAC,IAAI;AAC1E,YAAM,QAAQ,OAAO,EAAE,KAAK,IAAI,EAAE,QAAQ;AAE1C,UAAI,EAAE,SAAS,UAAa,EAAE,SAAS,UAAU,EAAE,SAAS,QAAS,MAAK,aAAa;AACvF,UAAI,EAAE,WAAW,UAAa,EAAE,OAAO,EAAE,WAAW,YAAY,OAAO,SAAS,EAAE,MAAM,GAAI,MAAK,iBAAiB,OAAO,EAAE,WAAW,WAAW,EAAE,SAAS,OAAO,EAAE,MAAM,EAAE;AAC7K,YAAM,OAAO,EAAE,SAAS,SAAS,EAAE,MAAM,OAAgB,IAAI,CAAC;AAC9D,YAAM,SAAS,OAAO,EAAE,WAAW,YAAY,OAAO,SAAS,EAAE,MAAM,IAAI,EAAE,QAAQ,EAAE,OAAO,IAAI,CAAC;AACnG,YAAM,IAAI,EAAE,KAAK,EAAE,QAAQ,OAAO,OAAO,KAAK,IAAI,KAAK,IAAI,OAAO,EAAE,GAAG,EAAE,IAAI,KAAK,IAAI,GAAG,KAAK,GAAG,GAAG,MAAM,GAAG,OAAO,CAAC;AAAA,IACvH;AAAA,EACF;AACA,QAAM,QAAqC,CAAC;AAC5C,MAAI,KAAK,UAAU,QAAW;AAC5B,QAAI,CAAC,SAAS,KAAK,KAAK,EAAG,MAAK,OAAO;AAAA,SAClC;AACH,YAAM,KAAK,OAAO,OAAO,QAAQ;AACjC,iBAAW,KAAK,OAAO;AACrB,cAAM,IAAI,KAAK,MAAM,CAAC;AACtB,YAAI,MAAM,OAAW;AACrB,YAAI,CAAC,SAAS,CAAC,KAAK,CAAC,MAAM,QAAQ,EAAE,MAAM,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG;AACjE,eAAK,SAAS,CAAC,EAAE;AACjB;AAAA,QACF;AACA,cAAM,GAAG,CAAC,UAAU,QAAQ,GAAG,OAAO;AACtC,cAAM,SAAU,EAAE,OAAqB,IAAI,IAAI,EAAE,OAAO,CAAC,MAAmB,MAAM,IAAI;AACtF,YAAI,OAAO,WAAW,GAAG;AACvB,eAAK,SAAS,CAAC,EAAE;AACjB;AAAA,QACF;AACA,cAAM,KAAK,OAAO,OAAO,IAAI,CAAC,OAAO,SAAS,MAAM,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC;AACnE,cAAM,KAAK,KAAK,IAAI,GAAG,GAAG,GAAG,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC;AAC9C,cAAM,KAAK,KAAK,IAAI,IAAI,KAAK,IAAI,GAAG,GAAG,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AACzD,cAAM,CAAC,IAAI,EAAE,QAAQ,QAAQ,OAAO,KAAK,IAAI,KAAK,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,IAAI,KAAK,IAAI,GAAG,EAAE,MAAM,EAAE;AAAA,MACnG;AAAA,IACF;AAAA,EACF;AACA,QAAM,SAAoB,CAAC;AAC3B,aAAW,KAAK,MAAM,QAAQ,KAAK,MAAM,IAAK,KAAK,SAAuB,CAAC,GAAG;AAC5E,UAAM,IAAI,SAAS,CAAC,IAAI,EAAE,OAAO;AACjC,QAAI,CAAC,SAAS,CAAC,KAAK,CAAC,SAAS,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG;AACzG,WAAK,SAAS,CAAC,KAAK,OAAO,EAAE,OAAO,WAAW,EAAE,KAAK,SAAS;AAC/D;AAAA,IACF;AACA,UAAM,GAAG,CAAC,MAAM,QAAQ,QAAQ,GAAG,QAAQ;AAC3C,UAAM,KAAK,KAAK,EAAE,EAAE;AACpB,QAAI,OAAO,KAAM;AACjB,UAAM,MAAM,OAAO,UAAU,MAAM,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,OAAO,GAAG,QAAQ,EAAE;AAC1E,WAAO,KAAK,EAAE,IAAI,MAAM,EAAE,GAAG,EAAE,GAAG,GAAG,EAAE,GAAG,OAAO,KAAK,IAAI,IAAI,OAAO,EAAE,KAAK,GAAG,QAAQ,KAAK,IAAI,IAAI,QAAQ,EAAE,MAAM,EAAE,GAAG,GAAI,EAAE,WAAW,OAAO,EAAE,QAAQ,KAAK,IAAI,CAAC,EAAG,CAAC;AAAA,EAC3K;AACA,MAAI,KAAK,WAAW,UAAa,CAAC,MAAM,QAAQ,KAAK,MAAM,EAAG,MAAK,QAAQ;AAE3E,QAAM,SAAS,CAAC,QAAgD;AAC9D,UAAM,IAAI,KAAK,GAAG;AAClB,QAAI,MAAM,OAAW,QAAO,CAAC;AAC7B,QAAI,CAAC,MAAM,QAAQ,CAAC,GAAG;AACrB,WAAK,GAAG;AACR,aAAO,CAAC;AAAA,IACV;AACA,UAAM,MAAgB,CAAC;AACvB,eAAW,MAAM,GAAgB;AAC/B,UAAI,OAAO,OAAO,YAAY,KAAK,IAAI,EAAE,GAAG;AAC1C,YAAI,CAAC,IAAI,SAAS,EAAE,EAAG,KAAI,KAAK,EAAE;AAAA,MACpC,MAAO,MAAK,OAAO,OAAO,WAAW,KAAK,KAAK,OAAO,EAAE,OAAO,GAAG,EAAE;AAAA,IACtE;AACA,WAAO;AAAA,EACT;AACA,QAAM,WAAW,IAAI,IAAI,OAAO,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;AAEhD,QAAM,OAAO,OAAO,MAAM,EAAE,OAAO,CAAC,OAAO;AACzC,QAAI,SAAS,IAAI,EAAE,EAAG,MAAK,EAAE;AAC7B,WAAO,CAAC,SAAS,IAAI,EAAE;AAAA,EACzB,CAAC;AACD,QAAM,QAA+B,CAAC;AACtC,MAAI,SAAS,KAAK,KAAK,GAAG;AACxB,eAAW,MAAM,OAAO,KAAK,KAAK,KAAK,EAAG,KAAI,CAAC,KAAK,IAAI,EAAE,EAAG,MAAK,SAAS,EAAE,EAAE;AAC/E,eAAW,MAAM,MAAM;AACrB,YAAM,IAAI,KAAK,MAAM,EAAE;AACvB,YAAM,EAAE,IAAI,SAAS,CAAC,KAAK,OAAO,EAAE,MAAM,KAAK,OAAO,EAAE,IAAI,IAAI,EAAE,QAAQ,EAAE,QAAQ,MAAM,EAAE,KAAK,IAAI,EAAE,QAAQ,GAAG,MAAM,EAAE;AAAA,IAC5H;AAAA,EACF;AACA,QAAM,QAAqB,EAAE,OAAO,QAAQ,QAAQ,OAAO,QAAQ,GAAG,MAAM,QAAQ,OAAO,QAAQ,GAAG,MAAM;AAC5G,SAAO,EAAE,IAAI,MAAM,OAAO,MAAM,KAAK,CAAC,MAAM,MAAM,CAAC,CAAC,IAAI,EAAE,GAAG,OAAO,MAAM,IAAI,OAAO,QAAQ;AAC/F;","names":[]}
|