@gjermundgaraba-designs/pixel-paper 0.21.0 → 0.22.1
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/DESIGN.md +22 -15
- package/dist/src/bench/bench.d.ts +17 -0
- package/dist/src/bench/bench.d.ts.map +1 -0
- package/dist/src/bench/bench.js +10 -0
- package/dist/src/bench/index.d.ts +3 -0
- package/dist/src/bench/index.d.ts.map +1 -0
- package/dist/src/bench/index.js +1 -0
- package/dist/src/chip/chip.d.ts +10 -0
- package/dist/src/chip/chip.d.ts.map +1 -1
- package/dist/src/chip/chip.js +19 -0
- package/dist/src/chip/index.d.ts +2 -2
- package/dist/src/chip/index.d.ts.map +1 -1
- package/dist/src/chip/index.js +1 -1
- package/dist/src/drag/drag.d.ts +18 -0
- package/dist/src/drag/drag.d.ts.map +1 -1
- package/dist/src/drag/drag.js +35 -7
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +1 -0
- package/dist/src/rail/index.d.ts +1 -1
- package/dist/src/rail/index.d.ts.map +1 -1
- package/dist/src/rail/index.js +1 -1
- package/dist/src/rail/rail.d.ts +217 -17
- package/dist/src/rail/rail.d.ts.map +1 -1
- package/dist/src/rail/rail.js +133 -15
- package/dist/src/reel/index.d.ts +1 -1
- package/dist/src/reel/index.d.ts.map +1 -1
- package/dist/src/reel/index.js +1 -1
- package/dist/src/reel/layout.d.ts +21 -26
- package/dist/src/reel/layout.d.ts.map +1 -1
- package/dist/src/reel/layout.js +84 -106
- package/dist/src/reel/reel.d.ts +30 -172
- package/dist/src/reel/reel.d.ts.map +1 -1
- package/dist/src/reel/reel.js +144 -195
- package/dist/src/rows/rows.d.ts +9 -1
- package/dist/src/rows/rows.d.ts.map +1 -1
- package/dist/src/rows/rows.js +1 -1
- package/package.json +1 -1
- package/src/bench/bench.ts +27 -0
- package/src/bench/index.ts +2 -0
- package/src/chip/chip.ts +31 -0
- package/src/chip/index.ts +2 -2
- package/src/drag/drag.ts +60 -1
- package/src/index.ts +1 -0
- package/src/pixel-paper.css +212 -32
- package/src/rail/index.ts +2 -0
- package/src/rail/rail.ts +181 -16
- package/src/reel/index.ts +0 -1
- package/src/reel/layout.ts +78 -118
- package/src/reel/reel.ts +108 -216
- package/src/rows/rows.ts +14 -2
- package/src/tokens.css +5 -1
package/dist/src/rail/rail.d.ts
CHANGED
|
@@ -2,12 +2,20 @@ import { Effect, Option, Schema } from "effect";
|
|
|
2
2
|
import * as Command from "foldkit/command";
|
|
3
3
|
import type { Html } from "foldkit/html";
|
|
4
4
|
import * as Mount from "foldkit/mount";
|
|
5
|
+
import * as Subscription from "foldkit/subscription";
|
|
5
6
|
import type * as Update from "foldkit/update";
|
|
6
|
-
/** Schema for a rail: whether it is open as a drawer (at 900px and under
|
|
7
|
-
*
|
|
7
|
+
/** Schema for a rail: whether it is open as a drawer (at 900px and under; wider, it is always
|
|
8
|
+
* in the page and this stays false), and its splitter while a pointer drags it. Its width is
|
|
9
|
+
* the parent's. */
|
|
8
10
|
export declare const Model: Schema.Struct<{
|
|
9
11
|
readonly id: Schema.String;
|
|
10
12
|
readonly isOpen: Schema.Boolean;
|
|
13
|
+
readonly maybeResizing: Schema.Option<Schema.Struct<{
|
|
14
|
+
readonly pointerId: Schema.Number;
|
|
15
|
+
readonly pressX: Schema.Number;
|
|
16
|
+
readonly fromWidth: Schema.Number;
|
|
17
|
+
readonly width: Schema.Number;
|
|
18
|
+
}>>;
|
|
11
19
|
}>;
|
|
12
20
|
export type Model = typeof Model.Type;
|
|
13
21
|
/** Union of all Messages a rail can produce. `ClosedDrawer` is the browser closing it on
|
|
@@ -15,6 +23,22 @@ export type Model = typeof Model.Type;
|
|
|
15
23
|
* the window growing past 900px while it is open, where the rail is back in the page. */
|
|
16
24
|
export declare const Message: import("foldkit/message").MessageUnion<{
|
|
17
25
|
readonly ClickedOpen: {};
|
|
26
|
+
readonly PressedSplitter: {
|
|
27
|
+
pointerId: Schema.Number;
|
|
28
|
+
clientX: Schema.Number;
|
|
29
|
+
width: Schema.Number;
|
|
30
|
+
};
|
|
31
|
+
readonly MovedSplitter: {
|
|
32
|
+
clientX: Schema.Number;
|
|
33
|
+
};
|
|
34
|
+
readonly ReleasedSplitter: {
|
|
35
|
+
clientX: Schema.Number;
|
|
36
|
+
};
|
|
37
|
+
readonly CancelledSplitter: {};
|
|
38
|
+
readonly PressedEscape: {};
|
|
39
|
+
readonly PressedSplitterKey: {
|
|
40
|
+
width: Schema.Number;
|
|
41
|
+
};
|
|
18
42
|
readonly ClickedClose: {};
|
|
19
43
|
readonly ClosedDrawer: {};
|
|
20
44
|
readonly BlurredDrawer: {};
|
|
@@ -23,12 +47,21 @@ export declare const Message: import("foldkit/message").MessageUnion<{
|
|
|
23
47
|
readonly CompletedHideRailDrawer: {};
|
|
24
48
|
}>;
|
|
25
49
|
export type Message = typeof Message.Type;
|
|
50
|
+
/** What a rail asks of its parent. `ResizedRail`: its splitter was let go, or stepped by a
|
|
51
|
+
* key, at `width` pixels, within the rail's bounds; the parent keeps it (per client) and
|
|
52
|
+
* passes it back as the view's `maybeWidth`. */
|
|
53
|
+
export declare const OutMessage: import("foldkit/message").MessageUnion<{
|
|
54
|
+
readonly ResizedRail: {
|
|
55
|
+
width: Schema.Number;
|
|
56
|
+
};
|
|
57
|
+
}>;
|
|
58
|
+
export type OutMessage = typeof OutMessage.Type;
|
|
26
59
|
/** Configuration for creating a rail with `init`. The `id` is the rail's, unique in the
|
|
27
60
|
* document. */
|
|
28
61
|
export type InitConfig = Readonly<{
|
|
29
62
|
id: string;
|
|
30
63
|
}>;
|
|
31
|
-
/** Creates a rail, closed. */
|
|
64
|
+
/** Creates a rail, closed, its splitter at rest. */
|
|
32
65
|
export declare const init: (config: InitConfig) => Model;
|
|
33
66
|
/** The rail's id, unique in the document. */
|
|
34
67
|
export declare const id: (model: Model) => string;
|
|
@@ -55,14 +88,25 @@ export declare const HideRailDrawer: Command.CommandDefinitionWithArgs<"HideRail
|
|
|
55
88
|
type UpdateReturn = Update.Return<Model, Message>;
|
|
56
89
|
/** Closes the rail's drawer, focus back on its button. */
|
|
57
90
|
export declare const close: (model: Model) => UpdateReturn;
|
|
58
|
-
/** Processes a rail Message and returns the next Model and
|
|
91
|
+
/** Processes a rail Message and returns the next Model, Commands and OutMessage: a splitter let
|
|
92
|
+
* go where it changes the width, or stepped by a key, asks for the width. */
|
|
59
93
|
export declare const update: (model: Model, message: Message) => Readonly<{
|
|
60
94
|
model: {
|
|
61
95
|
readonly id: string;
|
|
62
96
|
readonly isOpen: boolean;
|
|
97
|
+
readonly maybeResizing: Option.Option<{
|
|
98
|
+
readonly pointerId: number;
|
|
99
|
+
readonly pressX: number;
|
|
100
|
+
readonly fromWidth: number;
|
|
101
|
+
readonly width: number;
|
|
102
|
+
}>;
|
|
63
103
|
};
|
|
64
104
|
commands?: Update.Commands<{
|
|
105
|
+
readonly _tag: "PressedEscape";
|
|
106
|
+
} | {
|
|
65
107
|
readonly _tag: "BlurredDrawer";
|
|
108
|
+
} | {
|
|
109
|
+
readonly _tag: "CancelledSplitter";
|
|
66
110
|
} | {
|
|
67
111
|
readonly _tag: "ClickedClose";
|
|
68
112
|
} | {
|
|
@@ -73,10 +117,27 @@ export declare const update: (model: Model, message: Message) => Readonly<{
|
|
|
73
117
|
readonly _tag: "CompletedHideRailDrawer";
|
|
74
118
|
} | {
|
|
75
119
|
readonly _tag: "CompletedShowRailDrawer";
|
|
120
|
+
} | {
|
|
121
|
+
readonly _tag: "MovedSplitter";
|
|
122
|
+
readonly clientX: number;
|
|
123
|
+
} | {
|
|
124
|
+
readonly _tag: "PressedSplitter";
|
|
125
|
+
readonly pointerId: number;
|
|
126
|
+
readonly clientX: number;
|
|
127
|
+
readonly width: number;
|
|
128
|
+
} | {
|
|
129
|
+
readonly _tag: "PressedSplitterKey";
|
|
130
|
+
readonly width: number;
|
|
131
|
+
} | {
|
|
132
|
+
readonly _tag: "ReleasedSplitter";
|
|
133
|
+
readonly clientX: number;
|
|
76
134
|
} | {
|
|
77
135
|
readonly _tag: "WidenedPastDrawer";
|
|
78
136
|
}, never>;
|
|
79
|
-
outMessage?:
|
|
137
|
+
outMessage?: {
|
|
138
|
+
readonly _tag: "ResizedRail";
|
|
139
|
+
readonly width: number;
|
|
140
|
+
};
|
|
80
141
|
}>;
|
|
81
142
|
type DrawerMessage = typeof Message.ClosedDrawer.Type | typeof Message.BlurredDrawer.Type | typeof Message.WidenedPastDrawer.Type;
|
|
82
143
|
/** The window crossing the drawer's width: growing past it while the drawer is open closes
|
|
@@ -98,28 +159,138 @@ export declare const FollowRailDrawer: Mount.MountDefinitionNoArgs<"FollowRailDr
|
|
|
98
159
|
} | {
|
|
99
160
|
readonly _tag: "WidenedPastDrawer";
|
|
100
161
|
}>;
|
|
162
|
+
/** A dragged splitter follows the pointer, and Escape puts it back before a dialog or the
|
|
163
|
+
* page sees it, from listeners that run only while it is dragged. Lift them into the
|
|
164
|
+
* application's Subscriptions behind a key prefix of the parent's: `subscriptions("rail")` is
|
|
165
|
+
* keyed `railResize` and `railEscape`. */
|
|
166
|
+
export declare const subscriptions: <Prefix extends string>(keyPrefix: Prefix) => {
|
|
167
|
+
readonly resize: Subscription.EntryWithoutKeepAlive<{
|
|
168
|
+
readonly id: string;
|
|
169
|
+
readonly isOpen: boolean;
|
|
170
|
+
readonly maybeResizing: Option.Option<{
|
|
171
|
+
readonly pointerId: number;
|
|
172
|
+
readonly pressX: number;
|
|
173
|
+
readonly fromWidth: number;
|
|
174
|
+
readonly width: number;
|
|
175
|
+
}>;
|
|
176
|
+
}, {
|
|
177
|
+
readonly _tag: "PressedEscape";
|
|
178
|
+
} | {
|
|
179
|
+
readonly _tag: "BlurredDrawer";
|
|
180
|
+
} | {
|
|
181
|
+
readonly _tag: "CancelledSplitter";
|
|
182
|
+
} | {
|
|
183
|
+
readonly _tag: "ClickedClose";
|
|
184
|
+
} | {
|
|
185
|
+
readonly _tag: "ClickedOpen";
|
|
186
|
+
} | {
|
|
187
|
+
readonly _tag: "ClosedDrawer";
|
|
188
|
+
} | {
|
|
189
|
+
readonly _tag: "CompletedHideRailDrawer";
|
|
190
|
+
} | {
|
|
191
|
+
readonly _tag: "CompletedShowRailDrawer";
|
|
192
|
+
} | {
|
|
193
|
+
readonly _tag: "MovedSplitter";
|
|
194
|
+
readonly clientX: number;
|
|
195
|
+
} | {
|
|
196
|
+
readonly _tag: "PressedSplitter";
|
|
197
|
+
readonly pointerId: number;
|
|
198
|
+
readonly clientX: number;
|
|
199
|
+
readonly width: number;
|
|
200
|
+
} | {
|
|
201
|
+
readonly _tag: "PressedSplitterKey";
|
|
202
|
+
readonly width: number;
|
|
203
|
+
} | {
|
|
204
|
+
readonly _tag: "ReleasedSplitter";
|
|
205
|
+
readonly clientX: number;
|
|
206
|
+
} | {
|
|
207
|
+
readonly _tag: "WidenedPastDrawer";
|
|
208
|
+
}, {
|
|
209
|
+
readonly maybePointerId: Option.Option<number>;
|
|
210
|
+
}, never> & {
|
|
211
|
+
readonly __subscription: never;
|
|
212
|
+
};
|
|
213
|
+
readonly escape: Subscription.EntryWithoutKeepAlive<{
|
|
214
|
+
readonly id: string;
|
|
215
|
+
readonly isOpen: boolean;
|
|
216
|
+
readonly maybeResizing: Option.Option<{
|
|
217
|
+
readonly pointerId: number;
|
|
218
|
+
readonly pressX: number;
|
|
219
|
+
readonly fromWidth: number;
|
|
220
|
+
readonly width: number;
|
|
221
|
+
}>;
|
|
222
|
+
}, {
|
|
223
|
+
readonly _tag: "PressedEscape";
|
|
224
|
+
} | {
|
|
225
|
+
readonly _tag: "BlurredDrawer";
|
|
226
|
+
} | {
|
|
227
|
+
readonly _tag: "CancelledSplitter";
|
|
228
|
+
} | {
|
|
229
|
+
readonly _tag: "ClickedClose";
|
|
230
|
+
} | {
|
|
231
|
+
readonly _tag: "ClickedOpen";
|
|
232
|
+
} | {
|
|
233
|
+
readonly _tag: "ClosedDrawer";
|
|
234
|
+
} | {
|
|
235
|
+
readonly _tag: "CompletedHideRailDrawer";
|
|
236
|
+
} | {
|
|
237
|
+
readonly _tag: "CompletedShowRailDrawer";
|
|
238
|
+
} | {
|
|
239
|
+
readonly _tag: "MovedSplitter";
|
|
240
|
+
readonly clientX: number;
|
|
241
|
+
} | {
|
|
242
|
+
readonly _tag: "PressedSplitter";
|
|
243
|
+
readonly pointerId: number;
|
|
244
|
+
readonly clientX: number;
|
|
245
|
+
readonly width: number;
|
|
246
|
+
} | {
|
|
247
|
+
readonly _tag: "PressedSplitterKey";
|
|
248
|
+
readonly width: number;
|
|
249
|
+
} | {
|
|
250
|
+
readonly _tag: "ReleasedSplitter";
|
|
251
|
+
readonly clientX: number;
|
|
252
|
+
} | {
|
|
253
|
+
readonly _tag: "WidenedPastDrawer";
|
|
254
|
+
}, {
|
|
255
|
+
readonly isResizing: boolean;
|
|
256
|
+
}, never> & {
|
|
257
|
+
readonly __subscription: never;
|
|
258
|
+
};
|
|
259
|
+
} extends infer T ? { readonly [Key in keyof T as `${Prefix}${Capitalize<Key>}`]: T[Key]; } : never;
|
|
101
260
|
/** Per-render inputs passed to `view` through `h.submodel`'s `viewInputs`. */
|
|
102
261
|
export type ViewInputs = Readonly<{
|
|
103
|
-
/** Names the rail for screen readers, and its button
|
|
262
|
+
/** Names the rail for screen readers, and its button, drawer head and splitter
|
|
263
|
+
* (`"collections"`). */
|
|
104
264
|
label: string;
|
|
265
|
+
/** The width the reader gave the rail, in pixels, as the parent keeps it from `ResizedRail`
|
|
266
|
+
* (for this client: another reader's window is not this one's); none for the stylesheet's.
|
|
267
|
+
* A width out of the rail's bounds prints at the nearer bound. */
|
|
268
|
+
maybeWidth: Option.Option<number>;
|
|
105
269
|
/** The rail's panels: a tree, places, filters. A function because a Submodel's viewInputs
|
|
106
270
|
* may hold functions only at the top level, and Foldkit runs this one in the parent's
|
|
107
271
|
* boundary, so the handlers in what it returns dispatch the parent's Messages. */
|
|
108
272
|
toAsideView: () => ReadonlyArray<Html>;
|
|
109
|
-
/** The
|
|
110
|
-
* drawer to print first in it. A function because it receives that button, and
|
|
111
|
-
* parent's boundary like `toAsideView`. */
|
|
273
|
+
/** The page beside the rail, `main.deck#main` or `main.bench#main`, given the button that
|
|
274
|
+
* opens the drawer to print first in it. A function because it receives that button, and
|
|
275
|
+
* runs in the parent's boundary like `toAsideView`. */
|
|
112
276
|
toDeckView: (openButton: Html) => Html;
|
|
113
277
|
}>;
|
|
114
278
|
/**
|
|
115
279
|
* A column of panels beside the deck, fixed under the top bar and scrolling itself:
|
|
116
|
-
* `div.railed >` the deck, then `aside.rail[popover="auto"][aria-label]
|
|
117
|
-
*
|
|
118
|
-
*
|
|
119
|
-
*
|
|
280
|
+
* `div.railed >` the deck, then `aside.rail[popover="auto"][aria-label]`, then its splitter,
|
|
281
|
+
* `div.rail-resize[role="separator"]`, on its right edge. One element serves both layouts, so
|
|
282
|
+
* nothing in it renders twice or loses its state. At 900px and under it leaves the page, and
|
|
283
|
+
* `span.rail-open > button.btn.small` at the top of the deck opens the same element as a drawer
|
|
284
|
+
* over a veil, its head (the name and a close glyph) showing. Opening focuses its first
|
|
120
285
|
* control; Escape, a press on the veil, the close glyph, focus leaving or the window growing
|
|
121
286
|
* past 900px closes it, and the first three put focus back on the button.
|
|
122
287
|
*
|
|
288
|
+
* Its splitter sizes it, by a pointer (previewed as it moves) or the side arrows, within its
|
|
289
|
+
* bounds, and reports the width as `ResizedRail` for the parent to keep and pass back as
|
|
290
|
+
* `maybeWidth`, which the view sets as `--rail` on `div.railed`, so the page's padding and the
|
|
291
|
+
* rail's width follow it. The drawer keeps its own width. Lift `subscriptions(keyPrefix)` into
|
|
292
|
+
* the application's, or a dragged splitter follows nothing.
|
|
293
|
+
*
|
|
123
294
|
* Its state is its own, not `@foldkit/ui`'s Popover: that panel is placed by Floating UI and
|
|
124
295
|
* rendered only while open, and this one is always in the page, placed by the stylesheet, and
|
|
125
296
|
* opened as a native popover so the browser keeps it in the top layer.
|
|
@@ -127,8 +298,18 @@ export type ViewInputs = Readonly<{
|
|
|
127
298
|
export declare const view: import("foldkit/submodel").View<{
|
|
128
299
|
readonly id: string;
|
|
129
300
|
readonly isOpen: boolean;
|
|
301
|
+
readonly maybeResizing: Option.Option<{
|
|
302
|
+
readonly pointerId: number;
|
|
303
|
+
readonly pressX: number;
|
|
304
|
+
readonly fromWidth: number;
|
|
305
|
+
readonly width: number;
|
|
306
|
+
}>;
|
|
130
307
|
}, {
|
|
308
|
+
readonly _tag: "PressedEscape";
|
|
309
|
+
} | {
|
|
131
310
|
readonly _tag: "BlurredDrawer";
|
|
311
|
+
} | {
|
|
312
|
+
readonly _tag: "CancelledSplitter";
|
|
132
313
|
} | {
|
|
133
314
|
readonly _tag: "ClickedClose";
|
|
134
315
|
} | {
|
|
@@ -139,18 +320,37 @@ export declare const view: import("foldkit/submodel").View<{
|
|
|
139
320
|
readonly _tag: "CompletedHideRailDrawer";
|
|
140
321
|
} | {
|
|
141
322
|
readonly _tag: "CompletedShowRailDrawer";
|
|
323
|
+
} | {
|
|
324
|
+
readonly _tag: "MovedSplitter";
|
|
325
|
+
readonly clientX: number;
|
|
326
|
+
} | {
|
|
327
|
+
readonly _tag: "PressedSplitter";
|
|
328
|
+
readonly pointerId: number;
|
|
329
|
+
readonly clientX: number;
|
|
330
|
+
readonly width: number;
|
|
331
|
+
} | {
|
|
332
|
+
readonly _tag: "PressedSplitterKey";
|
|
333
|
+
readonly width: number;
|
|
334
|
+
} | {
|
|
335
|
+
readonly _tag: "ReleasedSplitter";
|
|
336
|
+
readonly clientX: number;
|
|
142
337
|
} | {
|
|
143
338
|
readonly _tag: "WidenedPastDrawer";
|
|
144
339
|
}, Readonly<{
|
|
145
|
-
/** Names the rail for screen readers, and its button
|
|
340
|
+
/** Names the rail for screen readers, and its button, drawer head and splitter
|
|
341
|
+
* (`"collections"`). */
|
|
146
342
|
label: string;
|
|
343
|
+
/** The width the reader gave the rail, in pixels, as the parent keeps it from `ResizedRail`
|
|
344
|
+
* (for this client: another reader's window is not this one's); none for the stylesheet's.
|
|
345
|
+
* A width out of the rail's bounds prints at the nearer bound. */
|
|
346
|
+
maybeWidth: Option.Option<number>;
|
|
147
347
|
/** The rail's panels: a tree, places, filters. A function because a Submodel's viewInputs
|
|
148
348
|
* may hold functions only at the top level, and Foldkit runs this one in the parent's
|
|
149
349
|
* boundary, so the handlers in what it returns dispatch the parent's Messages. */
|
|
150
350
|
toAsideView: () => ReadonlyArray<Html>;
|
|
151
|
-
/** The
|
|
152
|
-
* drawer to print first in it. A function because it receives that button, and
|
|
153
|
-
* parent's boundary like `toAsideView`. */
|
|
351
|
+
/** The page beside the rail, `main.deck#main` or `main.bench#main`, given the button that
|
|
352
|
+
* opens the drawer to print first in it. A function because it receives that button, and
|
|
353
|
+
* runs in the parent's boundary like `toAsideView`. */
|
|
154
354
|
toDeckView: (openButton: Html) => Html;
|
|
155
355
|
}>>;
|
|
156
356
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rail.d.ts","sourceRoot":"","sources":["../../../src/rail/rail.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,MAAM,
|
|
1
|
+
{"version":3,"file":"rail.d.ts","sourceRoot":"","sources":["../../../src/rail/rail.ts"],"names":[],"mappings":"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"}
|
package/dist/src/rail/rail.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { brandViewResult as __foldkitBrandViewResult } from 'foldkit/brand'
|
|
2
|
-
import { Array, Cause, Effect, Option, Schema, Stream } from "effect";
|
|
2
|
+
import { Array, Cause, Effect, Number, Option, Schema, Stream } from "effect";
|
|
3
3
|
import * as Command from "foldkit/command";
|
|
4
4
|
import * as Dom from "foldkit/dom";
|
|
5
5
|
import { defineMessageUnion } from "foldkit/message";
|
|
@@ -7,14 +7,27 @@ import * as Mount from "foldkit/mount";
|
|
|
7
7
|
import * as Render from "foldkit/render";
|
|
8
8
|
import { modifyFields } from "foldkit/struct";
|
|
9
9
|
import { defineView } from "foldkit/submodel";
|
|
10
|
+
import * as Subscription from "foldkit/subscription";
|
|
10
11
|
import * as Button from "../button/button.js";
|
|
12
|
+
import { escapeKeys, markDragging, pointerMessages, splitterAttributes } from "../drag/drag.js";
|
|
11
13
|
import * as IconButton from "../iconButton/iconButton.js";
|
|
14
|
+
import { prefixKeys } from "../subscription/prefixKeys.js";
|
|
12
15
|
// MODEL
|
|
13
|
-
/**
|
|
14
|
-
*
|
|
16
|
+
/** A splitter a pointer drags: pressed at `pressX` on a rail `fromWidth` wide, and the width
|
|
17
|
+
* it previews. */
|
|
18
|
+
const Resizing = Schema.Struct({
|
|
19
|
+
pointerId: Schema.Number,
|
|
20
|
+
pressX: Schema.Number,
|
|
21
|
+
fromWidth: Schema.Number,
|
|
22
|
+
width: Schema.Number,
|
|
23
|
+
});
|
|
24
|
+
/** Schema for a rail: whether it is open as a drawer (at 900px and under; wider, it is always
|
|
25
|
+
* in the page and this stays false), and its splitter while a pointer drags it. Its width is
|
|
26
|
+
* the parent's. */
|
|
15
27
|
export const Model = Schema.Struct({
|
|
16
28
|
id: Schema.String,
|
|
17
29
|
isOpen: Schema.Boolean,
|
|
30
|
+
maybeResizing: Schema.Option(Resizing),
|
|
18
31
|
});
|
|
19
32
|
// MESSAGE
|
|
20
33
|
/** Union of all Messages a rail can produce. `ClosedDrawer` is the browser closing it on
|
|
@@ -22,6 +35,12 @@ export const Model = Schema.Struct({
|
|
|
22
35
|
* the window growing past 900px while it is open, where the rail is back in the page. */
|
|
23
36
|
export const Message = defineMessageUnion({
|
|
24
37
|
ClickedOpen: {},
|
|
38
|
+
PressedSplitter: { pointerId: Schema.Number, clientX: Schema.Number, width: Schema.Number },
|
|
39
|
+
MovedSplitter: { clientX: Schema.Number },
|
|
40
|
+
ReleasedSplitter: { clientX: Schema.Number },
|
|
41
|
+
CancelledSplitter: {},
|
|
42
|
+
PressedEscape: {},
|
|
43
|
+
PressedSplitterKey: { width: Schema.Number },
|
|
25
44
|
ClickedClose: {},
|
|
26
45
|
ClosedDrawer: {},
|
|
27
46
|
BlurredDrawer: {},
|
|
@@ -29,8 +48,27 @@ export const Message = defineMessageUnion({
|
|
|
29
48
|
CompletedShowRailDrawer: {},
|
|
30
49
|
CompletedHideRailDrawer: {},
|
|
31
50
|
});
|
|
32
|
-
/**
|
|
33
|
-
|
|
51
|
+
/** What a rail asks of its parent. `ResizedRail`: its splitter was let go, or stepped by a
|
|
52
|
+
* key, at `width` pixels, within the rail's bounds; the parent keeps it (per client) and
|
|
53
|
+
* passes it back as the view's `maybeWidth`. */
|
|
54
|
+
export const OutMessage = defineMessageUnion({
|
|
55
|
+
ResizedRail: { width: Schema.Number },
|
|
56
|
+
});
|
|
57
|
+
/** Creates a rail, closed, its splitter at rest. */
|
|
58
|
+
export const init = (config) => (__foldkitBrandViewResult(({
|
|
59
|
+
id: config.id,
|
|
60
|
+
isOpen: false,
|
|
61
|
+
maybeResizing: Option.none(),
|
|
62
|
+
}), "@gjermundgaraba-designs/pixel-paper/src/rail/rail.js#init"));
|
|
63
|
+
// WIDTH
|
|
64
|
+
/** The rail's widths, in pixels: before the reader sizes it (as the stylesheet's `--rail` has
|
|
65
|
+
* it, which the splitter says as its value until a width is given), the least its panels
|
|
66
|
+
* still fit in (a tree's row keeps a glyph, a dot and a few words of its title), the most
|
|
67
|
+
* (which leaves the deck at least 421px of a 901px window, the narrowest one the rail stands
|
|
68
|
+
* in, more than a phone has), and what an arrow on its splitter moves it. The bounds and the
|
|
69
|
+
* step are the component's, not tokens: the splitter says them as its values. */
|
|
70
|
+
const WIDTH = { start: 272, least: 220, most: 480, step: 16 };
|
|
71
|
+
const bounded = (width) => __foldkitBrandViewResult((Math.round(Number.clamp(width, { minimum: WIDTH.least, maximum: WIDTH.most }))), "@gjermundgaraba-designs/pixel-paper/src/rail/rail.js#bounded");
|
|
34
72
|
// ACCESSORS
|
|
35
73
|
/** The rail's id, unique in the document. */
|
|
36
74
|
export const id = (model) => __foldkitBrandViewResult((model.id), "@gjermundgaraba-designs/pixel-paper/src/rail/rail.js#id");
|
|
@@ -85,9 +123,35 @@ const open = (model) => (__foldkitBrandViewResult(({
|
|
|
85
123
|
}), "@gjermundgaraba-designs/pixel-paper/src/rail/rail.js#open"));
|
|
86
124
|
/** Closes the rail's drawer, focus back on its button. */
|
|
87
125
|
export const close = (model) => __foldkitBrandViewResult((closeDrawer(model, true)), "@gjermundgaraba-designs/pixel-paper/src/rail/rail.js#close");
|
|
88
|
-
|
|
126
|
+
const withResizing = (model, maybeResizing) => __foldkitBrandViewResult((modifyFields(model, { maybeResizing: () => __foldkitBrandViewResult((maybeResizing), "@gjermundgaraba-designs/pixel-paper/src/rail/rail.js#maybeResizing") })), "@gjermundgaraba-designs/pixel-paper/src/rail/rail.js#withResizing");
|
|
127
|
+
/** The width a dragged splitter previews with the pointer at `clientX`. */
|
|
128
|
+
const dragTo = (model, clientX) => __foldkitBrandViewResult((withResizing(model, Option.map(model.maybeResizing, (resizing) => (__foldkitBrandViewResult(({
|
|
129
|
+
...resizing,
|
|
130
|
+
width: bounded(resizing.fromWidth + clientX - resizing.pressX),
|
|
131
|
+
}), "@gjermundgaraba-designs/pixel-paper/src/rail/rail.js#anonymous~7"))))), "@gjermundgaraba-designs/pixel-paper/src/rail/rail.js#dragTo");
|
|
132
|
+
/** Processes a rail Message and returns the next Model, Commands and OutMessage: a splitter let
|
|
133
|
+
* go where it changes the width, or stepped by a key, asks for the width. */
|
|
89
134
|
export const update = (model, message) => __foldkitBrandViewResult((Message.match(message, {
|
|
90
135
|
ClickedOpen: () => __foldkitBrandViewResult((open(model)), "@gjermundgaraba-designs/pixel-paper/src/rail/rail.js#ClickedOpen"),
|
|
136
|
+
PressedSplitter: ({ pointerId, clientX, width }) => __foldkitBrandViewResult((Option.isSome(model.maybeResizing)
|
|
137
|
+
? { model }
|
|
138
|
+
: {
|
|
139
|
+
model: withResizing(model, Option.some({ pointerId, pressX: clientX, fromWidth: width, width })),
|
|
140
|
+
}), "@gjermundgaraba-designs/pixel-paper/src/rail/rail.js#PressedSplitter"),
|
|
141
|
+
MovedSplitter: ({ clientX }) => (__foldkitBrandViewResult(({ model: dragTo(model, clientX) }), "@gjermundgaraba-designs/pixel-paper/src/rail/rail.js#MovedSplitter")),
|
|
142
|
+
ReleasedSplitter: ({ clientX }) => __foldkitBrandViewResult((Option.match(dragTo(model, clientX).maybeResizing, {
|
|
143
|
+
onNone: () => (__foldkitBrandViewResult(({ model }), "@gjermundgaraba-designs/pixel-paper/src/rail/rail.js#onNone")),
|
|
144
|
+
onSome: ({ fromWidth, width }) => (__foldkitBrandViewResult(({
|
|
145
|
+
model: withResizing(model, Option.none()),
|
|
146
|
+
...(width === fromWidth ? {} : { outMessage: OutMessage.ResizedRail({ width }) }),
|
|
147
|
+
}), "@gjermundgaraba-designs/pixel-paper/src/rail/rail.js#onSome")),
|
|
148
|
+
})), "@gjermundgaraba-designs/pixel-paper/src/rail/rail.js#ReleasedSplitter"),
|
|
149
|
+
CancelledSplitter: () => (__foldkitBrandViewResult(({ model: withResizing(model, Option.none()) }), "@gjermundgaraba-designs/pixel-paper/src/rail/rail.js#CancelledSplitter")),
|
|
150
|
+
PressedEscape: () => (__foldkitBrandViewResult(({ model: withResizing(model, Option.none()) }), "@gjermundgaraba-designs/pixel-paper/src/rail/rail.js#PressedEscape")),
|
|
151
|
+
PressedSplitterKey: ({ width }) => (__foldkitBrandViewResult(({
|
|
152
|
+
model,
|
|
153
|
+
outMessage: OutMessage.ResizedRail({ width: bounded(width) }),
|
|
154
|
+
}), "@gjermundgaraba-designs/pixel-paper/src/rail/rail.js#PressedSplitterKey")),
|
|
91
155
|
ClickedClose: () => __foldkitBrandViewResult((close(model)), "@gjermundgaraba-designs/pixel-paper/src/rail/rail.js#ClickedClose"),
|
|
92
156
|
ClosedDrawer: () => __foldkitBrandViewResult((close(model)), "@gjermundgaraba-designs/pixel-paper/src/rail/rail.js#ClosedDrawer"),
|
|
93
157
|
BlurredDrawer: () => __foldkitBrandViewResult((closeDrawer(model, false)), "@gjermundgaraba-designs/pixel-paper/src/rail/rail.js#BlurredDrawer"),
|
|
@@ -102,10 +166,10 @@ const DRAWER_QUERY = "(max-width: 900px)";
|
|
|
102
166
|
export const widthChangeMessage = (isDrawerWidth, isDrawerOpen) => __foldkitBrandViewResult((!isDrawerWidth && isDrawerOpen ? Option.some(Message.WidenedPastDrawer()) : Option.none()), "@gjermundgaraba-designs/pixel-paper/src/rail/rail.js#widthChangeMessage");
|
|
103
167
|
/** The browser closing the drawer (Escape, a press on the veil); a toggle that opened it says
|
|
104
168
|
* nothing. */
|
|
105
|
-
export const drawerToggleMessage = (event) => __foldkitBrandViewResult((Option.liftPredicate(Message.ClosedDrawer(), () => __foldkitBrandViewResult((event.newState === "closed"), "@gjermundgaraba-designs/pixel-paper/src/rail/rail.js#anonymous~
|
|
169
|
+
export const drawerToggleMessage = (event) => __foldkitBrandViewResult((Option.liftPredicate(Message.ClosedDrawer(), () => __foldkitBrandViewResult((event.newState === "closed"), "@gjermundgaraba-designs/pixel-paper/src/rail/rail.js#anonymous~8"))), "@gjermundgaraba-designs/pixel-paper/src/rail/rail.js#drawerToggleMessage");
|
|
106
170
|
/** Focus leaving the drawer while it is open (`isDrawerOpen`, the rail matching
|
|
107
171
|
* `:popover-open`); focus moving inside it says nothing. */
|
|
108
|
-
export const drawerFocusOutMessage = (rail, event, isDrawerOpen) => __foldkitBrandViewResult((Option.liftPredicate(Message.BlurredDrawer(), () => __foldkitBrandViewResult((isDrawerOpen && event.relatedTarget instanceof Node && !rail.contains(event.relatedTarget)), "@gjermundgaraba-designs/pixel-paper/src/rail/rail.js#anonymous~
|
|
172
|
+
export const drawerFocusOutMessage = (rail, event, isDrawerOpen) => __foldkitBrandViewResult((Option.liftPredicate(Message.BlurredDrawer(), () => __foldkitBrandViewResult((isDrawerOpen && event.relatedTarget instanceof Node && !rail.contains(event.relatedTarget)), "@gjermundgaraba-designs/pixel-paper/src/rail/rail.js#anonymous~9"))), "@gjermundgaraba-designs/pixel-paper/src/rail/rail.js#drawerFocusOutMessage");
|
|
109
173
|
/** Follows the drawer the browser shows: the browser closing it (Escape, a press on the
|
|
110
174
|
* veil), focus leaving it while it is open, and the window growing past its width while it
|
|
111
175
|
* is open, each of which closes the rail. */
|
|
@@ -126,27 +190,61 @@ export const FollowRailDrawer = Mount.defineStream("FollowRailDrawer", {
|
|
|
126
190
|
const fromWidth = Dom.streamFromMediaQuery({
|
|
127
191
|
query: DRAWER_QUERY,
|
|
128
192
|
mapMatches: (isDrawerWidth) => __foldkitBrandViewResult((widthChangeMessage(isDrawerWidth, isDrawerOpen())), "@gjermundgaraba-designs/pixel-paper/src/rail/rail.js#mapMatches"),
|
|
129
|
-
}).pipe(Stream.filter(Option.isSome), Stream.map(({ value }) => __foldkitBrandViewResult((value), "@gjermundgaraba-designs/pixel-paper/src/rail/rail.js#anonymous~
|
|
193
|
+
}).pipe(Stream.filter(Option.isSome), Stream.map(({ value }) => __foldkitBrandViewResult((value), "@gjermundgaraba-designs/pixel-paper/src/rail/rail.js#anonymous~10")));
|
|
130
194
|
return __foldkitBrandViewResult((Stream.mergeAll([fromToggle, fromFocusOut, fromWidth], {
|
|
131
195
|
concurrency: "unbounded",
|
|
132
196
|
})), "@gjermundgaraba-designs/pixel-paper/src/rail/rail.js#execute~3");
|
|
133
197
|
},
|
|
134
198
|
});
|
|
199
|
+
// SUBSCRIPTION
|
|
200
|
+
const railSubscriptions = Subscription.make()((entry) => (__foldkitBrandViewResult(({
|
|
201
|
+
resize: entry({ maybePointerId: Schema.Option(Schema.Number) }, {
|
|
202
|
+
modelToDependencies: (model) => (__foldkitBrandViewResult(({
|
|
203
|
+
maybePointerId: Option.map(model.maybeResizing, ({ pointerId }) => __foldkitBrandViewResult((pointerId), "@gjermundgaraba-designs/pixel-paper/src/rail/rail.js#anonymous~12")),
|
|
204
|
+
}), "@gjermundgaraba-designs/pixel-paper/src/rail/rail.js#modelToDependencies")),
|
|
205
|
+
dependenciesToStream: ({ maybePointerId }) => __foldkitBrandViewResult((Option.match(maybePointerId, {
|
|
206
|
+
onNone: () => __foldkitBrandViewResult((Stream.empty), "@gjermundgaraba-designs/pixel-paper/src/rail/rail.js#onNone~2"),
|
|
207
|
+
onSome: (pointerId) => __foldkitBrandViewResult((Stream.merge(pointerMessages(pointerId, {
|
|
208
|
+
moved: ({ clientX }) => __foldkitBrandViewResult((Message.MovedSplitter({ clientX })), "@gjermundgaraba-designs/pixel-paper/src/rail/rail.js#moved"),
|
|
209
|
+
released: ({ clientX }) => __foldkitBrandViewResult((Message.ReleasedSplitter({ clientX })), "@gjermundgaraba-designs/pixel-paper/src/rail/rail.js#released"),
|
|
210
|
+
cancelled: () => __foldkitBrandViewResult((Message.CancelledSplitter()), "@gjermundgaraba-designs/pixel-paper/src/rail/rail.js#cancelled"),
|
|
211
|
+
}), markDragging)), "@gjermundgaraba-designs/pixel-paper/src/rail/rail.js#onSome~2"),
|
|
212
|
+
})), "@gjermundgaraba-designs/pixel-paper/src/rail/rail.js#dependenciesToStream"),
|
|
213
|
+
}),
|
|
214
|
+
escape: entry({ isResizing: Schema.Boolean }, {
|
|
215
|
+
modelToDependencies: (model) => (__foldkitBrandViewResult(({ isResizing: Option.isSome(model.maybeResizing) }), "@gjermundgaraba-designs/pixel-paper/src/rail/rail.js#modelToDependencies~2")),
|
|
216
|
+
dependenciesToStream: ({ isResizing }) => __foldkitBrandViewResult((isResizing ? escapeKeys(Message.PressedEscape()) : Stream.empty), "@gjermundgaraba-designs/pixel-paper/src/rail/rail.js#dependenciesToStream~2"),
|
|
217
|
+
}),
|
|
218
|
+
}), "@gjermundgaraba-designs/pixel-paper/src/rail/rail.js#anonymous~11")));
|
|
219
|
+
/** A dragged splitter follows the pointer, and Escape puts it back before a dialog or the
|
|
220
|
+
* page sees it, from listeners that run only while it is dragged. Lift them into the
|
|
221
|
+
* application's Subscriptions behind a key prefix of the parent's: `subscriptions("rail")` is
|
|
222
|
+
* keyed `railResize` and `railEscape`. */
|
|
223
|
+
export const subscriptions = (keyPrefix) => __foldkitBrandViewResult((prefixKeys(keyPrefix, railSubscriptions)), "@gjermundgaraba-designs/pixel-paper/src/rail/rail.js#subscriptions");
|
|
135
224
|
/**
|
|
136
225
|
* A column of panels beside the deck, fixed under the top bar and scrolling itself:
|
|
137
|
-
* `div.railed >` the deck, then `aside.rail[popover="auto"][aria-label]
|
|
138
|
-
*
|
|
139
|
-
*
|
|
140
|
-
*
|
|
226
|
+
* `div.railed >` the deck, then `aside.rail[popover="auto"][aria-label]`, then its splitter,
|
|
227
|
+
* `div.rail-resize[role="separator"]`, on its right edge. One element serves both layouts, so
|
|
228
|
+
* nothing in it renders twice or loses its state. At 900px and under it leaves the page, and
|
|
229
|
+
* `span.rail-open > button.btn.small` at the top of the deck opens the same element as a drawer
|
|
230
|
+
* over a veil, its head (the name and a close glyph) showing. Opening focuses its first
|
|
141
231
|
* control; Escape, a press on the veil, the close glyph, focus leaving or the window growing
|
|
142
232
|
* past 900px closes it, and the first three put focus back on the button.
|
|
143
233
|
*
|
|
234
|
+
* Its splitter sizes it, by a pointer (previewed as it moves) or the side arrows, within its
|
|
235
|
+
* bounds, and reports the width as `ResizedRail` for the parent to keep and pass back as
|
|
236
|
+
* `maybeWidth`, which the view sets as `--rail` on `div.railed`, so the page's padding and the
|
|
237
|
+
* rail's width follow it. The drawer keeps its own width. Lift `subscriptions(keyPrefix)` into
|
|
238
|
+
* the application's, or a dragged splitter follows nothing.
|
|
239
|
+
*
|
|
144
240
|
* Its state is its own, not `@foldkit/ui`'s Popover: that panel is placed by Floating UI and
|
|
145
241
|
* rendered only while open, and this one is always in the page, placed by the stylesheet, and
|
|
146
242
|
* opened as a native popover so the browser keeps it in the top layer.
|
|
147
243
|
*/
|
|
148
244
|
export const view = defineView((model, viewInputs, h) => {
|
|
149
245
|
const { label, toAsideView, toDeckView } = viewInputs;
|
|
246
|
+
const maybeWidth = Option.orElse(Option.map(model.maybeResizing, ({ width }) => __foldkitBrandViewResult((width), "@gjermundgaraba-designs/pixel-paper/src/rail/rail.js#anonymous~14")), () => __foldkitBrandViewResult((Option.map(viewInputs.maybeWidth, bounded)), "@gjermundgaraba-designs/pixel-paper/src/rail/rail.js#anonymous~15"));
|
|
247
|
+
const width = Option.getOrElse(maybeWidth, () => __foldkitBrandViewResult((WIDTH.start), "@gjermundgaraba-designs/pixel-paper/src/rail/rail.js#anonymous~16"));
|
|
150
248
|
const openButton = h.span([h.Class("rail-open")], [
|
|
151
249
|
Button.view({
|
|
152
250
|
label,
|
|
@@ -162,7 +260,10 @@ export const view = defineView((model, viewInputs, h) => {
|
|
|
162
260
|
]);
|
|
163
261
|
// NOTE: the deck comes first so the page's main content, and its h1, precede the rail's
|
|
164
262
|
// panels in reading order; the stylesheet places the rail, fixed, at the left.
|
|
165
|
-
return __foldkitBrandViewResult((h.div([
|
|
263
|
+
return __foldkitBrandViewResult((h.div([
|
|
264
|
+
h.Class("railed"),
|
|
265
|
+
...Array.fromOption(Option.map(maybeWidth, (shown) => __foldkitBrandViewResult((h.Style({ "--rail": `${shown}px` })), "@gjermundgaraba-designs/pixel-paper/src/rail/rail.js#anonymous~17"))),
|
|
266
|
+
], [
|
|
166
267
|
toDeckView(openButton),
|
|
167
268
|
h.aside([
|
|
168
269
|
h.Id(model.id),
|
|
@@ -177,5 +278,22 @@ export const view = defineView((model, viewInputs, h) => {
|
|
|
177
278
|
]),
|
|
178
279
|
...toAsideView(),
|
|
179
280
|
]),
|
|
180
|
-
|
|
281
|
+
h.div([
|
|
282
|
+
h.Class("rail-resize"),
|
|
283
|
+
h.Role("separator"),
|
|
284
|
+
h.AriaLabel(`Width of ${label}`),
|
|
285
|
+
h.AriaControls(model.id),
|
|
286
|
+
h.AriaValuemin(WIDTH.least),
|
|
287
|
+
h.AriaValuemax(WIDTH.most),
|
|
288
|
+
h.AriaValuenow(width),
|
|
289
|
+
h.AriaValuetext(`${width} pixels`),
|
|
290
|
+
h.Tabindex(0),
|
|
291
|
+
...splitterAttributes({
|
|
292
|
+
orientation: "vertical",
|
|
293
|
+
isIdle: Option.isNone(model.maybeResizing),
|
|
294
|
+
onPress: (pointerId, clientX) => __foldkitBrandViewResult((Message.PressedSplitter({ pointerId, clientX, width })), "@gjermundgaraba-designs/pixel-paper/src/rail/rail.js#onPress"),
|
|
295
|
+
onStep: (direction) => __foldkitBrandViewResult((Message.PressedSplitterKey({ width: bounded(width + direction * WIDTH.step) })), "@gjermundgaraba-designs/pixel-paper/src/rail/rail.js#onStep"),
|
|
296
|
+
}, h),
|
|
297
|
+
]),
|
|
298
|
+
])), "@gjermundgaraba-designs/pixel-paper/src/rail/rail.js#anonymous~13");
|
|
181
299
|
});
|
package/dist/src/reel/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { Layout, OutMessage, Pane, apply } from "./layout.ts";
|
|
2
|
-
export { Action, AnnounceReel,
|
|
2
|
+
export { Action, AnnounceReel, FocusPane, Message, Model, RestoreFocus, ScrollIntoView, SizeLiftedPane, focusedPaneId, init, perform, reconcile, subscriptions, update, view, } from "./reel.ts";
|
|
3
3
|
export type { InitConfig, PaneRender, UpdateContext, ViewInputs } from "./reel.ts";
|
|
4
4
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/reel/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAC9D,OAAO,EACL,MAAM,EACN,YAAY,EACZ,SAAS,EACT,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/reel/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAC9D,OAAO,EACL,MAAM,EACN,YAAY,EACZ,SAAS,EACT,OAAO,EACP,KAAK,EACL,YAAY,EACZ,cAAc,EACd,cAAc,EACd,aAAa,EACb,IAAI,EACJ,OAAO,EACP,SAAS,EACT,aAAa,EACb,MAAM,EACN,IAAI,GACL,MAAM,WAAW,CAAC;AACnB,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC"}
|
package/dist/src/reel/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export { Layout, OutMessage, Pane, apply } from "./layout.js";
|
|
2
|
-
export { Action, AnnounceReel,
|
|
2
|
+
export { Action, AnnounceReel, FocusPane, Message, Model, RestoreFocus, ScrollIntoView, SizeLiftedPane, focusedPaneId, init, perform, reconcile, subscriptions, update, view, } from "./reel.js";
|