@embedpdf/core-ui 3.0.0-next.14 → 3.0.0-next.16
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/index.cjs +1317 -250
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +654 -133
- package/dist/index.d.ts +654 -133
- package/dist/index.js +1273 -245
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -1,19 +1,21 @@
|
|
|
1
1
|
//#region src/schema.d.ts
|
|
2
2
|
/**
|
|
3
|
-
* @embedpdf/core-ui — the structure-only
|
|
3
|
+
* @embedpdf/core-ui — the structure-only bar vocabulary.
|
|
4
4
|
*
|
|
5
|
-
*
|
|
5
|
+
* A bar contains only what a designer decides and the runtime cannot
|
|
6
6
|
* compute: order, grouping, importance, and each item's degradation ladder.
|
|
7
|
-
* Everything the runtime
|
|
7
|
+
* Everything the runtime can compute is banned from it by construction:
|
|
8
8
|
* no breakpoints, no show/hide lists, no locale overrides, no dividers, no
|
|
9
9
|
* spacers, no hand-written overflow menus. Fit is measured and solved at
|
|
10
10
|
* runtime (see solver.ts); the overflow menu is derived (see projection.ts).
|
|
11
|
+
* Where bars go, and the menus and panels around them, is the viewer's
|
|
12
|
+
* layout (see layout.ts).
|
|
11
13
|
*/
|
|
12
14
|
/** Presentation ladder for a command button, richest first. */
|
|
13
15
|
type Variant = 'icon+label' | 'icon' | 'label';
|
|
14
16
|
/**
|
|
15
17
|
* Who yields space first. 1 = first to degrade/overflow · 3 = default ·
|
|
16
|
-
* 5 = pinned: may still degrade variants, but
|
|
18
|
+
* 5 = pinned: may still degrade variants, but never leaves the bar.
|
|
17
19
|
*/
|
|
18
20
|
type Importance = 1 | 2 | 3 | 4 | 5;
|
|
19
21
|
declare const PINNED: Importance;
|
|
@@ -26,16 +28,17 @@ interface BarItem {
|
|
|
26
28
|
}
|
|
27
29
|
/**
|
|
28
30
|
* An app-rendered slot (e.g. the inline zoom strip). Each named variant is
|
|
29
|
-
* measured like any command button.
|
|
30
|
-
*
|
|
31
|
-
* is
|
|
31
|
+
* measured like any command button. Its `terminal` command is its menu form,
|
|
32
|
+
* what it becomes when it overflows; an item without one never leaves the bar
|
|
33
|
+
* (it is pinned, and so is its group), which keeps the overflow projection
|
|
34
|
+
* total.
|
|
32
35
|
*/
|
|
33
36
|
interface CustomItem {
|
|
34
37
|
readonly slot: string;
|
|
35
38
|
/** Named presentation variants, richest first. Default: ['default']. */
|
|
36
39
|
readonly variants?: readonly string[];
|
|
37
40
|
/** The command that stands in for this slot in menus (its last resort). */
|
|
38
|
-
readonly terminal
|
|
41
|
+
readonly terminal?: string;
|
|
39
42
|
readonly importance?: Importance;
|
|
40
43
|
}
|
|
41
44
|
type BarChild = BarItem | CustomItem | string;
|
|
@@ -46,22 +49,27 @@ interface BarGroup {
|
|
|
46
49
|
/** Presentation hint: 'tabs' renders as a tab strip and projects as radio rows. */
|
|
47
50
|
readonly role?: 'buttons' | 'tabs';
|
|
48
51
|
/**
|
|
49
|
-
* Stage 1 of the
|
|
50
|
-
* children (rightmost first, at the
|
|
52
|
+
* Stage 1 of the group degradation ladder: under pressure, move trailing
|
|
53
|
+
* children (rightmost first, at the child's importance) into a derived
|
|
51
54
|
* group-local disclosure — a trigger rendered inside the group opening a
|
|
52
55
|
* menu of the hidden children. Never sheds the last visible child: below
|
|
53
|
-
* that floor the group `collapse`s (stage 2) or overflows whole.
|
|
54
|
-
*
|
|
56
|
+
* that floor the group `collapse`s (stage 2) or overflows whole. The
|
|
57
|
+
* disclosure is computed, never authored.
|
|
55
58
|
*/
|
|
56
59
|
readonly shed?: boolean;
|
|
57
60
|
/**
|
|
58
|
-
* Stage 2: what the
|
|
61
|
+
* Stage 2: what the whole group degrades to once its children have
|
|
59
62
|
* exhausted their ladders (and shedding, if enabled, has hit its floor): a
|
|
60
63
|
* single menu button or a select-style picker. Groups with neither `shed`
|
|
61
64
|
* nor `collapse` send children to the global overflow menu one by one.
|
|
62
65
|
*/
|
|
63
66
|
readonly collapse?: 'menu' | 'select';
|
|
64
67
|
readonly importance?: Importance;
|
|
68
|
+
/**
|
|
69
|
+
* Shows only while something that isn't dependent shows in the same bar, like undo and redo
|
|
70
|
+
* beside a mode's tools: a bar with only dependent groups left shows nothing.
|
|
71
|
+
*/
|
|
72
|
+
readonly dependent?: boolean;
|
|
65
73
|
readonly items: readonly BarChild[];
|
|
66
74
|
}
|
|
67
75
|
/**
|
|
@@ -69,11 +77,11 @@ interface BarGroup {
|
|
|
69
77
|
* within a section — never across sections, never from schema data.
|
|
70
78
|
*
|
|
71
79
|
* The names are direction-aware (RTL flips start/end) and `center` is a
|
|
72
|
-
*
|
|
80
|
+
* soft contract: "balance this segment in the space left over by start and
|
|
73
81
|
* end". With symmetric flanks that coincides with true centering; with a
|
|
74
82
|
* heavy flank the segment drifts rather than fights — segments never
|
|
75
|
-
* overlap, matching how every toolbar convention (including
|
|
76
|
-
*
|
|
83
|
+
* overlap, matching how every toolbar convention (including spacer-flanked
|
|
84
|
+
* tabs) treats its middle region. Strict geometric centering
|
|
77
85
|
* would be a solver concern (a tighter budget: 2×max(start,end)+center),
|
|
78
86
|
* deliberately not offered until a product needs it.
|
|
79
87
|
*/
|
|
@@ -86,57 +94,16 @@ interface BarSchema {
|
|
|
86
94
|
readonly id: string;
|
|
87
95
|
readonly sections: BarSections;
|
|
88
96
|
}
|
|
89
|
-
/** A
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* The shell FRAME — region arrangement and visibility. Regions are a FIXED
|
|
101
|
-
* vocabulary (each carries semantics the shell must own: the toolbar's
|
|
102
|
-
* measurement physics, the document gate, aria landmarks); what's YOURS is
|
|
103
|
-
* where they sit, whether they show, and — through the region slots — what
|
|
104
|
-
* fills them. Part of the chrome value because it is structure: owned, never
|
|
105
|
-
* merged. Free-form layout is deliberately not offered — wanting a different
|
|
106
|
-
* frame architecture is what headless is for.
|
|
107
|
-
*/
|
|
108
|
-
interface FrameSchema {
|
|
109
|
-
/** Where the main bar lives. Its mode band rides the CONTENT side (below a
|
|
110
|
-
* top bar, above a bottom bar). Default: 'top'. */
|
|
111
|
-
readonly toolbar?: 'top' | 'bottom';
|
|
112
|
-
/** Document tab strip: 'multiple' shows it only with >1 tab. A hidden
|
|
113
|
-
* region hides its SLOT too — visibility outranks slotted content.
|
|
114
|
-
* Default: 'always'. */
|
|
115
|
-
readonly tabs?: 'always' | 'multiple' | 'never';
|
|
116
|
-
/** The header row — a socket only: the chrome ships no header of its own,
|
|
117
|
-
* so it renders nothing until a `slot="header"` child fills it. `false`
|
|
118
|
-
* removes the socket, keeping a slotted header out. Default: true. */
|
|
119
|
-
readonly header?: boolean;
|
|
120
|
-
}
|
|
121
|
-
interface ChromeSchema {
|
|
122
|
-
/** Standalone bars (e.g. the main toolbar). */
|
|
123
|
-
readonly bars: Readonly<Record<string, BarSchema>>;
|
|
124
|
-
/** Secondary bars keyed by tool mode — WHICH one shows is derived from the
|
|
125
|
-
* interaction hub's active tool, never stored. */
|
|
126
|
-
readonly modeBars?: Readonly<Record<string, BarSchema>>;
|
|
127
|
-
/** Named dropdown menus referenced by commands' `menu:` targets. */
|
|
128
|
-
readonly menus?: Readonly<Record<string, MenuSchema>>;
|
|
129
|
-
/** Contextual strips (selection menus) — same BarSchema, same fit engine. */
|
|
130
|
-
readonly strips?: Readonly<Record<string, BarSchema>>;
|
|
131
|
-
/** Region arrangement & visibility. Omitted = the default frame. */
|
|
132
|
-
readonly frame?: FrameSchema;
|
|
133
|
-
}
|
|
134
|
-
declare function item(command: string, opts?: Omit<BarItem, 'command'>): BarItem;
|
|
135
|
-
declare function custom(slot: string, opts: Omit<CustomItem, 'slot'>): CustomItem;
|
|
136
|
-
declare function group(id: string, items: readonly BarChild[]): BarGroup;
|
|
137
|
-
declare function group(id: string, opts: Omit<BarGroup, 'id' | 'items'> & {
|
|
138
|
-
items?: readonly BarChild[];
|
|
139
|
-
}, items?: readonly BarChild[]): BarGroup;
|
|
97
|
+
/** A command button: `item('zoom:in', { variants: ['icon+label', 'icon'] })`. */
|
|
98
|
+
declare function item(command: string, options?: Omit<BarItem, 'command'>): BarItem;
|
|
99
|
+
/**
|
|
100
|
+
* An item you draw yourself, by its slot name, and the command it becomes in the "More" menu:
|
|
101
|
+
* `custom('page-number', 'page:go-to', { variants: ['full', 'compact'] })`. Without a command,
|
|
102
|
+
* the item never leaves the bar.
|
|
103
|
+
*/
|
|
104
|
+
declare function custom(slot: string, terminal?: string, options?: Omit<CustomItem, 'slot' | 'terminal'>): CustomItem;
|
|
105
|
+
/** A group of items, with a separator between groups: `group('zoom', ['zoom:out', 'zoom:in'])`. */
|
|
106
|
+
declare function group(id: string, items: readonly BarChild[], options?: Omit<BarGroup, 'id' | 'items'>): BarGroup;
|
|
140
107
|
type NormalizedUnit = {
|
|
141
108
|
readonly kind: 'command';
|
|
142
109
|
/** Unique within the bar: `${groupId}:${command}`. Measurement + assignment key. */
|
|
@@ -149,7 +116,11 @@ type NormalizedUnit = {
|
|
|
149
116
|
readonly key: string;
|
|
150
117
|
readonly slot: string;
|
|
151
118
|
readonly variants: readonly string[];
|
|
152
|
-
|
|
119
|
+
/**
|
|
120
|
+
* The command it becomes in menus, or null for an item without one, which
|
|
121
|
+
* {@link filterBar} keeps, pinned.
|
|
122
|
+
*/
|
|
123
|
+
readonly terminal: string | null;
|
|
153
124
|
readonly importance: Importance;
|
|
154
125
|
};
|
|
155
126
|
interface NormalizedGroup {
|
|
@@ -159,6 +130,8 @@ interface NormalizedGroup {
|
|
|
159
130
|
readonly shed: boolean;
|
|
160
131
|
readonly collapse?: 'menu' | 'select';
|
|
161
132
|
readonly importance: Importance;
|
|
133
|
+
/** See {@link BarGroup.dependent}; the rule is {@link hasVisibleUnits}. */
|
|
134
|
+
readonly dependent: boolean;
|
|
162
135
|
readonly units: readonly NormalizedUnit[];
|
|
163
136
|
}
|
|
164
137
|
interface NormalizedSection {
|
|
@@ -170,76 +143,396 @@ interface NormalizedBar {
|
|
|
170
143
|
readonly sections: readonly NormalizedSection[];
|
|
171
144
|
}
|
|
172
145
|
declare const DEFAULT_IMPORTANCE: Importance;
|
|
173
|
-
/**
|
|
146
|
+
/** Whether a unit is a custom item with no command to become in menus: it never leaves the bar. */
|
|
147
|
+
declare const isStandaloneUnit: (unit: NormalizedUnit) => boolean;
|
|
148
|
+
/** The command a unit runs: its own, or a custom item's `terminal`; null for a standalone item. */
|
|
149
|
+
declare const commandOfUnit: (unit: NormalizedUnit) => string | null;
|
|
150
|
+
/**
|
|
151
|
+
* Resolve shorthands + defaults; validate uniqueness. Solver/projection input.
|
|
152
|
+
* A group holding a custom item without a command is pinned with it: it never
|
|
153
|
+
* collapses or overflows whole, so the item stays in the bar.
|
|
154
|
+
*/
|
|
174
155
|
declare function normalizeBar(bar: BarSchema): NormalizedBar;
|
|
175
156
|
/**
|
|
176
157
|
* Drop units whose command is currently invisible (permissions, disabled
|
|
177
|
-
* categories, contextual visibility)
|
|
158
|
+
* categories, contextual visibility) before solving — an invisible unit must
|
|
178
159
|
* not consume budget or appear in the overflow. Groups that empty out vanish
|
|
179
|
-
* naturally in the solver's separator math and in the projection.
|
|
160
|
+
* naturally in the solver's separator math and in the projection. A custom
|
|
161
|
+
* item without a command has nothing to ask `keep` about, and stays. A bar
|
|
162
|
+
* that shows nothing ({@link hasVisibleUnits}) keeps no unit at all, so its
|
|
163
|
+
* dependent groups go too.
|
|
180
164
|
*/
|
|
181
165
|
declare function filterBar(bar: NormalizedBar, keep: (unit: NormalizedUnit) => boolean): NormalizedBar;
|
|
182
166
|
/**
|
|
183
|
-
*
|
|
184
|
-
*
|
|
185
|
-
*
|
|
167
|
+
* Whether the bar shows anything once `keep` (as for {@link filterBar}) has had its say: a unit
|
|
168
|
+
* left in a group that isn't dependent. Dependent groups show only beside one, so a bar with
|
|
169
|
+
* only dependent groups left shows nothing.
|
|
186
170
|
*/
|
|
187
|
-
declare function
|
|
188
|
-
/** Dev-time cross-check: every command referenced by the chrome exists. */
|
|
189
|
-
declare function validateChrome(chrome: ChromeSchema, knownCommands: ReadonlySet<string>): string[];
|
|
171
|
+
declare function hasVisibleUnits(bar: NormalizedBar, keep: (unit: NormalizedUnit) => boolean): boolean;
|
|
190
172
|
//#endregion
|
|
191
|
-
//#region src/
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
* Swap a command in place everywhere it appears — bars, mode bars, strips,
|
|
214
|
-
* and (when the replacement is itself a plain command) menu rows.
|
|
215
|
-
*/
|
|
216
|
-
declare function replaceItem(schema: ChromeSchema, id: string, item: BarChild): ChromeSchema;
|
|
217
|
-
//#endregion
|
|
218
|
-
//#region src/helpers.d.ts
|
|
219
|
-
declare const chromeHelpers: {
|
|
220
|
-
readonly addItem: typeof addItem;
|
|
221
|
-
readonly removeItems: typeof removeItems;
|
|
222
|
-
readonly replaceItem: typeof replaceItem;
|
|
223
|
-
readonly item: typeof item;
|
|
224
|
-
readonly group: typeof group;
|
|
225
|
-
readonly custom: typeof custom;
|
|
226
|
-
readonly defineChrome: typeof defineChrome;
|
|
173
|
+
//#region src/layout.d.ts
|
|
174
|
+
/** An edge of the viewer. `start` and `end` follow the language: left and right, swapped in a right-to-left one. */
|
|
175
|
+
type BarEdge = 'top' | 'bottom' | 'start' | 'end';
|
|
176
|
+
/** Where a floating bar sits over the pages. */
|
|
177
|
+
type FloatPosition = 'top-start' | 'top' | 'top-end' | 'start' | 'end' | 'bottom-start' | 'bottom' | 'bottom-end';
|
|
178
|
+
/** What a bar over a selection follows: selected text, or selected annotations. */
|
|
179
|
+
type SelectionTarget = 'selection' | 'annotation';
|
|
180
|
+
/**
|
|
181
|
+
* Where a bar goes: along an edge, floating over the pages, along another bar on the side of the
|
|
182
|
+
* pages, or over what's selected. Bars on one edge stack from the outside in, in the order they
|
|
183
|
+
* were added; `before` and `after` put a bar next to another bar on that edge.
|
|
184
|
+
*/
|
|
185
|
+
type BarPlace = BarEdge | {
|
|
186
|
+
readonly edge: BarEdge;
|
|
187
|
+
readonly before?: string;
|
|
188
|
+
readonly after?: string;
|
|
189
|
+
} | {
|
|
190
|
+
readonly float: FloatPosition;
|
|
191
|
+
} | {
|
|
192
|
+
readonly with: string;
|
|
193
|
+
} | {
|
|
194
|
+
readonly at: SelectionTarget;
|
|
227
195
|
};
|
|
228
|
-
|
|
196
|
+
/** A command with options. */
|
|
197
|
+
interface LayoutCommandItem {
|
|
198
|
+
readonly command: string;
|
|
199
|
+
/** How it may show, richest first. Default `['icon']`. */
|
|
200
|
+
readonly variants?: readonly Variant[];
|
|
201
|
+
/** Who makes room first: `1` to `5` (never leaves the bar). Default `3`. */
|
|
202
|
+
readonly importance?: Importance;
|
|
203
|
+
}
|
|
204
|
+
/** Your own component, by its id. `command` is what it becomes in the "More" menu; without one, it never leaves the bar. */
|
|
205
|
+
interface LayoutCustomItem {
|
|
206
|
+
readonly custom: string;
|
|
207
|
+
readonly command?: string;
|
|
208
|
+
/** Your component's forms, largest first. Default `['default']`. */
|
|
209
|
+
readonly variants?: readonly string[];
|
|
210
|
+
readonly importance?: Importance;
|
|
211
|
+
}
|
|
212
|
+
/** A command id, a command with options, or your own component. */
|
|
213
|
+
type LayoutItem = string | LayoutCommandItem | LayoutCustomItem;
|
|
214
|
+
/** A group that needs a name or options. */
|
|
215
|
+
interface LayoutGroupObject {
|
|
216
|
+
/** Its name, so `add(item, { group })` can find it. */
|
|
217
|
+
readonly id?: string;
|
|
218
|
+
readonly items: readonly LayoutItem[];
|
|
219
|
+
/** Fold into one button with a menu (`'menu'`) or a dropdown (`'select'`) when there's no room. */
|
|
220
|
+
readonly collapse?: 'menu' | 'select';
|
|
221
|
+
/** Move items behind a button inside the group before the group folds or leaves the bar. */
|
|
222
|
+
readonly shed?: boolean;
|
|
223
|
+
/** Who makes room first: `1` to `5`. Default `3`. */
|
|
224
|
+
readonly importance?: Importance;
|
|
225
|
+
/** Its title in the "More" menu, as a translation key. */
|
|
226
|
+
readonly titleKey?: string;
|
|
227
|
+
/**
|
|
228
|
+
* Show only while something in the bar that isn't dependent shows, like undo and redo beside a
|
|
229
|
+
* mode's tools. A bar with only dependent groups left is empty, and a mode's tab goes with it.
|
|
230
|
+
*/
|
|
231
|
+
readonly dependent?: boolean;
|
|
232
|
+
}
|
|
233
|
+
/** A group of items, with a line between groups: an array, or an object when it needs a name or options. */
|
|
234
|
+
type LayoutGroup = readonly LayoutItem[] | LayoutGroupObject;
|
|
235
|
+
/** A section of a bar: its groups in order. A lone item is a group of one. */
|
|
236
|
+
type LayoutSection = readonly (LayoutGroup | LayoutItem)[];
|
|
237
|
+
/** A bar's sections: `start` (left), `center` and `end` (right); `start` and `end` swap in a right-to-left language. */
|
|
238
|
+
type SectionName = 'start' | 'center' | 'end';
|
|
239
|
+
interface LayoutBar {
|
|
240
|
+
readonly place: BarPlace;
|
|
241
|
+
/** Shown in this mode only. The mode gets a tab, titled by the bar's title, and a `mode:<mode>` command. */
|
|
242
|
+
readonly mode?: string;
|
|
243
|
+
readonly title?: string;
|
|
244
|
+
/** The title as a translation key. */
|
|
245
|
+
readonly titleKey?: string;
|
|
246
|
+
readonly start?: LayoutSection;
|
|
247
|
+
readonly center?: LayoutSection;
|
|
248
|
+
readonly end?: LayoutSection;
|
|
249
|
+
}
|
|
250
|
+
/** A section of a menu: an array of command ids, or an object when it has a title. */
|
|
251
|
+
type LayoutMenuSection = readonly string[] | {
|
|
252
|
+
readonly title?: string;
|
|
253
|
+
/** The title as a translation key. */
|
|
254
|
+
readonly titleKey?: string;
|
|
255
|
+
readonly items: readonly string[];
|
|
256
|
+
};
|
|
257
|
+
/** A menu: its sections, with a line between them. */
|
|
258
|
+
type LayoutMenu = readonly LayoutMenuSection[];
|
|
259
|
+
/** How a panel opens: beside the pages, over them, or up from the bottom. */
|
|
260
|
+
type PanelPresentation = 'dock' | 'overlay' | 'sheet';
|
|
261
|
+
/** How a panel opens at each of the viewer's sizes. A size left out opens the default way. */
|
|
262
|
+
interface PanelPresentationBySize {
|
|
263
|
+
readonly compact?: PanelPresentation;
|
|
264
|
+
readonly medium?: PanelPresentation;
|
|
265
|
+
readonly expanded?: PanelPresentation;
|
|
266
|
+
}
|
|
267
|
+
/** A panel's width: the one it starts at, and the narrowest and widest it can be dragged to. */
|
|
268
|
+
interface PanelWidth {
|
|
269
|
+
/** In px. Default `288`. */
|
|
270
|
+
readonly initial?: number;
|
|
271
|
+
/** In px. Default `200`. */
|
|
272
|
+
readonly min?: number;
|
|
273
|
+
/** In px. Default `640`. A docked panel never takes more than half the viewer. */
|
|
274
|
+
readonly max?: number;
|
|
275
|
+
}
|
|
276
|
+
interface LayoutPanel {
|
|
277
|
+
/** Default `'end'`. */
|
|
278
|
+
readonly side?: 'start' | 'end';
|
|
279
|
+
readonly title?: string;
|
|
280
|
+
/** The title as a translation key. */
|
|
281
|
+
readonly titleKey?: string;
|
|
282
|
+
/** Its button's icon. */
|
|
283
|
+
readonly icon?: string;
|
|
284
|
+
/**
|
|
285
|
+
* How it opens: the same way at every size, or per size. Default
|
|
286
|
+
* `{ compact: 'sheet', medium: 'overlay', expanded: 'dock' }`.
|
|
287
|
+
*/
|
|
288
|
+
readonly present?: PanelPresentation | PanelPresentationBySize;
|
|
289
|
+
/** Its width in px (where it starts), or where it starts and how far it drags. Default `288`. */
|
|
290
|
+
readonly width?: number | PanelWidth;
|
|
291
|
+
/** Whether people can drag its edge to change its width. Default `true`. */
|
|
292
|
+
readonly resizable?: boolean;
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Changes to a panel: the fields to set. `present` and `width` change only what they name: a
|
|
296
|
+
* map of sizes keeps the other sizes, and a number or `{ initial }` keeps `min` and `max`.
|
|
297
|
+
*/
|
|
298
|
+
type LayoutPanelPatch = Partial<LayoutPanel>;
|
|
299
|
+
/** When the document tabs show: always, while more than one document is open, or never. */
|
|
300
|
+
type TabsVisibility = 'always' | 'multiple' | 'never';
|
|
301
|
+
/** A layout as plain data: bars, menus and panels, each by id. */
|
|
302
|
+
interface LayoutData {
|
|
303
|
+
readonly bars?: Readonly<Record<string, LayoutBar>>;
|
|
304
|
+
readonly menus?: Readonly<Record<string, LayoutMenu>>;
|
|
305
|
+
readonly panels?: Readonly<Record<string, LayoutPanel>>;
|
|
306
|
+
readonly tabs?: TabsVisibility;
|
|
307
|
+
}
|
|
308
|
+
/** Where {@link Layout.add} puts an item. */
|
|
309
|
+
interface AddItemOptions {
|
|
310
|
+
/** The bar or menu. A bar wins over a menu with the same id. */
|
|
311
|
+
readonly to: string;
|
|
312
|
+
/** The bar's section for a new group. Default `'end'`. */
|
|
313
|
+
readonly section?: SectionName;
|
|
314
|
+
/** The group to join, by id; a new id starts a new group at the end of the section. */
|
|
315
|
+
readonly group?: string;
|
|
316
|
+
/** An item to put it before, in that item's group. */
|
|
317
|
+
readonly before?: string;
|
|
318
|
+
/** An item to put it after, in that item's group. */
|
|
319
|
+
readonly after?: string;
|
|
320
|
+
}
|
|
321
|
+
/** Where {@link Layout.remove} takes items from. */
|
|
322
|
+
interface RemoveItemOptions {
|
|
323
|
+
/** The bar or menu: always one place. To leave something out everywhere, turn it off instead. */
|
|
324
|
+
readonly from: string;
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* A layout: its data and the edits. Every edit returns a new layout and leaves this one as it
|
|
328
|
+
* was; an edit that names an id the layout doesn't have changes nothing and records a warning.
|
|
329
|
+
*/
|
|
330
|
+
interface Layout {
|
|
331
|
+
/** Move a bar. */
|
|
332
|
+
place(bar: string, place: BarPlace): Layout;
|
|
333
|
+
/** Add a bar, or replace the bar with that id. */
|
|
334
|
+
addBar(id: string, bar: LayoutBar): Layout;
|
|
335
|
+
/** Remove a bar. Removing a mode's bar removes its tab. */
|
|
336
|
+
removeBar(id: string): Layout;
|
|
337
|
+
/** Put an item in a bar or a menu: at the end of a section, in a group, or next to an item. */
|
|
338
|
+
add(item: LayoutItem, options: AddItemOptions): Layout;
|
|
339
|
+
/** Take items out of one bar or menu; a group or section with nothing left goes with them. */
|
|
340
|
+
remove(ids: string | readonly string[], options: RemoveItemOptions): Layout;
|
|
341
|
+
/** Put another item in an item's place, in every bar and menu. */
|
|
342
|
+
replace(id: string, item: LayoutItem): Layout;
|
|
343
|
+
/** Add a menu, or replace the menu with that id. */
|
|
344
|
+
addMenu(id: string, sections: LayoutMenu): Layout;
|
|
345
|
+
/** Add a panel, or replace the panel with that id. */
|
|
346
|
+
addPanel(id: string, panel: LayoutPanel): Layout;
|
|
347
|
+
/** Change a panel's fields. */
|
|
348
|
+
panel(id: string, changes: LayoutPanelPatch): Layout;
|
|
349
|
+
/**
|
|
350
|
+
* Change every panel's fields, as `panel(id, changes)` changes one: every panel the layout has
|
|
351
|
+
* so far, so a panel added after it keeps its own.
|
|
352
|
+
*/
|
|
353
|
+
panels(changes: LayoutPanelPatch): Layout;
|
|
354
|
+
/** Remove a panel, and its `panel:<id>` button from every bar and menu. */
|
|
355
|
+
removePanel(id: string): Layout;
|
|
356
|
+
/** When the document tabs show. */
|
|
357
|
+
tabs(visibility: TabsVisibility): Layout;
|
|
358
|
+
/** The layout as plain data. */
|
|
359
|
+
toJSON(): LayoutData;
|
|
360
|
+
}
|
|
361
|
+
/** A layout of `data`, which it never changes. */
|
|
362
|
+
declare function createLayout(data?: LayoutData): Layout;
|
|
363
|
+
/** Whether `value` is a layout made by {@link createLayout} or one of its edits. */
|
|
364
|
+
declare function isLayout(value: unknown): value is Layout;
|
|
365
|
+
/** What an item is called in edits: its command id, your component's id, or `''` for a non-item. */
|
|
366
|
+
declare function itemIdOf(item: LayoutItem): string;
|
|
367
|
+
/** The command an item runs or stands for in menus, or `null` for your component without one. */
|
|
368
|
+
declare function itemCommandOf(item: LayoutItem): string | null;
|
|
369
|
+
/** A panel's `present` as a map of sizes: one way at every size, or the sizes it names. */
|
|
370
|
+
declare const panelPresentationsOf: (present: PanelPresentation | PanelPresentationBySize) => PanelPresentationBySize;
|
|
371
|
+
/** A panel's `width` as its fields: a number is where it starts. */
|
|
372
|
+
declare const panelWidthFieldsOf: (width: number | PanelWidth) => PanelWidth;
|
|
373
|
+
/** The viewer's size class, from its own width. */
|
|
374
|
+
type ViewerSize = 'compact' | 'medium' | 'expanded';
|
|
375
|
+
/** What the layout function knows about the viewer, measured on the viewer itself. */
|
|
376
|
+
interface LayoutEnv {
|
|
377
|
+
/** `'compact'` under 600 px, `'medium'` to 1023 px, `'expanded'` from 1024 px. */
|
|
378
|
+
readonly size: ViewerSize;
|
|
379
|
+
/** The viewer's width, in px. */
|
|
380
|
+
readonly width: number;
|
|
381
|
+
/** Whether the main way of pointing is a finger. */
|
|
382
|
+
readonly touch: boolean;
|
|
383
|
+
/** How the user's language reads. */
|
|
384
|
+
readonly dir: 'ltr' | 'rtl';
|
|
385
|
+
}
|
|
386
|
+
/** The narrowest a medium viewer is, in px. */
|
|
387
|
+
declare const MEDIUM_MIN_WIDTH_PX = 600;
|
|
388
|
+
/** The narrowest an expanded viewer is, in px. */
|
|
389
|
+
declare const EXPANDED_MIN_WIDTH_PX = 1024;
|
|
390
|
+
/** The size class of a viewer this wide. */
|
|
391
|
+
declare function sizeOf(widthPx: number): ViewerSize;
|
|
392
|
+
/** Whether two envs are the same: the layout function runs again only when one of the fields changes. */
|
|
393
|
+
declare const sameLayoutEnv: (left: LayoutEnv, right: LayoutEnv) => boolean;
|
|
394
|
+
/** Gets the default layout and the viewer's env, and returns your layout. */
|
|
395
|
+
type LayoutFunction = (layout: Layout, env: LayoutEnv) => Layout | LayoutData;
|
|
396
|
+
/** What the `layout` config takes: a layout, plain layout data, or a function of the default. */
|
|
397
|
+
type LayoutOption = Layout | LayoutData | LayoutFunction;
|
|
398
|
+
/**
|
|
399
|
+
* The layout an option gives at this env: the default without one, the function's result, or
|
|
400
|
+
* the option itself. A function that throws or returns no layout gives the default, with a
|
|
401
|
+
* warning saying so.
|
|
402
|
+
*/
|
|
403
|
+
declare function resolveLayout(option: LayoutOption | null | undefined, defaults: Layout, env: LayoutEnv): Layout;
|
|
404
|
+
//#endregion
|
|
405
|
+
//#region src/layout-compile.d.ts
|
|
406
|
+
/** The id of the group that holds the mode tabs. */
|
|
407
|
+
declare const MODES_GROUP = "modes";
|
|
408
|
+
/** The command of the mode with no bar of its own: viewing. */
|
|
409
|
+
declare const VIEW_MODE_COMMAND = "mode:view";
|
|
410
|
+
/** The command that opens a mode, and its tab. */
|
|
411
|
+
declare const modeCommandOf: (mode: string) => string;
|
|
412
|
+
/** The command that opens and closes a panel, and its button. */
|
|
413
|
+
declare const panelCommandOf: (panel: string) => string;
|
|
414
|
+
/** Every place a bar can float over the pages: each corner, and the middle of each side. */
|
|
415
|
+
declare const FLOAT_POSITIONS: readonly FloatPosition[];
|
|
416
|
+
/** The edge a place is on, or `null` for a place that isn't an edge. */
|
|
417
|
+
declare function edgeOf(place: BarPlace | undefined): BarEdge | null;
|
|
418
|
+
/** The bar a place rides along, or `null`. */
|
|
419
|
+
declare function hostOf(place: BarPlace | undefined): string | null;
|
|
420
|
+
/** What a place follows when it is over a selection, or `null`. */
|
|
421
|
+
declare function selectionOf(place: BarPlace | undefined): SelectionTarget | null;
|
|
422
|
+
/** Where a place floats over the pages, or `null` for a place that doesn't float. */
|
|
423
|
+
declare function floatOf(place: BarPlace | undefined): FloatPosition | null;
|
|
424
|
+
/**
|
|
425
|
+
* The bars along an edge, from the outside in: in the order they were added, then each bar
|
|
426
|
+
* with `before` or `after` put next to the bar it names. A bar that names a bar not on this
|
|
427
|
+
* edge goes innermost.
|
|
428
|
+
*/
|
|
429
|
+
declare function barsOnEdge(data: LayoutData, edge: BarEdge): string[];
|
|
430
|
+
/** The bars that ride along `host`, in the order they were added, nearest first. */
|
|
431
|
+
declare function barsWith(data: LayoutData, host: string): string[];
|
|
432
|
+
/**
|
|
433
|
+
* Every bar drawn along an edge, from the outside in: each bar on the edge, followed by the bars
|
|
434
|
+
* that ride along it (nearest first) and the bars that ride along those.
|
|
435
|
+
*/
|
|
436
|
+
declare function edgeStackOf(data: LayoutData, edge: BarEdge): string[];
|
|
437
|
+
/** The bars floating at `position`, in the order they were added. */
|
|
438
|
+
declare function barsFloating(data: LayoutData, position: FloatPosition): string[];
|
|
439
|
+
/**
|
|
440
|
+
* Every bar drawn floating at `position`, from the viewer's edge in: each bar floating there,
|
|
441
|
+
* followed by the bars that ride along it, as {@link edgeStackOf} orders an edge.
|
|
442
|
+
*/
|
|
443
|
+
declare function floatStackOf(data: LayoutData, position: FloatPosition): string[];
|
|
444
|
+
/** The bars over a selection of this kind, in the order they were added. */
|
|
445
|
+
declare function barsAt(data: LayoutData, target: SelectionTarget): string[];
|
|
446
|
+
/** Every mode of the layout's bars, once each, in bar order. */
|
|
447
|
+
declare function modesOf(data: LayoutData): string[];
|
|
448
|
+
/** The bars shown in a mode, in bar order. */
|
|
449
|
+
declare function barsInMode(data: LayoutData, mode: string): string[];
|
|
450
|
+
/** What {@link compileBar} leaves out. */
|
|
451
|
+
interface CompileBarOptions {
|
|
452
|
+
/**
|
|
453
|
+
* Command ids to leave out, as if the bar didn't name them: a mode tab whose bars show nothing,
|
|
454
|
+
* a button whose menu is empty. With every mode tab left out, View goes too.
|
|
455
|
+
*/
|
|
456
|
+
readonly omit?: ReadonlySet<string>;
|
|
457
|
+
}
|
|
458
|
+
/**
|
|
459
|
+
* A bar as the toolbar fits it, or `null` for a bar the layout doesn't have. Groups written as
|
|
460
|
+
* arrays and lone items get ids of their own (`start-0`, …); an item twice in one group shows
|
|
461
|
+
* once; a group with nothing left goes.
|
|
462
|
+
*/
|
|
463
|
+
declare function compileBar(data: LayoutData, id: string, options?: CompileBarOptions): BarSchema | null;
|
|
464
|
+
/** When the document tabs show: as the layout says, else while more than one document is open. */
|
|
465
|
+
declare function tabsOf(data: LayoutData): TabsVisibility;
|
|
466
|
+
/** A menu section, read: its title and its command ids. */
|
|
467
|
+
interface MenuSection {
|
|
468
|
+
readonly title?: string;
|
|
469
|
+
readonly titleKey?: string;
|
|
470
|
+
readonly items: readonly string[];
|
|
471
|
+
}
|
|
472
|
+
/** A menu's sections, or `null` for a menu the layout doesn't have. An empty section goes. */
|
|
473
|
+
declare function menuOf(data: LayoutData, id: string): readonly MenuSection[] | null;
|
|
474
|
+
/** What {@link omittedCommandsOf} reads of a command; plugin-commands' `ResolvedCommand` satisfies it. */
|
|
475
|
+
interface OmissionCommand {
|
|
476
|
+
readonly visible: boolean;
|
|
477
|
+
readonly menu?: string;
|
|
478
|
+
}
|
|
479
|
+
/**
|
|
480
|
+
* The commands the bars leave out because what they lead to shows nothing: the tab of a mode
|
|
481
|
+
* whose bars have nothing visible ({@link hasVisibleUnits}: dependent groups alone don't count),
|
|
482
|
+
* and a button whose menu has nothing visible (or that the layout has no menu for). Sorted, so
|
|
483
|
+
* two equal results compare equal; pass it to {@link compileBar} as `omit`. Cheap to call on every change: what it reads of the layout is
|
|
484
|
+
* read once per layout data.
|
|
485
|
+
*/
|
|
486
|
+
declare function omittedCommandsOf(data: LayoutData, resolve: (id: string) => OmissionCommand | null): string[];
|
|
487
|
+
//#endregion
|
|
488
|
+
//#region src/layout-validate.d.ts
|
|
489
|
+
/** What the viewer has, to check a layout's ids against. */
|
|
490
|
+
interface LayoutKnownIds {
|
|
491
|
+
/**
|
|
492
|
+
* Every command id the viewer has. The ones the layout makes itself need not be listed: the
|
|
493
|
+
* mode tabs (`mode:view`, `mode:<mode>`) and the panel buttons (`panel:<id>`).
|
|
494
|
+
*/
|
|
495
|
+
readonly commands: Iterable<string>;
|
|
496
|
+
/** Whether a command id exists that `commands` can't list, such as one of a family's. */
|
|
497
|
+
readonly hasCommand?: (id: string) => boolean;
|
|
498
|
+
}
|
|
499
|
+
/**
|
|
500
|
+
* Every problem with a layout, as sentences: what its edits couldn't do first, then what its
|
|
501
|
+
* data names that the viewer doesn't have. Empty when there is none.
|
|
502
|
+
*/
|
|
503
|
+
declare function validateLayout(layout: Layout | LayoutData, known: LayoutKnownIds): string[];
|
|
504
|
+
//#endregion
|
|
505
|
+
//#region src/suggestions.d.ts
|
|
506
|
+
/**
|
|
507
|
+
* "Did you mean …?" for ids: the closest known id to one that doesn't exist,
|
|
508
|
+
* by edit distance, when it is close enough to be a typo.
|
|
509
|
+
*/
|
|
510
|
+
/**
|
|
511
|
+
* The number of single-character inserts, deletes, substitutions and swaps of two neighbours
|
|
512
|
+
* that turn `left` into `right`.
|
|
513
|
+
*/
|
|
514
|
+
declare function editDistance(left: string, right: string): number;
|
|
515
|
+
/**
|
|
516
|
+
* The candidate closest to `id`, or `null` when none is within a typo's reach: at most a third
|
|
517
|
+
* of the id's length, and never more than 3 edits apart.
|
|
518
|
+
*/
|
|
519
|
+
declare function closestMatch(id: string, candidates: Iterable<string>): string | null;
|
|
520
|
+
/** `' (did you mean "x"?)'` for the closest candidate, or `''` when there is none. */
|
|
521
|
+
declare function didYouMean(id: string, candidates: Iterable<string>): string;
|
|
229
522
|
//#endregion
|
|
230
523
|
//#region src/solver.d.ts
|
|
231
524
|
interface FitMetrics {
|
|
232
|
-
/**
|
|
525
|
+
/** Length of unit `key` rendered at `variant`; undefined = not yet measured. */
|
|
233
526
|
unit(key: string, variant: string): number | undefined;
|
|
234
|
-
/**
|
|
527
|
+
/** Length of group `id` rendered in its collapsed form ('menu' | 'select'). */
|
|
235
528
|
groupCollapsed(groupId: string): number | undefined;
|
|
236
|
-
/**
|
|
529
|
+
/** Length of group `id`'s disclosure trigger (shed groups only). */
|
|
237
530
|
groupTrigger(groupId: string): number | undefined;
|
|
238
|
-
/**
|
|
531
|
+
/** Length of the overflow trigger button. */
|
|
239
532
|
readonly overflowTrigger: number;
|
|
240
533
|
/** Gap between adjacent visible units. */
|
|
241
534
|
readonly gap: number;
|
|
242
|
-
/**
|
|
535
|
+
/** Length of a derived separator between adjacent visible groups (with its gaps). */
|
|
243
536
|
readonly separator: number;
|
|
244
537
|
}
|
|
245
538
|
type UnitAssignment = {
|
|
@@ -264,12 +557,13 @@ interface FitResult {
|
|
|
264
557
|
readonly units: ReadonlyMap<string, UnitAssignment>;
|
|
265
558
|
readonly groups: ReadonlyMap<string, GroupAssignment>;
|
|
266
559
|
readonly hasOverflow: boolean;
|
|
267
|
-
/** Total visible
|
|
268
|
-
readonly
|
|
560
|
+
/** Total visible length at this assignment (diagnostics + tests). */
|
|
561
|
+
readonly length: number;
|
|
269
562
|
/** False when any consulted measurement was missing (treated as 0). */
|
|
270
563
|
readonly complete: boolean;
|
|
271
564
|
}
|
|
272
|
-
|
|
565
|
+
/** Fit `bar` into `containerLength`, the room along its axis. */
|
|
566
|
+
declare function solve(bar: NormalizedBar, metrics: FitMetrics, containerLength: number): FitResult;
|
|
273
567
|
//#endregion
|
|
274
568
|
//#region src/projection.d.ts
|
|
275
569
|
type OverflowRow =
|
|
@@ -302,8 +596,7 @@ type ResolveMenuTarget = (commandId: string) => {
|
|
|
302
596
|
declare function projectOverflow(bar: NormalizedBar, fit: FitResult, resolve: ResolveMenuTarget): OverflowSection[];
|
|
303
597
|
/**
|
|
304
598
|
* The content of a group's disclosure trigger: its shed units, in bar order,
|
|
305
|
-
* in menu form — same totality rules as the global overflow.
|
|
306
|
-
* hand-written `mode-tabs-overflow-menu`, derived.
|
|
599
|
+
* in menu form — same totality rules as the global overflow.
|
|
307
600
|
*/
|
|
308
601
|
declare function projectShed(group: NormalizedGroup, fit: FitResult, resolve: ResolveMenuTarget): OverflowRow[];
|
|
309
602
|
/** One strip group: a separator boundary, its visible commands in bar order. */
|
|
@@ -313,17 +606,188 @@ interface StripGroup {
|
|
|
313
606
|
readonly commands: readonly string[];
|
|
314
607
|
}
|
|
315
608
|
/**
|
|
316
|
-
* Strip projection — a bar projected for
|
|
609
|
+
* Strip projection — a bar projected for un-measured rendering (a contextual
|
|
317
610
|
* strip anchored to a selection has no fit pressure to solve). The schema
|
|
318
|
-
* declares what
|
|
319
|
-
* decides what
|
|
320
|
-
* and an all-hidden bar projects to [] — "render nothing" falls out
|
|
611
|
+
* declares what could appear; `visible` (the command registry's runtime truth)
|
|
612
|
+
* decides what does: hidden commands drop out, groups that empty out vanish,
|
|
613
|
+
* and an all-hidden bar projects to [] — "render nothing" falls out, as it
|
|
614
|
+
* does for a bar with only dependent groups left ({@link filterBar}). Custom
|
|
321
615
|
* units project through their `terminal` command, same totality rule as the
|
|
322
616
|
* overflow. Upgrading a strip to measured/overflowing rendering later is a
|
|
323
617
|
* renderer swap (<Toolbar>), never a schema change.
|
|
324
618
|
*/
|
|
325
619
|
declare function projectStrip(bar: NormalizedBar, visible: (command: string) => boolean): StripGroup[];
|
|
326
620
|
//#endregion
|
|
621
|
+
//#region src/toolbar-layout.d.ts
|
|
622
|
+
/** What the layout reads of a resolved command; plugin-commands' `ResolvedCommand` satisfies it. */
|
|
623
|
+
interface ToolbarCommand {
|
|
624
|
+
readonly id: string;
|
|
625
|
+
readonly visible: boolean;
|
|
626
|
+
}
|
|
627
|
+
/** A group folded into one control: a menu button, or a `<select>`. */
|
|
628
|
+
interface CollapsedGroupView<Command extends ToolbarCommand = ToolbarCommand> {
|
|
629
|
+
readonly id: string;
|
|
630
|
+
readonly labelKey?: string;
|
|
631
|
+
readonly collapse: 'menu' | 'select';
|
|
632
|
+
readonly role: 'buttons' | 'tabs';
|
|
633
|
+
/** The group's visible commands (a custom item through its terminal command), resolved live. */
|
|
634
|
+
readonly commands: readonly Command[];
|
|
635
|
+
execute(id: string): void;
|
|
636
|
+
}
|
|
637
|
+
/**
|
|
638
|
+
* The button inside a group that shed some of its items. `commands` is what
|
|
639
|
+
* sits behind it, in bar order, resolved live. In the measurement layer it is
|
|
640
|
+
* measured with the whole group behind it, so a trigger that shows a count
|
|
641
|
+
* ("+3") is budgeted at its widest.
|
|
642
|
+
*/
|
|
643
|
+
interface GroupDisclosureView<Command extends ToolbarCommand = ToolbarCommand> {
|
|
644
|
+
readonly id: string;
|
|
645
|
+
readonly labelKey?: string;
|
|
646
|
+
readonly role: 'buttons' | 'tabs';
|
|
647
|
+
readonly commands: readonly Command[];
|
|
648
|
+
execute(id: string): void;
|
|
649
|
+
}
|
|
650
|
+
/** The "More" menu: what didn't fit, in sections, and the calls a menu needs. */
|
|
651
|
+
interface OverflowMenuView<Command extends ToolbarCommand = ToolbarCommand> {
|
|
652
|
+
readonly sections: readonly OverflowSection[];
|
|
653
|
+
readonly isOpen: boolean;
|
|
654
|
+
close(): void;
|
|
655
|
+
/** A row's command, resolved live, or `null` for an unknown id. */
|
|
656
|
+
resolve(id: string): Command | null;
|
|
657
|
+
execute(id: string): void;
|
|
658
|
+
}
|
|
659
|
+
/** What a custom item's renderer receives besides the item's variant. */
|
|
660
|
+
interface CustomSlotCtx {
|
|
661
|
+
/** `'live'` in the visible row, `'measure'` in the hidden measurement layer. */
|
|
662
|
+
layer: 'live' | 'measure';
|
|
663
|
+
/**
|
|
664
|
+
* Report the item's length yourself (its width, or its height in a vertical
|
|
665
|
+
* bar), for content the measurement layer can't hold.
|
|
666
|
+
*/
|
|
667
|
+
measure: (length: number) => void;
|
|
668
|
+
}
|
|
669
|
+
/**
|
|
670
|
+
* One thing in the toolbar. `key` is its identity in the live row, the same
|
|
671
|
+
* at every variant; `measureKey` is the key its length is reported under,
|
|
672
|
+
* unique across the whole toolbar. A `custom` part is the app's to draw;
|
|
673
|
+
* without a renderer for it, an adapter draws a native `<slot>` socket
|
|
674
|
+
* measured where it renders, and leaves it out of the measurement layer: only
|
|
675
|
+
* the first `<slot>` of a name gets the projected children.
|
|
676
|
+
*/
|
|
677
|
+
type ToolbarPart<Command extends ToolbarCommand = ToolbarCommand> = {
|
|
678
|
+
readonly kind: 'command';
|
|
679
|
+
readonly key: string;
|
|
680
|
+
readonly measureKey: string;
|
|
681
|
+
readonly command: Command;
|
|
682
|
+
readonly variant: string;
|
|
683
|
+
readonly run: () => void;
|
|
684
|
+
} | {
|
|
685
|
+
readonly kind: 'custom';
|
|
686
|
+
readonly key: string;
|
|
687
|
+
readonly measureKey: string;
|
|
688
|
+
/** The item's name, from `custom(name, terminal)`. */
|
|
689
|
+
readonly name: string;
|
|
690
|
+
readonly variant: string;
|
|
691
|
+
/** The command it becomes in the "More" menu; drawn when no renderer draws the item. */
|
|
692
|
+
readonly terminal: Command | null;
|
|
693
|
+
readonly runTerminal: () => void;
|
|
694
|
+
} | {
|
|
695
|
+
readonly kind: 'collapsed';
|
|
696
|
+
readonly key: string;
|
|
697
|
+
readonly measureKey: string;
|
|
698
|
+
readonly view: CollapsedGroupView<Command>;
|
|
699
|
+
} | {
|
|
700
|
+
readonly kind: 'disclosure';
|
|
701
|
+
readonly key: string;
|
|
702
|
+
readonly measureKey: string;
|
|
703
|
+
readonly view: GroupDisclosureView<Command>;
|
|
704
|
+
};
|
|
705
|
+
/** A group in the live row: its visible parts. Every group but a section's first has a separator before it. */
|
|
706
|
+
interface LiveGroup<Command extends ToolbarCommand = ToolbarCommand> {
|
|
707
|
+
readonly id: string;
|
|
708
|
+
readonly parts: readonly ToolbarPart<Command>[];
|
|
709
|
+
}
|
|
710
|
+
/** A section of the live row (`start`, `center` or `end`), with only its visible groups. */
|
|
711
|
+
interface LiveSection<Command extends ToolbarCommand = ToolbarCommand> {
|
|
712
|
+
readonly name: 'start' | 'center' | 'end';
|
|
713
|
+
readonly groups: readonly LiveGroup<Command>[];
|
|
714
|
+
}
|
|
715
|
+
interface ToolbarLayout<Command extends ToolbarCommand = ToolbarCommand> {
|
|
716
|
+
/** Always the three sections, in order. */
|
|
717
|
+
readonly sections: readonly LiveSection<Command>[];
|
|
718
|
+
/**
|
|
719
|
+
* What the measurement layer draws, each reporting its length under its
|
|
720
|
+
* `measureKey`: every unit in every variant, each collapsible group folded,
|
|
721
|
+
* each shed group's trigger with the whole group behind it.
|
|
722
|
+
*/
|
|
723
|
+
readonly measured: readonly ToolbarPart<Command>[];
|
|
724
|
+
readonly hasOverflow: boolean;
|
|
725
|
+
/** The "More" menu, derived from what didn't fit. */
|
|
726
|
+
readonly overflow: readonly OverflowSection[];
|
|
727
|
+
}
|
|
728
|
+
/** The keys a measurement layer reports lengths under; `@embedpdf/web`'s `toolbarMeasureKey` satisfies it. */
|
|
729
|
+
interface ToolbarMeasureKeys {
|
|
730
|
+
unit(unitKey: string, variant: string): string;
|
|
731
|
+
group(groupId: string): string;
|
|
732
|
+
groupTrigger(groupId: string): string;
|
|
733
|
+
}
|
|
734
|
+
/** What {@link layoutToolbar} reads. */
|
|
735
|
+
interface ToolbarLayoutInput<Command extends ToolbarCommand> {
|
|
736
|
+
/** The bar, from `normalizeBar`. */
|
|
737
|
+
readonly bar: NormalizedBar;
|
|
738
|
+
/** A command for the toolbar's document, or `null` for an id no plugin registered. */
|
|
739
|
+
readonly resolve: (id: string) => Command | null;
|
|
740
|
+
/** What an id no plugin registered draws as: a disabled command named by its id. */
|
|
741
|
+
readonly unregistered: (id: string) => Command;
|
|
742
|
+
/** Run a command for the toolbar's document. */
|
|
743
|
+
readonly execute: (id: string) => void;
|
|
744
|
+
/** Which menu a command opens, for the "More" menu's submenu rows. */
|
|
745
|
+
readonly menuTarget: ResolveMenuTarget;
|
|
746
|
+
/** The measured lengths, along the toolbar's axis. */
|
|
747
|
+
readonly metrics: FitMetrics;
|
|
748
|
+
/** The keys the measured lengths are reported under. */
|
|
749
|
+
readonly measureKey: ToolbarMeasureKeys;
|
|
750
|
+
/** The length the toolbar fills: its width, or its height when vertical. */
|
|
751
|
+
readonly containerLength: number;
|
|
752
|
+
/**
|
|
753
|
+
* Which way the toolbar runs. A vertical toolbar draws every command at
|
|
754
|
+
* `'icon'`, with no smaller step, and leaves its label to a tooltip. Default
|
|
755
|
+
* `'horizontal'`.
|
|
756
|
+
*/
|
|
757
|
+
readonly orientation?: 'horizontal' | 'vertical';
|
|
758
|
+
}
|
|
759
|
+
/** Fit the bar into `containerLength` and describe what to draw. */
|
|
760
|
+
declare function layoutToolbar<Command extends ToolbarCommand>(input: ToolbarLayoutInput<Command>): ToolbarLayout<Command>;
|
|
761
|
+
/**
|
|
762
|
+
* The menu a default folded group or group trigger opens: one section of the
|
|
763
|
+
* group's commands, a radio group when the group is tabs.
|
|
764
|
+
*/
|
|
765
|
+
declare function groupMenuView<Command extends ToolbarCommand>(view: CollapsedGroupView<Command> | GroupDisclosureView<Command>, isOpen: boolean, close: () => void): OverflowMenuView<Command>;
|
|
766
|
+
/** A group of a strip: its visible commands, in bar order. Groups are separator boundaries. */
|
|
767
|
+
interface StripViewGroup<Command extends ToolbarCommand = ToolbarCommand> {
|
|
768
|
+
readonly id: string;
|
|
769
|
+
readonly labelKey?: string;
|
|
770
|
+
readonly commands: readonly Command[];
|
|
771
|
+
}
|
|
772
|
+
/** A strip, resolved: only visible commands, only groups with one. */
|
|
773
|
+
interface StripView<Command extends ToolbarCommand = ToolbarCommand> {
|
|
774
|
+
readonly groups: readonly StripViewGroup<Command>[];
|
|
775
|
+
/** Run a command for the strip's document. */
|
|
776
|
+
execute(id: string): void;
|
|
777
|
+
}
|
|
778
|
+
/**
|
|
779
|
+
* A bar as a strip shows it now (`projectStrip`), each command resolved: the
|
|
780
|
+
* schema says what could appear, each command's `visible` decides what does.
|
|
781
|
+
* Empty while nothing applies.
|
|
782
|
+
*/
|
|
783
|
+
declare function stripGroupsOf<Command extends ToolbarCommand>(bar: NormalizedBar, resolve: (id: string) => Command | null): StripViewGroup<Command>[];
|
|
784
|
+
/**
|
|
785
|
+
* Whether two resolved strips show the same, group by group and command by
|
|
786
|
+
* command (`sameCommand` is plugin-commands' `resolvedCommandsEqual`): a
|
|
787
|
+
* strip's readers pass it on only when this is false.
|
|
788
|
+
*/
|
|
789
|
+
declare function sameStripGroups<Command extends ToolbarCommand>(left: readonly StripViewGroup<Command>[], right: readonly StripViewGroup<Command>[], sameCommand: (left: Command, right: Command) => boolean): boolean;
|
|
790
|
+
//#endregion
|
|
327
791
|
//#region src/shortcuts.d.ts
|
|
328
792
|
/**
|
|
329
793
|
* Shortcut parsing + matching — pure. No `navigator`: platform is an input
|
|
@@ -332,7 +796,7 @@ declare function projectStrip(bar: NormalizedBar, visible: (command: string) =>
|
|
|
332
796
|
* Grammar: modifiers and one key joined by '+', e.g. 'Mod+K', 'Ctrl+=',
|
|
333
797
|
* 'Shift+Alt+D', 'Meta+NumpadAdd'. 'Mod' is ⌘ on mac and Ctrl elsewhere.
|
|
334
798
|
* Keys longer than one character (F1, Escape, NumpadAdd, ArrowLeft) match
|
|
335
|
-
* `event.key`
|
|
799
|
+
* `event.key` or `event.code` case-insensitively, so numpad shortcuts work.
|
|
336
800
|
*/
|
|
337
801
|
interface ParsedShortcut {
|
|
338
802
|
readonly key: string;
|
|
@@ -352,13 +816,70 @@ interface KeyStroke {
|
|
|
352
816
|
readonly shiftKey: boolean;
|
|
353
817
|
}
|
|
354
818
|
declare function parseShortcut(shortcut: string): ParsedShortcut;
|
|
355
|
-
declare function matchShortcut(parsed: ParsedShortcut, stroke: KeyStroke,
|
|
819
|
+
declare function matchShortcut(parsed: ParsedShortcut, stroke: KeyStroke, options: {
|
|
820
|
+
isMac: boolean;
|
|
821
|
+
}): boolean;
|
|
822
|
+
/**
|
|
823
|
+
* Whether two shortcuts are pressed with the same keys on this platform: `'Mod+S'` and
|
|
824
|
+
* `'Ctrl+s'` are where `Mod` is Ctrl, and not on a Mac.
|
|
825
|
+
*/
|
|
826
|
+
declare function sameShortcut(left: string, right: string, options: {
|
|
356
827
|
isMac: boolean;
|
|
357
828
|
}): boolean;
|
|
358
|
-
/**
|
|
359
|
-
declare function formatShortcut(shortcut: string,
|
|
829
|
+
/** A shortcut as a menu or a tooltip shows it: `'⌘K'` on a Mac, `'Ctrl+K'` elsewhere. */
|
|
830
|
+
declare function formatShortcut(shortcut: string, options: {
|
|
360
831
|
isMac: boolean;
|
|
361
832
|
}): string;
|
|
362
833
|
//#endregion
|
|
363
|
-
|
|
834
|
+
//#region src/tree-keys.d.ts
|
|
835
|
+
/**
|
|
836
|
+
* The keyboard of a tree view, as the ARIA tree pattern has it — pure.
|
|
837
|
+
* A view hands in the rows that show (in order, each with its depth, whether
|
|
838
|
+
* it has children and whether they show), the focused row and the key
|
|
839
|
+
* (`KeyboardEvent.key`); it gets back what the key does, and does it. A key
|
|
840
|
+
* that does nothing returns `null`, so the view lets the event go on.
|
|
841
|
+
*
|
|
842
|
+
* ArrowDown, ArrowUp the next, the previous row
|
|
843
|
+
* ArrowRight a collapsed parent expands; an expanded one moves to its first child
|
|
844
|
+
* ArrowLeft an expanded parent collapses; any other row moves to its parent
|
|
845
|
+
* Home, End the first, the last row
|
|
846
|
+
* * every collapsed sibling of the focused row expands
|
|
847
|
+
* Enter the row activates
|
|
848
|
+
* F2, Delete the row is renamed or deleted, when the tree is editable
|
|
849
|
+
*/
|
|
850
|
+
/** A row as the keyboard sees it. */
|
|
851
|
+
interface TreeKeyRow {
|
|
852
|
+
/** How deep it sits: 0 at the top level. */
|
|
853
|
+
readonly depth: number;
|
|
854
|
+
readonly hasChildren: boolean;
|
|
855
|
+
/** Whether its children show. */
|
|
856
|
+
readonly expanded: boolean;
|
|
857
|
+
}
|
|
858
|
+
/** What a key does, naming rows by their index in the rows handed in. */
|
|
859
|
+
type TreeKeyAction = {
|
|
860
|
+
readonly type: 'focus';
|
|
861
|
+
readonly row: number;
|
|
862
|
+
} | {
|
|
863
|
+
readonly type: 'expand';
|
|
864
|
+
readonly rows: readonly number[];
|
|
865
|
+
} | {
|
|
866
|
+
readonly type: 'collapse';
|
|
867
|
+
readonly row: number;
|
|
868
|
+
} | {
|
|
869
|
+
readonly type: 'activate';
|
|
870
|
+
readonly row: number;
|
|
871
|
+
} | {
|
|
872
|
+
readonly type: 'rename';
|
|
873
|
+
readonly row: number;
|
|
874
|
+
} | {
|
|
875
|
+
readonly type: 'delete';
|
|
876
|
+
readonly row: number;
|
|
877
|
+
};
|
|
878
|
+
interface TreeKeyOptions {
|
|
879
|
+
/** Whether F2 and Delete edit the tree. Off by default: a reader's tree only moves and opens. */
|
|
880
|
+
readonly editable?: boolean;
|
|
881
|
+
}
|
|
882
|
+
declare function treeKeyAction(rows: readonly TreeKeyRow[], focused: number, key: string, options?: TreeKeyOptions): TreeKeyAction | null;
|
|
883
|
+
//#endregion
|
|
884
|
+
export { type AddItemOptions, type BarChild, type BarEdge, type BarGroup, type BarItem, type BarPlace, type BarSchema, type BarSections, type CollapsedGroupView, type CompileBarOptions, type CustomItem, type CustomSlotCtx, DEFAULT_IMPORTANCE, EXPANDED_MIN_WIDTH_PX, FLOAT_POSITIONS, type FitMetrics, type FitResult, type FloatPosition, type GroupAssignment, type GroupDisclosureView, type Importance, type KeyStroke, type Layout, type LayoutBar, type LayoutCommandItem, type LayoutCustomItem, type LayoutData, type LayoutEnv, type LayoutFunction, type LayoutGroup, type LayoutGroupObject, type LayoutItem, type LayoutKnownIds, type LayoutMenu, type LayoutMenuSection, type LayoutOption, type LayoutPanel, type LayoutPanelPatch, type LayoutSection, type LiveGroup, type LiveSection, MEDIUM_MIN_WIDTH_PX, MODES_GROUP, type MenuSection, type NormalizedBar, type NormalizedGroup, type NormalizedSection, type NormalizedUnit, type OmissionCommand, type OverflowMenuView, type OverflowRow, type OverflowSection, PINNED, type PanelPresentation, type PanelPresentationBySize, type PanelWidth, type ParsedShortcut, type RemoveItemOptions, type ResolveMenuTarget, type SectionName, type SelectionTarget, type StripGroup, type StripView, type StripViewGroup, type TabsVisibility, type ToolbarCommand, type ToolbarLayout, type ToolbarLayoutInput, type ToolbarMeasureKeys, type ToolbarPart, type TreeKeyAction, type TreeKeyOptions, type TreeKeyRow, type UnitAssignment, VIEW_MODE_COMMAND, type Variant, type ViewerSize, barsAt, barsFloating, barsInMode, barsOnEdge, barsWith, closestMatch, commandOfUnit, compileBar, createLayout, custom, didYouMean, edgeOf, edgeStackOf, editDistance, filterBar, floatOf, floatStackOf, formatShortcut, group, groupMenuView, hasVisibleUnits, hostOf, isLayout, isStandaloneUnit, item, itemCommandOf, itemIdOf, layoutToolbar, matchShortcut, menuOf, modeCommandOf, modesOf, normalizeBar, omittedCommandsOf, panelCommandOf, panelPresentationsOf, panelWidthFieldsOf, parseShortcut, projectOverflow, projectShed, projectStrip, resolveLayout, sameLayoutEnv, sameShortcut, sameStripGroups, selectionOf, sizeOf, solve, stripGroupsOf, tabsOf, treeKeyAction, validateLayout };
|
|
364
885
|
//# sourceMappingURL=index.d.cts.map
|