@k2b/ui 0.32.0 → 0.33.0
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/browser/actions/Dropdown.js +159 -99
- package/dist/browser/actions/Dropdown.js.map +1 -1
- package/dist/browser/actions/FilterChip.js +113 -56
- package/dist/browser/actions/FilterChip.js.map +1 -1
- package/dist/browser/actions/filter-messages.js +26 -2
- package/dist/browser/actions/filter-messages.js.map +1 -1
- package/dist/browser/actions/menu-rows.js +23 -3
- package/dist/browser/actions/menu-rows.js.map +1 -1
- package/dist/browser/actions/menu-sheet.js +2 -7
- package/dist/browser/actions/menu-sheet.js.map +1 -1
- package/dist/browser/chat/ChatComposer.js +480 -403
- package/dist/browser/chat/ChatComposer.js.map +1 -1
- package/dist/browser/chat/chat-messages.js +14 -0
- package/dist/browser/chat/chat-messages.js.map +1 -1
- package/dist/browser/chat/index.js.map +1 -1
- package/dist/browser/content/Calendar.js +39 -29
- package/dist/browser/content/Calendar.js.map +1 -1
- package/dist/browser/content/CalendarDayView.js +159 -165
- package/dist/browser/content/CalendarDayView.js.map +1 -1
- package/dist/browser/content/MessageRow.js +607 -343
- package/dist/browser/content/MessageRow.js.map +1 -1
- package/dist/browser/content/ReactionBar.js +17 -0
- package/dist/browser/content/ReactionBar.js.map +1 -1
- package/dist/browser/content/index.js +1 -1
- package/dist/browser/content/index.js.map +1 -1
- package/dist/browser/feedback/dialog-core.js +6 -0
- package/dist/browser/feedback/dialog-core.js.map +1 -1
- package/dist/browser/inputs/TextInput.js +4 -1
- package/dist/browser/inputs/TextInput.js.map +1 -1
- package/dist/browser/intl/shortcut-messages.js +4 -0
- package/dist/browser/intl/shortcut-messages.js.map +1 -1
- package/dist/browser/intl/shortcut.js +4 -0
- package/dist/browser/intl/shortcut.js.map +1 -1
- package/dist/browser/layout/AppWorkspace.js +529 -512
- package/dist/browser/layout/AppWorkspace.js.map +1 -1
- package/dist/browser/layout/MobileShell.js +213 -38
- package/dist/browser/layout/MobileShell.js.map +1 -1
- package/dist/browser/layout/index.js +1 -0
- package/dist/browser/layout/index.js.map +1 -1
- package/dist/browser/layout/scroll-fade.js +32 -5
- package/dist/browser/layout/scroll-fade.js.map +1 -1
- package/dist/browser/surfaces/NoticeCard.js +46 -30
- package/dist/browser/surfaces/NoticeCard.js.map +1 -1
- package/dist/browser/surfaces/resource-messages.js +2 -2
- package/dist/browser/surfaces/resource-messages.js.map +1 -1
- package/dist/ssr/actions/Dropdown.js +51 -27
- package/dist/ssr/actions/Dropdown.js.map +1 -1
- package/dist/ssr/actions/FilterChip.js +67 -16
- package/dist/ssr/actions/FilterChip.js.map +1 -1
- package/dist/ssr/actions/filter-messages.js +26 -2
- package/dist/ssr/actions/filter-messages.js.map +1 -1
- package/dist/ssr/actions/menu-rows.js +23 -3
- package/dist/ssr/actions/menu-rows.js.map +1 -1
- package/dist/ssr/actions/menu-sheet.js +2 -7
- package/dist/ssr/actions/menu-sheet.js.map +1 -1
- package/dist/ssr/chat/ChatComposer.js +96 -67
- package/dist/ssr/chat/ChatComposer.js.map +1 -1
- package/dist/ssr/chat/chat-messages.js +14 -0
- package/dist/ssr/chat/chat-messages.js.map +1 -1
- package/dist/ssr/chat/index.js.map +1 -1
- package/dist/ssr/content/Calendar.js +40 -31
- package/dist/ssr/content/Calendar.js.map +1 -1
- package/dist/ssr/content/CalendarDayView.js +40 -48
- package/dist/ssr/content/CalendarDayView.js.map +1 -1
- package/dist/ssr/content/MessageRow.js +264 -91
- package/dist/ssr/content/MessageRow.js.map +1 -1
- package/dist/ssr/content/ReactionBar.js +17 -0
- package/dist/ssr/content/ReactionBar.js.map +1 -1
- package/dist/ssr/content/index.js +1 -1
- package/dist/ssr/content/index.js.map +1 -1
- package/dist/ssr/feedback/dialog-core.js +6 -0
- package/dist/ssr/feedback/dialog-core.js.map +1 -1
- package/dist/ssr/inputs/TextInput.js +4 -1
- package/dist/ssr/inputs/TextInput.js.map +1 -1
- package/dist/ssr/intl/shortcut-messages.js +4 -0
- package/dist/ssr/intl/shortcut-messages.js.map +1 -1
- package/dist/ssr/intl/shortcut.js +4 -0
- package/dist/ssr/intl/shortcut.js.map +1 -1
- package/dist/ssr/layout/AppWorkspace.js +134 -122
- package/dist/ssr/layout/AppWorkspace.js.map +1 -1
- package/dist/ssr/layout/MobileShell.js +100 -20
- package/dist/ssr/layout/MobileShell.js.map +1 -1
- package/dist/ssr/layout/index.js +1 -0
- package/dist/ssr/layout/index.js.map +1 -1
- package/dist/ssr/layout/scroll-fade.js +32 -5
- package/dist/ssr/layout/scroll-fade.js.map +1 -1
- package/dist/ssr/surfaces/NoticeCard.js +21 -12
- package/dist/ssr/surfaces/NoticeCard.js.map +1 -1
- package/dist/ssr/surfaces/resource-messages.js +2 -2
- package/dist/ssr/surfaces/resource-messages.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/types/actions/Dropdown.d.ts +14 -0
- package/dist/types/actions/FilterChip.d.ts +11 -0
- package/dist/types/actions/filter-messages.d.ts +12 -0
- package/dist/types/actions/menu-rows.d.ts +7 -2
- package/dist/types/chat/ChatComposer.d.ts +13 -0
- package/dist/types/chat/chat-messages.d.ts +7 -0
- package/dist/types/chat/index.d.ts +1 -1
- package/dist/types/content/Calendar.d.ts +7 -0
- package/dist/types/content/MessageRow.d.ts +64 -2
- package/dist/types/content/index.d.ts +2 -2
- package/dist/types/feedback/dialog-core.d.ts +3 -0
- package/dist/types/intl/shortcut-messages.d.ts +2 -0
- package/dist/types/layout/AppWorkspace.d.ts +2 -0
- package/dist/types/layout/MobileShell.d.ts +52 -5
- package/dist/types/layout/index.d.ts +2 -1
- package/dist/types/layout/scroll-fade.d.ts +5 -0
- package/dist/types/surfaces/NoticeCard.d.ts +3 -0
- package/package.json +2 -2
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { template as _$template } from "solid-js/web";
|
|
2
|
+
import { memo as _$memo } from "solid-js/web";
|
|
3
|
+
import { setAttribute as _$setAttribute } from "solid-js/web";
|
|
2
4
|
import { className as _$className } from "solid-js/web";
|
|
3
5
|
import { effect as _$effect } from "solid-js/web";
|
|
4
6
|
import { getNextElement as _$getNextElement } from "solid-js/web";
|
|
@@ -6,11 +8,21 @@ import { getNextMarker as _$getNextMarker } from "solid-js/web";
|
|
|
6
8
|
import { insert as _$insert } from "solid-js/web";
|
|
7
9
|
import { createComponent as _$createComponent } from "solid-js/web";
|
|
8
10
|
import { use as _$use } from "solid-js/web";
|
|
9
|
-
var _tmpl$ = /*#__PURE__*/_$template(`<div
|
|
10
|
-
_tmpl$2 = /*#__PURE__*/_$template(`<
|
|
11
|
-
_tmpl$3 = /*#__PURE__*/_$template(`<
|
|
12
|
-
_tmpl$4 = /*#__PURE__*/_$template(`<
|
|
13
|
-
|
|
11
|
+
var _tmpl$ = /*#__PURE__*/_$template(`<div><!$><!/><!$><!/><main class=k2b-mobile-shell__main></main><!$><!/>`),
|
|
12
|
+
_tmpl$2 = /*#__PURE__*/_$template(`<span class=k2b-mobile-shell__title-narrow>`),
|
|
13
|
+
_tmpl$3 = /*#__PURE__*/_$template(`<span class=k2b-mobile-shell__title-wide>`),
|
|
14
|
+
_tmpl$4 = /*#__PURE__*/_$template(`<div class=k2b-mobile-shell__actions>`),
|
|
15
|
+
_tmpl$5 = /*#__PURE__*/_$template(`<header class=k2b-mobile-shell__header><!$><!/><h1 class=k2b-mobile-shell__title></h1><!$><!/>`),
|
|
16
|
+
_tmpl$6 = /*#__PURE__*/_$template(`<i class="ti ti-chevron-left"aria-hidden=true>`),
|
|
17
|
+
_tmpl$7 = /*#__PURE__*/_$template(`<a><i aria-hidden=true></i><span class=k2b-truncate-fade></span><!$><!/>`),
|
|
18
|
+
_tmpl$8 = /*#__PURE__*/_$template(`<span class=k2b-mobile-shell__sidebar-count>`),
|
|
19
|
+
_tmpl$9 = /*#__PURE__*/_$template(`<ul>`),
|
|
20
|
+
_tmpl$0 = /*#__PURE__*/_$template(`<li>`),
|
|
21
|
+
_tmpl$1 = /*#__PURE__*/_$template(`<div class=k2b-mobile-shell__sidebar-foot>`),
|
|
22
|
+
_tmpl$10 = /*#__PURE__*/_$template(`<nav class=k2b-mobile-shell__sidebar><div class=k2b-mobile-shell__sidebar-head><!$><!/><span class=k2b-truncate-fade></span></div><div class=k2b-mobile-shell__sidebar-body><!$><!/><!$><!/></div><!$><!/>`),
|
|
23
|
+
_tmpl$11 = /*#__PURE__*/_$template(`<img alt width=32 height=32>`),
|
|
24
|
+
_tmpl$12 = /*#__PURE__*/_$template(`<section><h2></h2><!$><!/>`);
|
|
25
|
+
import { For, onCleanup, onMount, Show } from "solid-js";
|
|
14
26
|
import { IconButton, IconButtonLink } from "../actions/Button";
|
|
15
27
|
import ScrollArea from "./ScrollArea";
|
|
16
28
|
import { installScrollFades } from "./scroll-fade";
|
|
@@ -151,15 +163,16 @@ const observeLinkTaps = root => {
|
|
|
151
163
|
export function observeMobileShell(root) {
|
|
152
164
|
const main = root.querySelector(":scope > .k2b-mobile-shell__main");
|
|
153
165
|
const body = main?.querySelector(":scope > .k2b-mobile-shell__body");
|
|
154
|
-
if (!main
|
|
166
|
+
if (!main) return () => {};
|
|
155
167
|
const stopLinkTaps = observeLinkTaps(root);
|
|
156
|
-
|
|
168
|
+
// Content with its own scroll areas keeps its own fades; the room a toast takes applies to the whole main area.
|
|
169
|
+
const stopScrollFades = body ? installScrollFades(body) : () => {};
|
|
157
170
|
let frame = 0;
|
|
158
171
|
const measure = () => {
|
|
159
172
|
frame = 0;
|
|
160
173
|
const footer = Math.max(0, root.getBoundingClientRect().bottom - main.getBoundingClientRect().bottom);
|
|
161
174
|
document.body.style.setProperty(FOOTER_HEIGHT, `${footer}px`);
|
|
162
|
-
root.style.setProperty(TOAST_INSET, `${persistentToastInset(body)}px`);
|
|
175
|
+
root.style.setProperty(TOAST_INSET, `${persistentToastInset(body ?? main)}px`);
|
|
163
176
|
};
|
|
164
177
|
const schedule = () => {
|
|
165
178
|
if (!frame) frame = requestAnimationFrame(measure);
|
|
@@ -195,32 +208,54 @@ function MobileShellRoot(props) {
|
|
|
195
208
|
var _el$ = _$getNextElement(_tmpl$),
|
|
196
209
|
_el$3 = _el$.firstChild,
|
|
197
210
|
[_el$4, _co$] = _$getNextMarker(_el$3.nextSibling),
|
|
198
|
-
_el$
|
|
199
|
-
_el$
|
|
200
|
-
|
|
211
|
+
_el$5 = _el$4.nextSibling,
|
|
212
|
+
[_el$6, _co$2] = _$getNextMarker(_el$5.nextSibling),
|
|
213
|
+
_el$2 = _el$6.nextSibling,
|
|
214
|
+
_el$7 = _el$2.nextSibling,
|
|
215
|
+
[_el$8, _co$3] = _$getNextMarker(_el$7.nextSibling);
|
|
201
216
|
var _ref$ = root;
|
|
202
217
|
typeof _ref$ === "function" ? _$use(_ref$, _el$) : root = _el$;
|
|
203
|
-
_$insert(_el$, () => props.
|
|
204
|
-
_$insert(_el
|
|
205
|
-
|
|
206
|
-
get
|
|
218
|
+
_$insert(_el$, () => props.sidebar, _el$4, _co$);
|
|
219
|
+
_$insert(_el$, () => props.header, _el$6, _co$2);
|
|
220
|
+
_$insert(_el$2, _$createComponent(Show, {
|
|
221
|
+
get when() {
|
|
222
|
+
return props.scroll !== false;
|
|
223
|
+
},
|
|
224
|
+
get fallback() {
|
|
207
225
|
return props.children;
|
|
226
|
+
},
|
|
227
|
+
get children() {
|
|
228
|
+
return _$createComponent(ScrollArea, {
|
|
229
|
+
"class": "k2b-mobile-shell__body",
|
|
230
|
+
get children() {
|
|
231
|
+
return props.children;
|
|
232
|
+
}
|
|
233
|
+
});
|
|
208
234
|
}
|
|
209
235
|
}));
|
|
210
|
-
_$insert(_el$, () => props.footer, _el$
|
|
211
|
-
_$effect(
|
|
236
|
+
_$insert(_el$, () => props.footer, _el$8, _co$3);
|
|
237
|
+
_$effect(_p$ => {
|
|
238
|
+
var _v$ = props.class ? `k2b-mobile-shell ${props.class}` : "k2b-mobile-shell",
|
|
239
|
+
_v$2 = props.scroll === false ? "" : undefined;
|
|
240
|
+
_v$ !== _p$.e && _$className(_el$, _p$.e = _v$);
|
|
241
|
+
_v$2 !== _p$.t && _$setAttribute(_el$, "data-k2b-content-heads", _p$.t = _v$2);
|
|
242
|
+
return _p$;
|
|
243
|
+
}, {
|
|
244
|
+
e: undefined,
|
|
245
|
+
t: undefined
|
|
246
|
+
});
|
|
212
247
|
return _el$;
|
|
213
248
|
})();
|
|
214
249
|
}
|
|
215
250
|
function MobileShellHeader(props) {
|
|
216
251
|
return (() => {
|
|
217
|
-
var _el$
|
|
218
|
-
_el$
|
|
219
|
-
[_el$
|
|
220
|
-
_el$
|
|
221
|
-
_el$
|
|
222
|
-
[_el$
|
|
223
|
-
_$insert(_el$
|
|
252
|
+
var _el$9 = _$getNextElement(_tmpl$5),
|
|
253
|
+
_el$12 = _el$9.firstChild,
|
|
254
|
+
[_el$13, _co$4] = _$getNextMarker(_el$12.nextSibling),
|
|
255
|
+
_el$0 = _el$13.nextSibling,
|
|
256
|
+
_el$14 = _el$0.nextSibling,
|
|
257
|
+
[_el$15, _co$5] = _$getNextMarker(_el$14.nextSibling);
|
|
258
|
+
_$insert(_el$9, _$createComponent(Show, {
|
|
224
259
|
get when() {
|
|
225
260
|
return props.back;
|
|
226
261
|
},
|
|
@@ -231,18 +266,24 @@ function MobileShellHeader(props) {
|
|
|
231
266
|
get fallback() {
|
|
232
267
|
return _$createComponent(IconButton, {
|
|
233
268
|
"class": "k2b-mobile-shell__back",
|
|
269
|
+
get ["data-with-sidebar"]() {
|
|
270
|
+
return back().withSidebar === false ? "false" : undefined;
|
|
271
|
+
},
|
|
234
272
|
get label() {
|
|
235
273
|
return back().label;
|
|
236
274
|
},
|
|
237
275
|
tooltip: false,
|
|
238
276
|
onClick: () => back().onClick?.(),
|
|
239
277
|
get children() {
|
|
240
|
-
return _$getNextElement(_tmpl$
|
|
278
|
+
return _$getNextElement(_tmpl$6);
|
|
241
279
|
}
|
|
242
280
|
});
|
|
243
281
|
},
|
|
244
282
|
children: href => _$createComponent(IconButtonLink, {
|
|
245
283
|
"class": "k2b-mobile-shell__back",
|
|
284
|
+
get ["data-with-sidebar"]() {
|
|
285
|
+
return back().withSidebar === false ? "false" : undefined;
|
|
286
|
+
},
|
|
246
287
|
get href() {
|
|
247
288
|
return href();
|
|
248
289
|
},
|
|
@@ -252,33 +293,167 @@ function MobileShellHeader(props) {
|
|
|
252
293
|
tooltip: false,
|
|
253
294
|
onClick: () => back().onClick?.(),
|
|
254
295
|
get children() {
|
|
255
|
-
return _$getNextElement(_tmpl$
|
|
296
|
+
return _$getNextElement(_tmpl$6);
|
|
256
297
|
}
|
|
257
298
|
})
|
|
258
299
|
})
|
|
259
|
-
}), _el$
|
|
260
|
-
_$insert(_el$
|
|
261
|
-
|
|
300
|
+
}), _el$13, _co$4);
|
|
301
|
+
_$insert(_el$0, _$createComponent(Show, {
|
|
302
|
+
get when() {
|
|
303
|
+
return _$memo(() => props.sidebarTitle !== undefined)() && props.sidebarTitle !== props.title;
|
|
304
|
+
},
|
|
305
|
+
get fallback() {
|
|
306
|
+
return props.title;
|
|
307
|
+
},
|
|
308
|
+
get children() {
|
|
309
|
+
return [(() => {
|
|
310
|
+
var _el$1 = _$getNextElement(_tmpl$2);
|
|
311
|
+
_$insert(_el$1, () => props.title);
|
|
312
|
+
return _el$1;
|
|
313
|
+
})(), (() => {
|
|
314
|
+
var _el$10 = _$getNextElement(_tmpl$3);
|
|
315
|
+
_$insert(_el$10, () => props.sidebarTitle);
|
|
316
|
+
return _el$10;
|
|
317
|
+
})()];
|
|
318
|
+
}
|
|
319
|
+
}));
|
|
320
|
+
_$insert(_el$9, _$createComponent(Show, {
|
|
262
321
|
get when() {
|
|
263
322
|
return props.actions;
|
|
264
323
|
},
|
|
265
324
|
get children() {
|
|
266
|
-
var _el$
|
|
267
|
-
_$insert(_el$
|
|
268
|
-
return _el$
|
|
325
|
+
var _el$11 = _$getNextElement(_tmpl$4);
|
|
326
|
+
_$insert(_el$11, () => props.actions);
|
|
327
|
+
return _el$11;
|
|
328
|
+
}
|
|
329
|
+
}), _el$15, _co$5);
|
|
330
|
+
return _el$9;
|
|
331
|
+
})();
|
|
332
|
+
}
|
|
333
|
+
function SidebarLink(props) {
|
|
334
|
+
return (() => {
|
|
335
|
+
var _el$18 = _$getNextElement(_tmpl$7),
|
|
336
|
+
_el$19 = _el$18.firstChild,
|
|
337
|
+
_el$20 = _el$19.nextSibling,
|
|
338
|
+
_el$21 = _el$20.nextSibling,
|
|
339
|
+
[_el$22, _co$6] = _$getNextMarker(_el$21.nextSibling);
|
|
340
|
+
_$insert(_el$20, () => props.item.label);
|
|
341
|
+
_$insert(_el$18, _$createComponent(Show, {
|
|
342
|
+
get when() {
|
|
343
|
+
return props.item.count;
|
|
344
|
+
},
|
|
345
|
+
children: count => (() => {
|
|
346
|
+
var _el$23 = _$getNextElement(_tmpl$8);
|
|
347
|
+
_$insert(_el$23, count);
|
|
348
|
+
return _el$23;
|
|
349
|
+
})()
|
|
350
|
+
}), _el$22, _co$6);
|
|
351
|
+
_$effect(_p$ => {
|
|
352
|
+
var _v$3 = props.item.href,
|
|
353
|
+
_v$4 = props.item.current ? "page" : undefined,
|
|
354
|
+
_v$5 = props.item.id,
|
|
355
|
+
_v$6 = props.item.title ?? props.item.label,
|
|
356
|
+
_v$7 = props.item.icon;
|
|
357
|
+
_v$3 !== _p$.e && _$setAttribute(_el$18, "href", _p$.e = _v$3);
|
|
358
|
+
_v$4 !== _p$.t && _$setAttribute(_el$18, "aria-current", _p$.t = _v$4);
|
|
359
|
+
_v$5 !== _p$.a && _$setAttribute(_el$18, "data-tab", _p$.a = _v$5);
|
|
360
|
+
_v$6 !== _p$.o && _$setAttribute(_el$18, "data-k2b-title", _p$.o = _v$6);
|
|
361
|
+
_v$7 !== _p$.i && _$className(_el$19, _p$.i = _v$7);
|
|
362
|
+
return _p$;
|
|
363
|
+
}, {
|
|
364
|
+
e: undefined,
|
|
365
|
+
t: undefined,
|
|
366
|
+
a: undefined,
|
|
367
|
+
o: undefined,
|
|
368
|
+
i: undefined
|
|
369
|
+
});
|
|
370
|
+
return _el$18;
|
|
371
|
+
})();
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
/**
|
|
375
|
+
* The navigation of a touch app on a wide screen, in `MobileShell`'s `sidebar`: the app's name, then its destinations
|
|
376
|
+
* as 44 px rows with icon and label, the open one in the action colour. A press shows the item's page frame at once,
|
|
377
|
+
* as on a tab, and the row of a loading page pulses.
|
|
378
|
+
*/
|
|
379
|
+
function MobileShellSidebar(props) {
|
|
380
|
+
const list = items => (() => {
|
|
381
|
+
var _el$24 = _$getNextElement(_tmpl$9);
|
|
382
|
+
_$insert(_el$24, _$createComponent(For, {
|
|
383
|
+
each: items,
|
|
384
|
+
children: item => (() => {
|
|
385
|
+
var _el$25 = _$getNextElement(_tmpl$0);
|
|
386
|
+
_$insert(_el$25, _$createComponent(SidebarLink, {
|
|
387
|
+
item: item
|
|
388
|
+
}));
|
|
389
|
+
return _el$25;
|
|
390
|
+
})()
|
|
391
|
+
}));
|
|
392
|
+
return _el$24;
|
|
393
|
+
})();
|
|
394
|
+
return (() => {
|
|
395
|
+
var _el$26 = _$getNextElement(_tmpl$10),
|
|
396
|
+
_el$27 = _el$26.firstChild,
|
|
397
|
+
_el$29 = _el$27.firstChild,
|
|
398
|
+
[_el$30, _co$7] = _$getNextMarker(_el$29.nextSibling),
|
|
399
|
+
_el$28 = _el$30.nextSibling,
|
|
400
|
+
_el$31 = _el$27.nextSibling,
|
|
401
|
+
_el$32 = _el$31.firstChild,
|
|
402
|
+
[_el$33, _co$8] = _$getNextMarker(_el$32.nextSibling),
|
|
403
|
+
_el$34 = _el$33.nextSibling,
|
|
404
|
+
[_el$35, _co$9] = _$getNextMarker(_el$34.nextSibling),
|
|
405
|
+
_el$37 = _el$31.nextSibling,
|
|
406
|
+
[_el$38, _co$0] = _$getNextMarker(_el$37.nextSibling);
|
|
407
|
+
_$insert(_el$27, _$createComponent(Show, {
|
|
408
|
+
get when() {
|
|
409
|
+
return props.logo;
|
|
410
|
+
},
|
|
411
|
+
children: logo => (() => {
|
|
412
|
+
var _el$39 = _$getNextElement(_tmpl$11);
|
|
413
|
+
_$effect(() => _$setAttribute(_el$39, "src", logo()));
|
|
414
|
+
return _el$39;
|
|
415
|
+
})()
|
|
416
|
+
}), _el$30, _co$7);
|
|
417
|
+
_$insert(_el$28, () => props.title);
|
|
418
|
+
_$insert(_el$31, () => list(props.items), _el$33, _co$8);
|
|
419
|
+
_$insert(_el$31, _$createComponent(For, {
|
|
420
|
+
get each() {
|
|
421
|
+
return (props.sections ?? []).filter(section => section.items.length > 0);
|
|
422
|
+
},
|
|
423
|
+
children: section => (() => {
|
|
424
|
+
var _el$40 = _$getNextElement(_tmpl$12),
|
|
425
|
+
_el$41 = _el$40.firstChild,
|
|
426
|
+
_el$42 = _el$41.nextSibling,
|
|
427
|
+
[_el$43, _co$1] = _$getNextMarker(_el$42.nextSibling);
|
|
428
|
+
_$insert(_el$41, () => section.title);
|
|
429
|
+
_$insert(_el$40, () => list(section.items), _el$43, _co$1);
|
|
430
|
+
return _el$40;
|
|
431
|
+
})()
|
|
432
|
+
}), _el$35, _co$9);
|
|
433
|
+
_$insert(_el$26, _$createComponent(Show, {
|
|
434
|
+
get when() {
|
|
435
|
+
return props.footer?.length;
|
|
436
|
+
},
|
|
437
|
+
get children() {
|
|
438
|
+
var _el$36 = _$getNextElement(_tmpl$1);
|
|
439
|
+
_$insert(_el$36, () => list(props.footer ?? []));
|
|
440
|
+
return _el$36;
|
|
269
441
|
}
|
|
270
|
-
}), _el$
|
|
271
|
-
|
|
442
|
+
}), _el$38, _co$0);
|
|
443
|
+
_$effect(() => _$setAttribute(_el$26, "aria-label", props.label));
|
|
444
|
+
return _el$26;
|
|
272
445
|
})();
|
|
273
446
|
}
|
|
274
447
|
|
|
275
448
|
/**
|
|
276
|
-
* The full-screen frame of a phone app: a header, one scroll area, and an optional footer such as a `TabBar`.
|
|
277
|
-
*
|
|
278
|
-
*
|
|
449
|
+
* The full-screen frame of a phone app: a header, one scroll area, and an optional footer such as a `TabBar`. With a
|
|
450
|
+
* `sidebar`, a window of 48rem and wider shows the sidebar at the start edge instead of the footer, and the toast rail
|
|
451
|
+
* stays in the area beside it. While it is mounted, the document itself never scrolls, pinch zoom and rubber-banding
|
|
452
|
+
* are off, and the toast rail sits above the footer. Mount one per page, as the page's layout.
|
|
279
453
|
*/
|
|
280
454
|
export const MobileShell = Object.assign(MobileShellRoot, {
|
|
281
|
-
Header: MobileShellHeader
|
|
455
|
+
Header: MobileShellHeader,
|
|
456
|
+
Sidebar: MobileShellSidebar
|
|
282
457
|
});
|
|
283
458
|
export default MobileShell;
|
|
284
459
|
//# sourceMappingURL=MobileShell.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":[],"sources":["layout/MobileShell.tsx"],"sourcesContent":["import { type JSX, onCleanup, onMount, Show } from \"solid-js\";\nimport { IconButton, IconButtonLink } from \"../actions/Button\";\nimport ScrollArea from \"./ScrollArea\";\nimport { installScrollFades } from \"./scroll-fade\";\n\nexport type MobileShellProps = {\n /** Usually `MobileShell.Header`; it sits above the scroll area and pads the top safe area. */\n header: JSX.Element;\n /** Usually a `TabBar`; it sits below the scroll area and pads the bottom safe area itself. */\n footer?: JSX.Element;\n /** The page content, inside the shell's only scroll area. */\n children: JSX.Element;\n class?: string;\n};\n\nexport type MobileShellHeaderProps = {\n title: string;\n /** A Back control before the title: a link with `href`, otherwise a button. */\n back?: { href?: string; onClick?: () => void; label: string };\n /** Controls after the title, such as a menu. */\n actions?: JSX.Element;\n};\n\n/** Read by the toast rail, which is portalled outside the shell, so it lives on the body. */\nconst FOOTER_HEIGHT = \"--k2b-mobile-shell-footer-height\";\n/** How much of the scroll area a persistent toast covers; local to the shell. */\nconst TOAST_INSET = \"--k2b-mobile-shell-toast-inset\";\n\n/**\n * The visible part of the toast rail when it holds a toast without a timer (`duration: 0`, running progress, or a\n * custom slot), so the last row of the scroll area can still scroll above it. A rail that sits elsewhere, such as\n * above a dialog, covers nothing.\n */\nconst persistentToastInset = (body: HTMLElement): number => {\n if (document.querySelector(\"dialog:modal\")) return 0;\n const cards = [...document.querySelectorAll<HTMLElement>(\"[data-k2b-toast-container] [data-k2b-toast]:not([data-closing])\")];\n if (!cards.some((card) => card.dataset.persistent === \"true\")) return 0;\n const area = body.getBoundingClientRect();\n const top = Math.min(...cards.map((card) => card.getBoundingClientRect().top));\n return Math.max(0, Math.min(area.height, area.bottom - top));\n};\n\n/** Marks the link whose page is loading; the tab bar shows it as selected. */\nconst PENDING = \"data-k2b-pending\";\n/** On a link: the title of the page it opens. Such a link switches the shell to that page's frame at the first touch. */\nconst PAGE_TITLE = \"data-k2b-title\";\n/** On the root while the shell shows the frame of the page that is loading. */\nconst SWITCHING = \"data-k2b-switching\";\n/** On the header title while the shell switches: the loading page's title, which the title shows instead. */\nconst NEXT_TITLE = \"data-k2b-next-title\";\n\n/** The link a click or press follows as a page load of this origin, or null when it does something else. */\nconst pageLink = (root: HTMLElement, event: MouseEvent): HTMLAnchorElement | null => {\n if (event.defaultPrevented || event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return null;\n const link = event.target instanceof Element ? event.target.closest<HTMLAnchorElement>(\"a[href]\") : null;\n if (!link || !root.contains(link) || link.hasAttribute(\"download\") || (link.target && link.target !== \"_self\")) return null;\n const url = new URL(link.href);\n if (url.origin !== location.origin) return null;\n // A jump inside the page loads nothing.\n if (url.hash && url.pathname === location.pathname && url.search === location.search) return null;\n return link;\n};\n\n/**\n * Taps on the shell's links. iOS shows `:active` only while the page listens to touches, so a tap gets its pressed\n * state at once. A link's page keeps loading while the old page stays visible; a second tap on it would cancel that\n * load and start it over, so it is ignored. A link that names its page's title, such as a tab, shows that page's\n * frame at the first touch instead of at the end of the tap: its title and an empty content area, until the page\n * arrives. Returns the cleanup.\n */\nconst observeLinkTaps = (root: HTMLElement): (() => void) => {\n /** The link marked as the next page. */\n let pending: string | undefined;\n /** Whether its page is loading; a pressed tab waits for its click. */\n let loading = false;\n const clear = () => {\n pending = undefined;\n loading = false;\n for (const link of root.querySelectorAll(`[${PENDING}]`)) link.removeAttribute(PENDING);\n root.removeAttribute(SWITCHING);\n root.querySelector(\".k2b-mobile-shell__title\")?.removeAttribute(NEXT_TITLE);\n };\n const mark = (link: HTMLAnchorElement) => {\n clear();\n pending = link.href;\n link.setAttribute(PENDING, \"\");\n const title = link.getAttribute(PAGE_TITLE);\n const heading = root.querySelector(\".k2b-mobile-shell__title\");\n if (title === null || !heading) return;\n heading.setAttribute(NEXT_TITLE, title);\n root.setAttribute(SWITCHING, \"\");\n };\n const touch = () => {};\n // A press on a tab shows its page's frame while the finger is still down. The page itself loads with the click\n // that ends the tap, as for any link: only the end of a touch counts as the person's action, and a load that\n // started before it could let the browser's Back skip this page.\n const press = (event: PointerEvent) => {\n if (!event.isPrimary) return;\n const link = pageLink(root, event);\n if (!link?.hasAttribute(PAGE_TITLE) || (link.href === pending && loading)) return;\n mark(link);\n };\n // A press that the browser takes over, such as one that turns into a scroll, ends without a click and takes its\n // frame back.\n const cancel = (event: PointerEvent) => {\n if (event.isPrimary && !loading) clear();\n };\n // On the window, so it runs after every handler of the click, including delegated ones that prevent it.\n const click = (event: MouseEvent) => {\n const link = pageLink(root, event);\n if (link && link.href === pending && loading) {\n event.preventDefault();\n return;\n }\n // Any other tap ends the wait, also for a link that answered with a download instead of a page.\n clear();\n if (!link) return;\n mark(link);\n loading = true;\n };\n // iOS sends no click for a tap on content without an action, so the end of a tap anywhere else ends the wait as\n // well. A touch that scrolls ends without a pointerup and keeps a load's wait.\n const release = (event: PointerEvent) => {\n if (pending === undefined) return;\n const link = event.target instanceof Element ? event.target.closest<HTMLAnchorElement>(\"a[href]\") : null;\n if (link?.href !== pending) clear();\n };\n // A page restored from the back/forward cache shows the state it was left in.\n const show = (event: PageTransitionEvent) => {\n if (event.persisted) clear();\n };\n document.addEventListener(\"touchstart\", touch, { passive: true });\n window.addEventListener(\"pointerdown\", press);\n window.addEventListener(\"pointercancel\", cancel);\n window.addEventListener(\"pointerup\", release);\n window.addEventListener(\"click\", click);\n window.addEventListener(\"pageshow\", show);\n return () => {\n document.removeEventListener(\"touchstart\", touch);\n window.removeEventListener(\"pointerdown\", press);\n window.removeEventListener(\"pointercancel\", cancel);\n window.removeEventListener(\"pointerup\", release);\n window.removeEventListener(\"click\", click);\n window.removeEventListener(\"pageshow\", show);\n clear();\n };\n};\n\n/**\n * Keeps a mounted shell working: the footer height on the body, which the portalled toast rail reads, the room a\n * persistent toast takes from the scroll area, the scroll area's edge fade, and immediate feedback for link taps.\n * The fade is the only cue at the footer's edge, which has no rule. `MobileShell` calls it itself;\n * a page that renders the shell on the server without hydrating it calls it once in the browser. Returns the\n * cleanup.\n */\nexport function observeMobileShell(root: HTMLElement): () => void {\n const main = root.querySelector<HTMLElement>(\":scope > .k2b-mobile-shell__main\");\n const body = main?.querySelector<HTMLElement>(\":scope > .k2b-mobile-shell__body\");\n if (!main || !body) return () => {};\n const stopLinkTaps = observeLinkTaps(root);\n const stopScrollFades = installScrollFades(body);\n let frame = 0;\n const measure = () => {\n frame = 0;\n const footer = Math.max(0, root.getBoundingClientRect().bottom - main.getBoundingClientRect().bottom);\n document.body.style.setProperty(FOOTER_HEIGHT, `${footer}px`);\n root.style.setProperty(TOAST_INSET, `${persistentToastInset(body)}px`);\n };\n const schedule = () => {\n if (!frame) frame = requestAnimationFrame(measure);\n };\n measure();\n // The footer can appear, disappear, or change height; the main area takes whatever it leaves.\n const resize = new ResizeObserver(schedule);\n resize.observe(root);\n resize.observe(main);\n // Toasts arrive and leave anywhere in the document, and their slots grow and collapse in a transition.\n const mutations = new MutationObserver(schedule);\n mutations.observe(document.body, {\n childList: true,\n subtree: true,\n attributes: true,\n attributeFilter: [\"data-state\", \"data-closing\", \"data-persistent\", \"open\"],\n });\n document.addEventListener(\"transitionend\", schedule, true);\n return () => {\n if (frame) cancelAnimationFrame(frame);\n resize.disconnect();\n mutations.disconnect();\n document.removeEventListener(\"transitionend\", schedule, true);\n document.body.style.removeProperty(FOOTER_HEIGHT);\n stopLinkTaps();\n stopScrollFades();\n };\n}\n\nfunction MobileShellRoot(props: MobileShellProps): JSX.Element {\n let root!: HTMLDivElement;\n\n onMount(() => onCleanup(observeMobileShell(root)));\n\n return (\n <div ref={root} class={props.class ? `k2b-mobile-shell ${props.class}` : \"k2b-mobile-shell\"}>\n {props.header}\n <main class=\"k2b-mobile-shell__main\">\n <ScrollArea class=\"k2b-mobile-shell__body\">{props.children}</ScrollArea>\n </main>\n {props.footer}\n </div>\n );\n}\n\nfunction MobileShellHeader(props: MobileShellHeaderProps): JSX.Element {\n return (\n <header class=\"k2b-mobile-shell__header\">\n <Show when={props.back}>\n {(back) => (\n <Show\n when={back().href}\n fallback={\n <IconButton class=\"k2b-mobile-shell__back\" label={back().label} tooltip={false} onClick={() => back().onClick?.()}>\n <i class=\"ti ti-chevron-left\" aria-hidden=\"true\" />\n </IconButton>\n }\n >\n {(href) => (\n <IconButtonLink\n class=\"k2b-mobile-shell__back\"\n href={href()}\n label={back().label}\n tooltip={false}\n onClick={() => back().onClick?.()}\n >\n <i class=\"ti ti-chevron-left\" aria-hidden=\"true\" />\n </IconButtonLink>\n )}\n </Show>\n )}\n </Show>\n <h1 class=\"k2b-mobile-shell__title\">{props.title}</h1>\n <Show when={props.actions}>\n <div class=\"k2b-mobile-shell__actions\">{props.actions}</div>\n </Show>\n </header>\n );\n}\n\n/**\n * The full-screen frame of a phone app: a header, one scroll area, and an optional footer such as a `TabBar`. While\n * it is mounted, the document itself never scrolls, pinch zoom and rubber-banding are off, and the toast rail sits\n * above the footer. Mount one per page, as the page's layout.\n */\nexport const MobileShell = Object.assign(MobileShellRoot, { Header: MobileShellHeader });\n\nexport default MobileShell;\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":[],"sources":["layout/MobileShell.tsx"],"sourcesContent":["import { For, type JSX, onCleanup, onMount, Show } from \"solid-js\";\nimport { IconButton, IconButtonLink } from \"../actions/Button\";\nimport ScrollArea from \"./ScrollArea\";\nimport { installScrollFades } from \"./scroll-fade\";\nimport type { TabBarItem } from \"./TabBar\";\n\nexport type MobileShellProps = {\n /** Usually `MobileShell.Header`; it sits above the scroll area and pads the top safe area. */\n header?: JSX.Element;\n /** Usually a `TabBar`; it sits below the scroll area and pads the bottom safe area itself. */\n footer?: JSX.Element;\n /**\n * Usually `MobileShell.Sidebar` with the footer's destinations and more. From 48rem of window width it stands at\n * the start edge and the footer goes; below, it is not shown. The server renders both, so CSS alone decides.\n */\n sidebar?: JSX.Element;\n /** The page content, inside the shell's only scroll area. */\n children: JSX.Element;\n /**\n * `false` for content that brings its own heads and scroll areas, such as `AppWorkspace.Main` levels: it fills the\n * main area without the shell's scroll area, and the header shows only as the frame of the next page while a tapped\n * tab's page loads.\n */\n scroll?: boolean;\n class?: string;\n};\n\nexport type MobileShellHeaderProps = {\n title: string;\n /** The title while the shell shows its sidebar, which already names the app; `title` by default. */\n sidebarTitle?: string;\n /**\n * A Back control before the title: a link with `href`, otherwise a button. `withSidebar: false` hides it while the\n * shell shows its sidebar, for a way back to a destination the sidebar lists.\n */\n back?: { href?: string; onClick?: () => void; label: string; withSidebar?: boolean };\n /** Controls after the title, such as a menu. */\n actions?: JSX.Element;\n};\n\n/** Read by the toast rail, which is portalled outside the shell, so it lives on the body. */\nconst FOOTER_HEIGHT = \"--k2b-mobile-shell-footer-height\";\n/** How much of the scroll area a persistent toast covers; local to the shell. */\nconst TOAST_INSET = \"--k2b-mobile-shell-toast-inset\";\n\n/**\n * The visible part of the toast rail when it holds a toast without a timer (`duration: 0`, running progress, or a\n * custom slot), so the last row of the scroll area can still scroll above it. A rail that sits elsewhere, such as\n * above a dialog, covers nothing.\n */\nconst persistentToastInset = (body: HTMLElement): number => {\n if (document.querySelector(\"dialog:modal\")) return 0;\n const cards = [...document.querySelectorAll<HTMLElement>(\"[data-k2b-toast-container] [data-k2b-toast]:not([data-closing])\")];\n if (!cards.some((card) => card.dataset.persistent === \"true\")) return 0;\n const area = body.getBoundingClientRect();\n const top = Math.min(...cards.map((card) => card.getBoundingClientRect().top));\n return Math.max(0, Math.min(area.height, area.bottom - top));\n};\n\n/** Marks the link whose page is loading; the tab bar shows it as selected. */\nconst PENDING = \"data-k2b-pending\";\n/** On a link: the title of the page it opens. Such a link switches the shell to that page's frame at the first touch. */\nconst PAGE_TITLE = \"data-k2b-title\";\n/** On the root while the shell shows the frame of the page that is loading. */\nconst SWITCHING = \"data-k2b-switching\";\n/** On the header title while the shell switches: the loading page's title, which the title shows instead. */\nconst NEXT_TITLE = \"data-k2b-next-title\";\n\n/** The link a click or press follows as a page load of this origin, or null when it does something else. */\nconst pageLink = (root: HTMLElement, event: MouseEvent): HTMLAnchorElement | null => {\n if (event.defaultPrevented || event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return null;\n const link = event.target instanceof Element ? event.target.closest<HTMLAnchorElement>(\"a[href]\") : null;\n if (!link || !root.contains(link) || link.hasAttribute(\"download\") || (link.target && link.target !== \"_self\")) return null;\n const url = new URL(link.href);\n if (url.origin !== location.origin) return null;\n // A jump inside the page loads nothing.\n if (url.hash && url.pathname === location.pathname && url.search === location.search) return null;\n return link;\n};\n\n/**\n * Taps on the shell's links. iOS shows `:active` only while the page listens to touches, so a tap gets its pressed\n * state at once. A link's page keeps loading while the old page stays visible; a second tap on it would cancel that\n * load and start it over, so it is ignored. A link that names its page's title, such as a tab, shows that page's\n * frame at the first touch instead of at the end of the tap: its title and an empty content area, until the page\n * arrives. Returns the cleanup.\n */\nconst observeLinkTaps = (root: HTMLElement): (() => void) => {\n /** The link marked as the next page. */\n let pending: string | undefined;\n /** Whether its page is loading; a pressed tab waits for its click. */\n let loading = false;\n const clear = () => {\n pending = undefined;\n loading = false;\n for (const link of root.querySelectorAll(`[${PENDING}]`)) link.removeAttribute(PENDING);\n root.removeAttribute(SWITCHING);\n root.querySelector(\".k2b-mobile-shell__title\")?.removeAttribute(NEXT_TITLE);\n };\n const mark = (link: HTMLAnchorElement) => {\n clear();\n pending = link.href;\n link.setAttribute(PENDING, \"\");\n const title = link.getAttribute(PAGE_TITLE);\n const heading = root.querySelector(\".k2b-mobile-shell__title\");\n if (title === null || !heading) return;\n heading.setAttribute(NEXT_TITLE, title);\n root.setAttribute(SWITCHING, \"\");\n };\n const touch = () => {};\n // A press on a tab shows its page's frame while the finger is still down. The page itself loads with the click\n // that ends the tap, as for any link: only the end of a touch counts as the person's action, and a load that\n // started before it could let the browser's Back skip this page.\n const press = (event: PointerEvent) => {\n if (!event.isPrimary) return;\n const link = pageLink(root, event);\n if (!link?.hasAttribute(PAGE_TITLE) || (link.href === pending && loading)) return;\n mark(link);\n };\n // A press that the browser takes over, such as one that turns into a scroll, ends without a click and takes its\n // frame back.\n const cancel = (event: PointerEvent) => {\n if (event.isPrimary && !loading) clear();\n };\n // On the window, so it runs after every handler of the click, including delegated ones that prevent it.\n const click = (event: MouseEvent) => {\n const link = pageLink(root, event);\n if (link && link.href === pending && loading) {\n event.preventDefault();\n return;\n }\n // Any other tap ends the wait, also for a link that answered with a download instead of a page.\n clear();\n if (!link) return;\n mark(link);\n loading = true;\n };\n // iOS sends no click for a tap on content without an action, so the end of a tap anywhere else ends the wait as\n // well. A touch that scrolls ends without a pointerup and keeps a load's wait.\n const release = (event: PointerEvent) => {\n if (pending === undefined) return;\n const link = event.target instanceof Element ? event.target.closest<HTMLAnchorElement>(\"a[href]\") : null;\n if (link?.href !== pending) clear();\n };\n // A page restored from the back/forward cache shows the state it was left in.\n const show = (event: PageTransitionEvent) => {\n if (event.persisted) clear();\n };\n document.addEventListener(\"touchstart\", touch, { passive: true });\n window.addEventListener(\"pointerdown\", press);\n window.addEventListener(\"pointercancel\", cancel);\n window.addEventListener(\"pointerup\", release);\n window.addEventListener(\"click\", click);\n window.addEventListener(\"pageshow\", show);\n return () => {\n document.removeEventListener(\"touchstart\", touch);\n window.removeEventListener(\"pointerdown\", press);\n window.removeEventListener(\"pointercancel\", cancel);\n window.removeEventListener(\"pointerup\", release);\n window.removeEventListener(\"click\", click);\n window.removeEventListener(\"pageshow\", show);\n clear();\n };\n};\n\n/**\n * Keeps a mounted shell working: the footer height on the body, which the portalled toast rail reads, the room a\n * persistent toast takes from the scroll area, the scroll area's edge fade, and immediate feedback for link taps.\n * The fade is the only cue at the footer's edge, which has no rule. `MobileShell` calls it itself;\n * a page that renders the shell on the server without hydrating it calls it once in the browser. Returns the\n * cleanup.\n */\nexport function observeMobileShell(root: HTMLElement): () => void {\n const main = root.querySelector<HTMLElement>(\":scope > .k2b-mobile-shell__main\");\n const body = main?.querySelector<HTMLElement>(\":scope > .k2b-mobile-shell__body\");\n if (!main) return () => {};\n const stopLinkTaps = observeLinkTaps(root);\n // Content with its own scroll areas keeps its own fades; the room a toast takes applies to the whole main area.\n const stopScrollFades = body ? installScrollFades(body) : () => {};\n let frame = 0;\n const measure = () => {\n frame = 0;\n const footer = Math.max(0, root.getBoundingClientRect().bottom - main.getBoundingClientRect().bottom);\n document.body.style.setProperty(FOOTER_HEIGHT, `${footer}px`);\n root.style.setProperty(TOAST_INSET, `${persistentToastInset(body ?? main)}px`);\n };\n const schedule = () => {\n if (!frame) frame = requestAnimationFrame(measure);\n };\n measure();\n // The footer can appear, disappear, or change height; the main area takes whatever it leaves.\n const resize = new ResizeObserver(schedule);\n resize.observe(root);\n resize.observe(main);\n // Toasts arrive and leave anywhere in the document, and their slots grow and collapse in a transition.\n const mutations = new MutationObserver(schedule);\n mutations.observe(document.body, {\n childList: true,\n subtree: true,\n attributes: true,\n attributeFilter: [\"data-state\", \"data-closing\", \"data-persistent\", \"open\"],\n });\n document.addEventListener(\"transitionend\", schedule, true);\n return () => {\n if (frame) cancelAnimationFrame(frame);\n resize.disconnect();\n mutations.disconnect();\n document.removeEventListener(\"transitionend\", schedule, true);\n document.body.style.removeProperty(FOOTER_HEIGHT);\n stopLinkTaps();\n stopScrollFades();\n };\n}\n\nfunction MobileShellRoot(props: MobileShellProps): JSX.Element {\n let root!: HTMLDivElement;\n\n onMount(() => onCleanup(observeMobileShell(root)));\n\n return (\n <div\n ref={root}\n class={props.class ? `k2b-mobile-shell ${props.class}` : \"k2b-mobile-shell\"}\n data-k2b-content-heads={props.scroll === false ? \"\" : undefined}\n >\n {props.sidebar}\n {props.header}\n <main class=\"k2b-mobile-shell__main\">\n <Show when={props.scroll !== false} fallback={props.children}>\n <ScrollArea class=\"k2b-mobile-shell__body\">{props.children}</ScrollArea>\n </Show>\n </main>\n {props.footer}\n </div>\n );\n}\n\nfunction MobileShellHeader(props: MobileShellHeaderProps): JSX.Element {\n return (\n <header class=\"k2b-mobile-shell__header\">\n <Show when={props.back}>\n {(back) => (\n <Show\n when={back().href}\n fallback={\n <IconButton\n class=\"k2b-mobile-shell__back\"\n data-with-sidebar={back().withSidebar === false ? \"false\" : undefined}\n label={back().label}\n tooltip={false}\n onClick={() => back().onClick?.()}\n >\n <i class=\"ti ti-chevron-left\" aria-hidden=\"true\" />\n </IconButton>\n }\n >\n {(href) => (\n <IconButtonLink\n class=\"k2b-mobile-shell__back\"\n data-with-sidebar={back().withSidebar === false ? \"false\" : undefined}\n href={href()}\n label={back().label}\n tooltip={false}\n onClick={() => back().onClick?.()}\n >\n <i class=\"ti ti-chevron-left\" aria-hidden=\"true\" />\n </IconButtonLink>\n )}\n </Show>\n )}\n </Show>\n <h1 class=\"k2b-mobile-shell__title\">\n <Show when={props.sidebarTitle !== undefined && props.sidebarTitle !== props.title} fallback={props.title}>\n <span class=\"k2b-mobile-shell__title-narrow\">{props.title}</span>\n <span class=\"k2b-mobile-shell__title-wide\">{props.sidebarTitle}</span>\n </Show>\n </h1>\n <Show when={props.actions}>\n <div class=\"k2b-mobile-shell__actions\">{props.actions}</div>\n </Show>\n </header>\n );\n}\n\nexport type MobileShellSidebarItem = TabBarItem & {\n /** A count after the label, such as unread messages; 0 shows nothing. */\n count?: number;\n};\n\nexport type MobileShellSidebarProps = {\n /** Accessible name of the navigation landmark; usually the tab bar's. */\n label: string;\n /** The app's name in the sidebar's head. */\n title: string;\n /** Address of the app's logo before the name; decorative, the name says it. */\n logo?: string;\n /** Destinations at the top, such as Start. */\n items: readonly MobileShellSidebarItem[];\n /** Named groups below them, such as the apps; a group without items is left out. */\n sections?: readonly { title: string; items: readonly MobileShellSidebarItem[] }[];\n /** Destinations at the bottom edge, such as Settings. */\n footer?: readonly MobileShellSidebarItem[];\n};\n\nfunction SidebarLink(props: { item: MobileShellSidebarItem }): JSX.Element {\n return (\n <a\n href={props.item.href}\n aria-current={props.item.current ? \"page\" : undefined}\n data-tab={props.item.id}\n data-k2b-title={props.item.title ?? props.item.label}\n >\n <i class={props.item.icon} aria-hidden=\"true\" />\n <span class=\"k2b-truncate-fade\">{props.item.label}</span>\n <Show when={props.item.count}>{(count) => <span class=\"k2b-mobile-shell__sidebar-count\">{count()}</span>}</Show>\n </a>\n );\n}\n\n/**\n * The navigation of a touch app on a wide screen, in `MobileShell`'s `sidebar`: the app's name, then its destinations\n * as 44 px rows with icon and label, the open one in the action colour. A press shows the item's page frame at once,\n * as on a tab, and the row of a loading page pulses.\n */\nfunction MobileShellSidebar(props: MobileShellSidebarProps): JSX.Element {\n const list = (items: readonly MobileShellSidebarItem[]) => (\n <ul>\n <For each={items}>\n {(item) => (\n <li>\n <SidebarLink item={item} />\n </li>\n )}\n </For>\n </ul>\n );\n return (\n <nav class=\"k2b-mobile-shell__sidebar\" aria-label={props.label}>\n <div class=\"k2b-mobile-shell__sidebar-head\">\n <Show when={props.logo}>{(logo) => <img src={logo()} alt=\"\" width=\"32\" height=\"32\" />}</Show>\n <span class=\"k2b-truncate-fade\">{props.title}</span>\n </div>\n <div class=\"k2b-mobile-shell__sidebar-body\">\n {list(props.items)}\n <For each={(props.sections ?? []).filter((section) => section.items.length > 0)}>\n {(section) => (\n <section>\n <h2>{section.title}</h2>\n {list(section.items)}\n </section>\n )}\n </For>\n </div>\n <Show when={props.footer?.length}>\n <div class=\"k2b-mobile-shell__sidebar-foot\">{list(props.footer ?? [])}</div>\n </Show>\n </nav>\n );\n}\n\n/**\n * The full-screen frame of a phone app: a header, one scroll area, and an optional footer such as a `TabBar`. With a\n * `sidebar`, a window of 48rem and wider shows the sidebar at the start edge instead of the footer, and the toast rail\n * stays in the area beside it. While it is mounted, the document itself never scrolls, pinch zoom and rubber-banding\n * are off, and the toast rail sits above the footer. Mount one per page, as the page's layout.\n */\nexport const MobileShell = Object.assign(MobileShellRoot, { Header: MobileShellHeader, Sidebar: MobileShellSidebar });\n\nexport default MobileShell;\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -25,6 +25,7 @@ export { readSettingsError, SettingsField, SettingsGroup, SettingsPage, Settings
|
|
|
25
25
|
export { default as SettingsCollection } from "./SettingsCollection";
|
|
26
26
|
export { default as SettingsModal } from "./SettingsModal";
|
|
27
27
|
export { APP_WORKSPACE_SWITCHER_SEARCH_FROM } from "./SidebarSwitcher";
|
|
28
|
+
export { measureScrollFade } from "./scroll-fade";
|
|
28
29
|
export { default as TabBar } from "./TabBar";
|
|
29
30
|
export { TableOfContents } from "./TableOfContents";
|
|
30
31
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":[],"sources":["layout/index.ts"],"sourcesContent":["export type {\n AppOverviewCardsProps,\n AppOverviewEmptyStateProps,\n AppOverviewPanelProps,\n AppOverviewProps,\n} from \"./AppOverview\";\nexport { default as AppOverview } from \"./AppOverview\";\nexport type {\n AppWorkspaceBottomDrawerHeight,\n AppWorkspaceBottomDrawerProps,\n AppWorkspaceContentProps,\n AppWorkspaceDetailProps,\n AppWorkspaceDetailWidth,\n AppWorkspaceHeadProps,\n AppWorkspaceMainPaneProps,\n AppWorkspaceMainProps,\n AppWorkspaceNavTreeItemProps,\n AppWorkspaceNavTreeMove,\n AppWorkspaceNavTreeProps,\n AppWorkspaceProps,\n AppWorkspaceSidebarAccessoryVisibility,\n AppWorkspaceSidebarBodyProps,\n AppWorkspaceSidebarIconActionProps,\n AppWorkspaceSidebarIconActionTone,\n AppWorkspaceSidebarIconGridProps,\n AppWorkspaceSidebarItemActionProps,\n AppWorkspaceSidebarItemActionsProps,\n AppWorkspaceSidebarItemIconProps,\n AppWorkspaceSidebarItemLabelProps,\n AppWorkspaceSidebarItemMetaProps,\n AppWorkspaceSidebarItemProps,\n AppWorkspaceSidebarItemStatusProps,\n AppWorkspaceSidebarItemTone,\n AppWorkspaceSidebarProps,\n AppWorkspaceSidebarSectionProps,\n AppWorkspaceSidebarVisibility,\n AppWorkspaceWidthShare,\n} from \"./AppWorkspace\";\nexport { appWorkspaceDetailElementId, default as AppWorkspace } from \"./AppWorkspace\";\nexport { watchAppHostWidth } from \"./app-host-width\";\nexport type { AppWorkspaceControllerOptions } from \"./app-workspace-controller\";\nexport { installAppWorkspaceController, parkWorkspaceDetailDrawers } from \"./app-workspace-controller\";\nexport type {\n AppWorkspaceLayoutState,\n AppWorkspaceResizeKind,\n} from \"./app-workspace-state\";\nexport {\n APP_WORKSPACE_DETAIL_DEFAULT,\n APP_WORKSPACE_DETAIL_MAX,\n APP_WORKSPACE_DETAIL_MIN,\n APP_WORKSPACE_DRAWER_DEFAULT,\n APP_WORKSPACE_DRAWER_MAX,\n APP_WORKSPACE_DRAWER_MIN,\n APP_WORKSPACE_MAIN_MIN,\n APP_WORKSPACE_MAIN_MIN_HEIGHT,\n APP_WORKSPACE_PANE_DEFAULT,\n APP_WORKSPACE_PANE_MAX,\n APP_WORKSPACE_PANE_MIN,\n APP_WORKSPACE_SIDEBAR_COLLAPSE_THRESHOLD,\n APP_WORKSPACE_SIDEBAR_COLLAPSED,\n APP_WORKSPACE_SIDEBAR_DEFAULT,\n APP_WORKSPACE_SIDEBAR_MAX,\n APP_WORKSPACE_SIDEBAR_MIN,\n appWorkspaceLayoutStyle,\n appWorkspacePanelVariable,\n appWorkspaceResizeLimits,\n normalizeAppWorkspaceLayoutState,\n parseAppWorkspaceLayoutState,\n resolveAppWorkspaceSidebarWidth,\n safeAppWorkspacePanelId,\n serializeAppWorkspaceLayoutState,\n shouldCollapseAppWorkspaceSidebar,\n} from \"./app-workspace-state\";\nexport { type BottomSheetProps, bottomSheetAdaptiveOptions, bottomSheetOptions, default as BottomSheet } from \"./BottomSheet\";\nexport type { DataPanelProps } from \"./DataPanel\";\nexport { DataPanel } from \"./DataPanel\";\nexport type {\n DetailPanelActionButtonProps,\n DetailPanelActionLinkProps,\n DetailPanelActionProps,\n DetailPanelActionSecondary,\n DetailPanelBodyProps,\n DetailPanelGroupProps,\n DetailPanelHeaderProps,\n DetailPanelProps,\n DetailPanelSectionProps,\n DetailPanelSummaryProps,\n DetailPanelTone,\n} from \"./DetailPanel\";\nexport { default as DetailPanel } from \"./DetailPanel\";\nexport type { DiscussionComposerProps, DiscussionItemProps, DiscussionListProps, DiscussionProps } from \"./Discussion\";\nexport { default as Discussion } from \"./Discussion\";\nexport type {\n FloatingWindowClose,\n FloatingWindowProps,\n OpenFloatingWindowOptions,\n} from \"./FloatingWindow\";\nexport {\n default as FloatingWindow,\n type FloatingWindowRect,\n fitFloatingWindowRect,\n openFloatingWindow,\n} from \"./FloatingWindow\";\nexport type { MobileShellHeaderProps, MobileShellProps } from \"./MobileShell\";\nexport { default as MobileShell, observeMobileShell } from \"./MobileShell\";\nexport { default as Navigation, type NavigationProps } from \"./Navigation\";\nexport {\n createNavigation,\n findNavigationItem,\n type NavigationController,\n type NavigationItem,\n type NavigationOptions,\n type NavigationStatus,\n} from \"./navigation-model\";\nexport type { PageTitleProps, PageTrailLink, PageTrailState } from \"./PageTitle\";\nexport { followPageTrail, PAGE_TRAIL_EVENT, PageTitle, PageTrailProvider, readPageTrail, setPageTrail, usePageTrail } from \"./PageTitle\";\nexport type {\n PanelDialogBodyProps,\n PanelDialogFooterProps,\n PanelDialogHeaderProps,\n PanelDialogProps,\n PanelDialogSectionProps,\n PanelDialogSurface,\n PanelDialogTabOption,\n PanelDialogTabsProps,\n} from \"./PanelDialog\";\nexport {\n confirmDiscardIfDirty,\n default as PanelDialog,\n panelDialogFixedOptions,\n panelDialogFixedPanelClass,\n panelDialogOptions,\n panelDialogPanelClass,\n panelDialogWideOptions,\n panelDialogWidePanelClass,\n panelDialogWorkspaceOptions,\n panelDialogWorkspacePanelClass,\n} from \"./PanelDialog\";\nexport type { PanelHeaderProps } from \"./PanelHeader\";\nexport { PanelHeader } from \"./PanelHeader\";\nexport type { PanesItem, PanesProps } from \"./Panes\";\nexport { default as Panes } from \"./Panes\";\nexport type { PullToRefreshProps, PullToRefreshState } from \"./PullToRefresh\";\nexport { default as PullToRefresh } from \"./PullToRefresh\";\nexport { installPageTitleController } from \"./page-title-controller\";\nexport type {\n AddPanesItemOptions,\n PanesDirection,\n PanesGroup,\n PanesIntent,\n PanesLayout,\n PanesNode,\n PanesPath,\n PanesPathSegment,\n PanesSide,\n PanesSplit,\n} from \"./panes-layout\";\nexport {\n activatePanesItem,\n addPanesItem,\n applyPanesIntent,\n createPanesLayout,\n isPanesItemVisible,\n PANES_LAYOUT_VERSION,\n parsePanesLayout,\n reconcilePanesLayout,\n removePanesItem,\n resizePanesSplit,\n} from \"./panes-layout\";\nexport { default as ResizeSeparator, type ResizeSeparatorProps } from \"./ResizeSeparator\";\nexport { attachResizeSeparator, type ResizeSeparatorOptions } from \"./resize-separator\";\nexport type { ScrollAreaProps } from \"./ScrollArea\";\nexport { default as ScrollArea } from \"./ScrollArea\";\nexport type {\n SettingsFieldControlProps,\n SettingsFieldProps,\n SettingsGroupActionProps,\n SettingsGroupProps,\n SettingsPageProps,\n SettingsPanelFooterProps,\n SettingsSaveBarProps,\n SettingsSectionProps,\n} from \"./Settings\";\nexport {\n readSettingsError,\n SettingsField,\n SettingsGroup,\n SettingsPage,\n SettingsPanelFooter,\n SettingsSaveBar,\n SettingsSection,\n sameSettingValue,\n} from \"./Settings\";\nexport type {\n SettingsCollectionActionProps,\n SettingsCollectionItemActionsProps,\n SettingsCollectionItemProps,\n SettingsCollectionItemReorderProps,\n SettingsCollectionItemStatusProps,\n SettingsCollectionProps,\n} from \"./SettingsCollection\";\nexport { default as SettingsCollection } from \"./SettingsCollection\";\nexport type {\n SettingsModalFooterProps,\n SettingsModalGroupProps,\n SettingsModalProps,\n SettingsModalTabProps,\n SettingsModalTabTone,\n} from \"./SettingsModal\";\nexport { default as SettingsModal } from \"./SettingsModal\";\nexport {\n APP_WORKSPACE_SWITCHER_SEARCH_FROM,\n type AppWorkspaceSidebarSwitcherProps,\n type AppWorkspaceSwitcherAction,\n type AppWorkspaceSwitcherOption,\n} from \"./SidebarSwitcher\";\nexport type { TabBarItem, TabBarProps } from \"./TabBar\";\nexport { default as TabBar } from \"./TabBar\";\nexport type { TableOfContentsItem, TableOfContentsProps } from \"./TableOfContents\";\nexport { TableOfContents } from \"./TableOfContents\";\n"],"mappings":"AAMA,SAAS,OAAO,IAAI,WAAW,QAAQ,eAAe;AAgCtD,SAAS,2BAA2B,EAAE,OAAO,IAAI,YAAY,QAAQ,gBAAgB;AACrF,SAAS,iBAAiB,QAAQ,kBAAkB;AAEpD,SAAS,6BAA6B,EAAE,0BAA0B,QAAQ,4BAA4B;AAKtG,SACE,4BAA4B,EAC5B,wBAAwB,EACxB,wBAAwB,EACxB,4BAA4B,EAC5B,wBAAwB,EACxB,wBAAwB,EACxB,sBAAsB,EACtB,6BAA6B,EAC7B,0BAA0B,EAC1B,sBAAsB,EACtB,sBAAsB,EACtB,wCAAwC,EACxC,+BAA+B,EAC/B,6BAA6B,EAC7B,yBAAyB,EACzB,yBAAyB,EACzB,uBAAuB,EACvB,yBAAyB,EACzB,wBAAwB,EACxB,gCAAgC,EAChC,4BAA4B,EAC5B,+BAA+B,EAC/B,uBAAuB,EACvB,gCAAgC,EAChC,iCAAiC,QAC5B,uBAAuB;AAC9B,SAAgC,0BAA0B,EAAE,kBAAkB,EAAE,OAAO,IAAI,WAAW,QAAQ,eAAe;AAE7H,SAAS,SAAS,QAAQ,aAAa;AAcvC,SAAS,OAAO,IAAI,WAAW,QAAQ,eAAe;AAEtD,SAAS,OAAO,IAAI,UAAU,QAAQ,cAAc;AAMpD,SACE,OAAO,IAAI,cAAc,EAEzB,qBAAqB,EACrB,kBAAkB,QACb,kBAAkB;AAEzB,SAAS,OAAO,IAAI,WAAW,EAAE,kBAAkB,QAAQ,eAAe;AAC1E,SAAS,OAAO,IAAI,UAAU,QAA8B,cAAc;AAC1E,SACE,gBAAgB,EAChB,kBAAkB,QAKb,oBAAoB;AAE3B,SAAS,eAAe,EAAE,gBAAgB,EAAE,SAAS,EAAE,iBAAiB,EAAE,aAAa,EAAE,YAAY,EAAE,YAAY,QAAQ,aAAa;AAWxI,SACE,qBAAqB,EACrB,OAAO,IAAI,WAAW,EACtB,uBAAuB,EACvB,0BAA0B,EAC1B,kBAAkB,EAClB,qBAAqB,EACrB,sBAAsB,EACtB,yBAAyB,EACzB,2BAA2B,EAC3B,8BAA8B,QACzB,eAAe;AAEtB,SAAS,WAAW,QAAQ,eAAe;AAE3C,SAAS,OAAO,IAAI,KAAK,QAAQ,SAAS;AAE1C,SAAS,OAAO,IAAI,aAAa,QAAQ,iBAAiB;AAC1D,SAAS,0BAA0B,QAAQ,yBAAyB;AAapE,SACE,iBAAiB,EACjB,YAAY,EACZ,gBAAgB,EAChB,iBAAiB,EACjB,kBAAkB,EAClB,oBAAoB,EACpB,gBAAgB,EAChB,oBAAoB,EACpB,eAAe,EACf,gBAAgB,QACX,gBAAgB;AACvB,SAAS,OAAO,IAAI,eAAe,QAAmC,mBAAmB;AACzF,SAAS,qBAAqB,QAAqC,oBAAoB;AAEvF,SAAS,OAAO,IAAI,UAAU,QAAQ,cAAc;AAWpD,SACE,iBAAiB,EACjB,aAAa,EACb,aAAa,EACb,YAAY,EACZ,mBAAmB,EACnB,eAAe,EACf,eAAe,EACf,gBAAgB,QACX,YAAY;AASnB,SAAS,OAAO,IAAI,kBAAkB,QAAQ,sBAAsB;AAQpE,SAAS,OAAO,IAAI,aAAa,QAAQ,iBAAiB;AAC1D,SACE,kCAAkC,QAI7B,mBAAmB;
|
|
1
|
+
{"version":3,"names":[],"sources":["layout/index.ts"],"sourcesContent":["export type {\n AppOverviewCardsProps,\n AppOverviewEmptyStateProps,\n AppOverviewPanelProps,\n AppOverviewProps,\n} from \"./AppOverview\";\nexport { default as AppOverview } from \"./AppOverview\";\nexport type {\n AppWorkspaceBottomDrawerHeight,\n AppWorkspaceBottomDrawerProps,\n AppWorkspaceContentProps,\n AppWorkspaceDetailProps,\n AppWorkspaceDetailWidth,\n AppWorkspaceHeadProps,\n AppWorkspaceMainPaneProps,\n AppWorkspaceMainProps,\n AppWorkspaceNavTreeItemProps,\n AppWorkspaceNavTreeMove,\n AppWorkspaceNavTreeProps,\n AppWorkspaceProps,\n AppWorkspaceSidebarAccessoryVisibility,\n AppWorkspaceSidebarBodyProps,\n AppWorkspaceSidebarIconActionProps,\n AppWorkspaceSidebarIconActionTone,\n AppWorkspaceSidebarIconGridProps,\n AppWorkspaceSidebarItemActionProps,\n AppWorkspaceSidebarItemActionsProps,\n AppWorkspaceSidebarItemIconProps,\n AppWorkspaceSidebarItemLabelProps,\n AppWorkspaceSidebarItemMetaProps,\n AppWorkspaceSidebarItemProps,\n AppWorkspaceSidebarItemStatusProps,\n AppWorkspaceSidebarItemTone,\n AppWorkspaceSidebarProps,\n AppWorkspaceSidebarSectionProps,\n AppWorkspaceSidebarVisibility,\n AppWorkspaceWidthShare,\n} from \"./AppWorkspace\";\nexport { appWorkspaceDetailElementId, default as AppWorkspace } from \"./AppWorkspace\";\nexport { watchAppHostWidth } from \"./app-host-width\";\nexport type { AppWorkspaceControllerOptions } from \"./app-workspace-controller\";\nexport { installAppWorkspaceController, parkWorkspaceDetailDrawers } from \"./app-workspace-controller\";\nexport type {\n AppWorkspaceLayoutState,\n AppWorkspaceResizeKind,\n} from \"./app-workspace-state\";\nexport {\n APP_WORKSPACE_DETAIL_DEFAULT,\n APP_WORKSPACE_DETAIL_MAX,\n APP_WORKSPACE_DETAIL_MIN,\n APP_WORKSPACE_DRAWER_DEFAULT,\n APP_WORKSPACE_DRAWER_MAX,\n APP_WORKSPACE_DRAWER_MIN,\n APP_WORKSPACE_MAIN_MIN,\n APP_WORKSPACE_MAIN_MIN_HEIGHT,\n APP_WORKSPACE_PANE_DEFAULT,\n APP_WORKSPACE_PANE_MAX,\n APP_WORKSPACE_PANE_MIN,\n APP_WORKSPACE_SIDEBAR_COLLAPSE_THRESHOLD,\n APP_WORKSPACE_SIDEBAR_COLLAPSED,\n APP_WORKSPACE_SIDEBAR_DEFAULT,\n APP_WORKSPACE_SIDEBAR_MAX,\n APP_WORKSPACE_SIDEBAR_MIN,\n appWorkspaceLayoutStyle,\n appWorkspacePanelVariable,\n appWorkspaceResizeLimits,\n normalizeAppWorkspaceLayoutState,\n parseAppWorkspaceLayoutState,\n resolveAppWorkspaceSidebarWidth,\n safeAppWorkspacePanelId,\n serializeAppWorkspaceLayoutState,\n shouldCollapseAppWorkspaceSidebar,\n} from \"./app-workspace-state\";\nexport { type BottomSheetProps, bottomSheetAdaptiveOptions, bottomSheetOptions, default as BottomSheet } from \"./BottomSheet\";\nexport type { DataPanelProps } from \"./DataPanel\";\nexport { DataPanel } from \"./DataPanel\";\nexport type {\n DetailPanelActionButtonProps,\n DetailPanelActionLinkProps,\n DetailPanelActionProps,\n DetailPanelActionSecondary,\n DetailPanelBodyProps,\n DetailPanelGroupProps,\n DetailPanelHeaderProps,\n DetailPanelProps,\n DetailPanelSectionProps,\n DetailPanelSummaryProps,\n DetailPanelTone,\n} from \"./DetailPanel\";\nexport { default as DetailPanel } from \"./DetailPanel\";\nexport type { DiscussionComposerProps, DiscussionItemProps, DiscussionListProps, DiscussionProps } from \"./Discussion\";\nexport { default as Discussion } from \"./Discussion\";\nexport type {\n FloatingWindowClose,\n FloatingWindowProps,\n OpenFloatingWindowOptions,\n} from \"./FloatingWindow\";\nexport {\n default as FloatingWindow,\n type FloatingWindowRect,\n fitFloatingWindowRect,\n openFloatingWindow,\n} from \"./FloatingWindow\";\nexport type { MobileShellHeaderProps, MobileShellProps, MobileShellSidebarItem, MobileShellSidebarProps } from \"./MobileShell\";\nexport { default as MobileShell, observeMobileShell } from \"./MobileShell\";\nexport { default as Navigation, type NavigationProps } from \"./Navigation\";\nexport {\n createNavigation,\n findNavigationItem,\n type NavigationController,\n type NavigationItem,\n type NavigationOptions,\n type NavigationStatus,\n} from \"./navigation-model\";\nexport type { PageTitleProps, PageTrailLink, PageTrailState } from \"./PageTitle\";\nexport { followPageTrail, PAGE_TRAIL_EVENT, PageTitle, PageTrailProvider, readPageTrail, setPageTrail, usePageTrail } from \"./PageTitle\";\nexport type {\n PanelDialogBodyProps,\n PanelDialogFooterProps,\n PanelDialogHeaderProps,\n PanelDialogProps,\n PanelDialogSectionProps,\n PanelDialogSurface,\n PanelDialogTabOption,\n PanelDialogTabsProps,\n} from \"./PanelDialog\";\nexport {\n confirmDiscardIfDirty,\n default as PanelDialog,\n panelDialogFixedOptions,\n panelDialogFixedPanelClass,\n panelDialogOptions,\n panelDialogPanelClass,\n panelDialogWideOptions,\n panelDialogWidePanelClass,\n panelDialogWorkspaceOptions,\n panelDialogWorkspacePanelClass,\n} from \"./PanelDialog\";\nexport type { PanelHeaderProps } from \"./PanelHeader\";\nexport { PanelHeader } from \"./PanelHeader\";\nexport type { PanesItem, PanesProps } from \"./Panes\";\nexport { default as Panes } from \"./Panes\";\nexport type { PullToRefreshProps, PullToRefreshState } from \"./PullToRefresh\";\nexport { default as PullToRefresh } from \"./PullToRefresh\";\nexport { installPageTitleController } from \"./page-title-controller\";\nexport type {\n AddPanesItemOptions,\n PanesDirection,\n PanesGroup,\n PanesIntent,\n PanesLayout,\n PanesNode,\n PanesPath,\n PanesPathSegment,\n PanesSide,\n PanesSplit,\n} from \"./panes-layout\";\nexport {\n activatePanesItem,\n addPanesItem,\n applyPanesIntent,\n createPanesLayout,\n isPanesItemVisible,\n PANES_LAYOUT_VERSION,\n parsePanesLayout,\n reconcilePanesLayout,\n removePanesItem,\n resizePanesSplit,\n} from \"./panes-layout\";\nexport { default as ResizeSeparator, type ResizeSeparatorProps } from \"./ResizeSeparator\";\nexport { attachResizeSeparator, type ResizeSeparatorOptions } from \"./resize-separator\";\nexport type { ScrollAreaProps } from \"./ScrollArea\";\nexport { default as ScrollArea } from \"./ScrollArea\";\nexport type {\n SettingsFieldControlProps,\n SettingsFieldProps,\n SettingsGroupActionProps,\n SettingsGroupProps,\n SettingsPageProps,\n SettingsPanelFooterProps,\n SettingsSaveBarProps,\n SettingsSectionProps,\n} from \"./Settings\";\nexport {\n readSettingsError,\n SettingsField,\n SettingsGroup,\n SettingsPage,\n SettingsPanelFooter,\n SettingsSaveBar,\n SettingsSection,\n sameSettingValue,\n} from \"./Settings\";\nexport type {\n SettingsCollectionActionProps,\n SettingsCollectionItemActionsProps,\n SettingsCollectionItemProps,\n SettingsCollectionItemReorderProps,\n SettingsCollectionItemStatusProps,\n SettingsCollectionProps,\n} from \"./SettingsCollection\";\nexport { default as SettingsCollection } from \"./SettingsCollection\";\nexport type {\n SettingsModalFooterProps,\n SettingsModalGroupProps,\n SettingsModalProps,\n SettingsModalTabProps,\n SettingsModalTabTone,\n} from \"./SettingsModal\";\nexport { default as SettingsModal } from \"./SettingsModal\";\nexport {\n APP_WORKSPACE_SWITCHER_SEARCH_FROM,\n type AppWorkspaceSidebarSwitcherProps,\n type AppWorkspaceSwitcherAction,\n type AppWorkspaceSwitcherOption,\n} from \"./SidebarSwitcher\";\nexport { measureScrollFade } from \"./scroll-fade\";\nexport type { TabBarItem, TabBarProps } from \"./TabBar\";\nexport { default as TabBar } from \"./TabBar\";\nexport type { TableOfContentsItem, TableOfContentsProps } from \"./TableOfContents\";\nexport { TableOfContents } from \"./TableOfContents\";\n"],"mappings":"AAMA,SAAS,OAAO,IAAI,WAAW,QAAQ,eAAe;AAgCtD,SAAS,2BAA2B,EAAE,OAAO,IAAI,YAAY,QAAQ,gBAAgB;AACrF,SAAS,iBAAiB,QAAQ,kBAAkB;AAEpD,SAAS,6BAA6B,EAAE,0BAA0B,QAAQ,4BAA4B;AAKtG,SACE,4BAA4B,EAC5B,wBAAwB,EACxB,wBAAwB,EACxB,4BAA4B,EAC5B,wBAAwB,EACxB,wBAAwB,EACxB,sBAAsB,EACtB,6BAA6B,EAC7B,0BAA0B,EAC1B,sBAAsB,EACtB,sBAAsB,EACtB,wCAAwC,EACxC,+BAA+B,EAC/B,6BAA6B,EAC7B,yBAAyB,EACzB,yBAAyB,EACzB,uBAAuB,EACvB,yBAAyB,EACzB,wBAAwB,EACxB,gCAAgC,EAChC,4BAA4B,EAC5B,+BAA+B,EAC/B,uBAAuB,EACvB,gCAAgC,EAChC,iCAAiC,QAC5B,uBAAuB;AAC9B,SAAgC,0BAA0B,EAAE,kBAAkB,EAAE,OAAO,IAAI,WAAW,QAAQ,eAAe;AAE7H,SAAS,SAAS,QAAQ,aAAa;AAcvC,SAAS,OAAO,IAAI,WAAW,QAAQ,eAAe;AAEtD,SAAS,OAAO,IAAI,UAAU,QAAQ,cAAc;AAMpD,SACE,OAAO,IAAI,cAAc,EAEzB,qBAAqB,EACrB,kBAAkB,QACb,kBAAkB;AAEzB,SAAS,OAAO,IAAI,WAAW,EAAE,kBAAkB,QAAQ,eAAe;AAC1E,SAAS,OAAO,IAAI,UAAU,QAA8B,cAAc;AAC1E,SACE,gBAAgB,EAChB,kBAAkB,QAKb,oBAAoB;AAE3B,SAAS,eAAe,EAAE,gBAAgB,EAAE,SAAS,EAAE,iBAAiB,EAAE,aAAa,EAAE,YAAY,EAAE,YAAY,QAAQ,aAAa;AAWxI,SACE,qBAAqB,EACrB,OAAO,IAAI,WAAW,EACtB,uBAAuB,EACvB,0BAA0B,EAC1B,kBAAkB,EAClB,qBAAqB,EACrB,sBAAsB,EACtB,yBAAyB,EACzB,2BAA2B,EAC3B,8BAA8B,QACzB,eAAe;AAEtB,SAAS,WAAW,QAAQ,eAAe;AAE3C,SAAS,OAAO,IAAI,KAAK,QAAQ,SAAS;AAE1C,SAAS,OAAO,IAAI,aAAa,QAAQ,iBAAiB;AAC1D,SAAS,0BAA0B,QAAQ,yBAAyB;AAapE,SACE,iBAAiB,EACjB,YAAY,EACZ,gBAAgB,EAChB,iBAAiB,EACjB,kBAAkB,EAClB,oBAAoB,EACpB,gBAAgB,EAChB,oBAAoB,EACpB,eAAe,EACf,gBAAgB,QACX,gBAAgB;AACvB,SAAS,OAAO,IAAI,eAAe,QAAmC,mBAAmB;AACzF,SAAS,qBAAqB,QAAqC,oBAAoB;AAEvF,SAAS,OAAO,IAAI,UAAU,QAAQ,cAAc;AAWpD,SACE,iBAAiB,EACjB,aAAa,EACb,aAAa,EACb,YAAY,EACZ,mBAAmB,EACnB,eAAe,EACf,eAAe,EACf,gBAAgB,QACX,YAAY;AASnB,SAAS,OAAO,IAAI,kBAAkB,QAAQ,sBAAsB;AAQpE,SAAS,OAAO,IAAI,aAAa,QAAQ,iBAAiB;AAC1D,SACE,kCAAkC,QAI7B,mBAAmB;AAC1B,SAAS,iBAAiB,QAAQ,eAAe;AAEjD,SAAS,OAAO,IAAI,MAAM,QAAQ,UAAU;AAE5C,SAAS,eAAe,QAAQ,mBAAmB","ignoreList":[]}
|
|
@@ -19,21 +19,38 @@ export function scrollFadeEdges(body) {
|
|
|
19
19
|
function observeScrollFade(body) {
|
|
20
20
|
let entry = active.get(body);
|
|
21
21
|
if (!entry) {
|
|
22
|
-
const
|
|
22
|
+
const apply = () => {
|
|
23
23
|
const edges = scrollFadeEdges(body);
|
|
24
24
|
if (edges) {
|
|
25
25
|
if (body.getAttribute("data-scroll-fade") !== edges) body.setAttribute("data-scroll-fade", edges);
|
|
26
26
|
} else if (body.hasAttribute("data-scroll-fade")) body.removeAttribute("data-scroll-fade");
|
|
27
27
|
};
|
|
28
|
+
// Measuring forces layout. Scrolling (the browser sends one scroll event per frame) and changes to the scrollport
|
|
29
|
+
// itself measure at once; changes of its content are measured once per frame. A list that updates many rows at
|
|
30
|
+
// once, such as marking every chat read, otherwise lays the page out again for each row, and a measurement in the
|
|
31
|
+
// middle of a large change can delay the next frame enough to count as a layout shift. A reader that needs the
|
|
32
|
+
// current edges before the frame ends calls `measureScrollFade`.
|
|
33
|
+
let frame = 0;
|
|
34
|
+
const measure = () => {
|
|
35
|
+
if (frame) cancelAnimationFrame(frame);
|
|
36
|
+
frame = 0;
|
|
37
|
+
apply();
|
|
38
|
+
};
|
|
39
|
+
const update = () => {
|
|
40
|
+
if (!frame) frame = requestAnimationFrame(() => {
|
|
41
|
+
frame = 0;
|
|
42
|
+
apply();
|
|
43
|
+
});
|
|
44
|
+
};
|
|
28
45
|
const resize = new ResizeObserver(update);
|
|
29
46
|
const observe = () => {
|
|
30
47
|
resize.disconnect();
|
|
31
48
|
resize.observe(body);
|
|
32
49
|
for (const child of Array.from(body.children)) resize.observe(child);
|
|
33
|
-
|
|
50
|
+
measure();
|
|
34
51
|
};
|
|
35
52
|
const mutations = new MutationObserver(records => {
|
|
36
|
-
if (records.some(record => record.type === "childList" && record.target === body)) observe();else update();
|
|
53
|
+
if (records.some(record => record.type === "childList" && record.target === body)) observe();else if (records.some(record => record.target === body)) apply();else update();
|
|
37
54
|
});
|
|
38
55
|
mutations.observe(body, {
|
|
39
56
|
childList: true,
|
|
@@ -42,16 +59,18 @@ function observeScrollFade(body) {
|
|
|
42
59
|
attributes: true,
|
|
43
60
|
attributeFilter: ["class", "style", "hidden", "open", "data-scroll-fade-mode", "data-scroll-fade-axis", "dir"]
|
|
44
61
|
});
|
|
45
|
-
body.addEventListener("scroll",
|
|
62
|
+
body.addEventListener("scroll", apply, {
|
|
46
63
|
passive: true
|
|
47
64
|
});
|
|
48
65
|
observe();
|
|
49
66
|
entry = {
|
|
50
67
|
users: 0,
|
|
68
|
+
measure,
|
|
51
69
|
stop: () => {
|
|
70
|
+
if (frame) cancelAnimationFrame(frame);
|
|
52
71
|
resize.disconnect();
|
|
53
72
|
mutations.disconnect();
|
|
54
|
-
body.removeEventListener("scroll",
|
|
73
|
+
body.removeEventListener("scroll", apply);
|
|
55
74
|
body.removeAttribute("data-scroll-fade");
|
|
56
75
|
}
|
|
57
76
|
};
|
|
@@ -65,6 +84,14 @@ function observeScrollFade(body) {
|
|
|
65
84
|
}
|
|
66
85
|
};
|
|
67
86
|
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Measures an observed scrollport's fades now instead of at the end of the frame. Call it before reading the fades in
|
|
90
|
+
* the same frame as a change of the scrollport's content, as an editor does when it keeps its cursor clear of them.
|
|
91
|
+
*/
|
|
92
|
+
export function measureScrollFade(element) {
|
|
93
|
+
active.get(element)?.measure();
|
|
94
|
+
}
|
|
68
95
|
export function createScrollFade(element, enabled) {
|
|
69
96
|
createEffect(() => {
|
|
70
97
|
if (!enabled()) return;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":[],"sources":["layout/scroll-fade.ts"],"sourcesContent":["import { createEffect, onCleanup } from \"solid-js\";\n\nconst selector = \"[data-scroll-fade-mode]\";\nconst active = new WeakMap<HTMLElement, { users: number; stop: () => void }>();\n\n/** Self-contained because the sidebar inline script embeds its source. */\nexport function scrollFadeEdges(body: HTMLElement): \"top\" | \"bottom\" | \"both\" | undefined {\n const mode = body.getAttribute(\"data-scroll-fade-mode\");\n const horizontal = body.getAttribute(\"data-scroll-fade-axis\") === \"horizontal\";\n const overflow = horizontal ? body.scrollWidth - body.clientWidth : body.scrollHeight - body.clientHeight;\n // Horizontal RTL scrollLeft starts at zero on the right and becomes negative.\n const rtl = horizontal && getComputedStyle(body).direction === \"rtl\";\n const offset = horizontal ? (rtl ? overflow + body.scrollLeft : body.scrollLeft) : body.scrollTop;\n const top = mode === \"both\" && overflow > 1 && offset > 1;\n const bottom = !!mode && overflow > 1 && overflow - offset > 1;\n return top && bottom ? \"both\" : top ? \"top\" : bottom ? \"bottom\" : undefined;\n}\n\n/** Shared by hydrated components and the workspace's server-rendered scrollports. */\nfunction observeScrollFade(body: HTMLElement) {\n let entry = active.get(body);\n if (!entry) {\n const update = () => {\n const edges = scrollFadeEdges(body);\n if (edges) {\n if (body.getAttribute(\"data-scroll-fade\") !== edges) body.setAttribute(\"data-scroll-fade\", edges);\n } else if (body.hasAttribute(\"data-scroll-fade\")) body.removeAttribute(\"data-scroll-fade\");\n };\n const resize = new ResizeObserver(update);\n const observe = () => {\n resize.disconnect();\n resize.observe(body);\n for (const child of Array.from(body.children)) resize.observe(child);\n update();\n };\n const mutations = new MutationObserver((records) => {\n if (records.some((record) => record.type === \"childList\" && record.target === body)) observe();\n else update();\n });\n mutations.observe(body, {\n childList: true,\n subtree: true,\n characterData: true,\n attributes: true,\n attributeFilter: [\"class\", \"style\", \"hidden\", \"open\", \"data-scroll-fade-mode\", \"data-scroll-fade-axis\", \"dir\"],\n });\n body.addEventListener(\"scroll\", update, { passive: true });\n observe();\n entry = {\n users: 0,\n stop: () => {\n resize.disconnect();\n mutations.disconnect();\n body.removeEventListener(\"scroll\", update);\n body.removeAttribute(\"data-scroll-fade\");\n },\n };\n active.set(body, entry);\n }\n entry.users++;\n return () => {\n if (--entry.users === 0) {\n entry.stop();\n active.delete(body);\n }\n };\n}\n\nexport function createScrollFade(element: () => HTMLElement | undefined, enabled: () => boolean) {\n createEffect(() => {\n if (!enabled()) return;\n const body = element();\n if (body) onCleanup(observeScrollFade(body));\n });\n}\n\n/** Enrich only explicitly marked UI scrollports, including SSR and later navigation. */\nexport function installScrollFades(root: Document | HTMLElement) {\n const owned = new Map<HTMLElement, () => void>();\n const sync = () => {\n const next = new Set(Array.from(root.querySelectorAll<HTMLElement>(selector)));\n if (root instanceof HTMLElement && root.matches(selector)) next.add(root);\n for (const [element, stop] of owned)\n if (!next.has(element)) {\n stop();\n owned.delete(element);\n }\n for (const element of next) if (!owned.has(element)) owned.set(element, observeScrollFade(element));\n };\n const containsPort = (node: Node) => node instanceof Element && (node.matches(selector) || node.querySelector(selector));\n const mutations = new MutationObserver((records) => {\n if (\n records.some(\n (record) =>\n record.type === \"attributes\" ||\n Array.from(record.addedNodes).some(containsPort) ||\n Array.from(record.removedNodes).some(containsPort),\n )\n )\n sync();\n });\n mutations.observe(root, { childList: true, subtree: true, attributes: true, attributeFilter: [\"data-scroll-fade-mode\"] });\n sync();\n return () => {\n mutations.disconnect();\n for (const stop of owned.values()) stop();\n owned.clear();\n };\n}\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":[],"sources":["layout/scroll-fade.ts"],"sourcesContent":["import { createEffect, onCleanup } from \"solid-js\";\n\nconst selector = \"[data-scroll-fade-mode]\";\nconst active = new WeakMap<HTMLElement, { users: number; measure: () => void; stop: () => void }>();\n\n/** Self-contained because the sidebar inline script embeds its source. */\nexport function scrollFadeEdges(body: HTMLElement): \"top\" | \"bottom\" | \"both\" | undefined {\n const mode = body.getAttribute(\"data-scroll-fade-mode\");\n const horizontal = body.getAttribute(\"data-scroll-fade-axis\") === \"horizontal\";\n const overflow = horizontal ? body.scrollWidth - body.clientWidth : body.scrollHeight - body.clientHeight;\n // Horizontal RTL scrollLeft starts at zero on the right and becomes negative.\n const rtl = horizontal && getComputedStyle(body).direction === \"rtl\";\n const offset = horizontal ? (rtl ? overflow + body.scrollLeft : body.scrollLeft) : body.scrollTop;\n const top = mode === \"both\" && overflow > 1 && offset > 1;\n const bottom = !!mode && overflow > 1 && overflow - offset > 1;\n return top && bottom ? \"both\" : top ? \"top\" : bottom ? \"bottom\" : undefined;\n}\n\n/** Shared by hydrated components and the workspace's server-rendered scrollports. */\nfunction observeScrollFade(body: HTMLElement) {\n let entry = active.get(body);\n if (!entry) {\n const apply = () => {\n const edges = scrollFadeEdges(body);\n if (edges) {\n if (body.getAttribute(\"data-scroll-fade\") !== edges) body.setAttribute(\"data-scroll-fade\", edges);\n } else if (body.hasAttribute(\"data-scroll-fade\")) body.removeAttribute(\"data-scroll-fade\");\n };\n // Measuring forces layout. Scrolling (the browser sends one scroll event per frame) and changes to the scrollport\n // itself measure at once; changes of its content are measured once per frame. A list that updates many rows at\n // once, such as marking every chat read, otherwise lays the page out again for each row, and a measurement in the\n // middle of a large change can delay the next frame enough to count as a layout shift. A reader that needs the\n // current edges before the frame ends calls `measureScrollFade`.\n let frame = 0;\n const measure = () => {\n if (frame) cancelAnimationFrame(frame);\n frame = 0;\n apply();\n };\n const update = () => {\n if (!frame)\n frame = requestAnimationFrame(() => {\n frame = 0;\n apply();\n });\n };\n const resize = new ResizeObserver(update);\n const observe = () => {\n resize.disconnect();\n resize.observe(body);\n for (const child of Array.from(body.children)) resize.observe(child);\n measure();\n };\n const mutations = new MutationObserver((records) => {\n if (records.some((record) => record.type === \"childList\" && record.target === body)) observe();\n else if (records.some((record) => record.target === body)) apply();\n else update();\n });\n mutations.observe(body, {\n childList: true,\n subtree: true,\n characterData: true,\n attributes: true,\n attributeFilter: [\"class\", \"style\", \"hidden\", \"open\", \"data-scroll-fade-mode\", \"data-scroll-fade-axis\", \"dir\"],\n });\n body.addEventListener(\"scroll\", apply, { passive: true });\n observe();\n entry = {\n users: 0,\n measure,\n stop: () => {\n if (frame) cancelAnimationFrame(frame);\n resize.disconnect();\n mutations.disconnect();\n body.removeEventListener(\"scroll\", apply);\n body.removeAttribute(\"data-scroll-fade\");\n },\n };\n active.set(body, entry);\n }\n entry.users++;\n return () => {\n if (--entry.users === 0) {\n entry.stop();\n active.delete(body);\n }\n };\n}\n\n/**\n * Measures an observed scrollport's fades now instead of at the end of the frame. Call it before reading the fades in\n * the same frame as a change of the scrollport's content, as an editor does when it keeps its cursor clear of them.\n */\nexport function measureScrollFade(element: HTMLElement) {\n active.get(element)?.measure();\n}\n\nexport function createScrollFade(element: () => HTMLElement | undefined, enabled: () => boolean) {\n createEffect(() => {\n if (!enabled()) return;\n const body = element();\n if (body) onCleanup(observeScrollFade(body));\n });\n}\n\n/** Enrich only explicitly marked UI scrollports, including SSR and later navigation. */\nexport function installScrollFades(root: Document | HTMLElement) {\n const owned = new Map<HTMLElement, () => void>();\n const sync = () => {\n const next = new Set(Array.from(root.querySelectorAll<HTMLElement>(selector)));\n if (root instanceof HTMLElement && root.matches(selector)) next.add(root);\n for (const [element, stop] of owned)\n if (!next.has(element)) {\n stop();\n owned.delete(element);\n }\n for (const element of next) if (!owned.has(element)) owned.set(element, observeScrollFade(element));\n };\n const containsPort = (node: Node) => node instanceof Element && (node.matches(selector) || node.querySelector(selector));\n const mutations = new MutationObserver((records) => {\n if (\n records.some(\n (record) =>\n record.type === \"attributes\" ||\n Array.from(record.addedNodes).some(containsPort) ||\n Array.from(record.removedNodes).some(containsPort),\n )\n )\n sync();\n });\n mutations.observe(root, { childList: true, subtree: true, attributes: true, attributeFilter: [\"data-scroll-fade-mode\"] });\n sync();\n return () => {\n mutations.disconnect();\n for (const stop of owned.values()) stop();\n owned.clear();\n };\n}\n"],"mappings":"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","ignoreList":[]}
|