@eifi1/ui-kit 0.39.1 → 0.40.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/README.md +8 -7
- package/dist/billing/billing-overview.d.ts +10 -0
- package/dist/components/autocomplete.js +5 -1
- package/dist/components/autocomplete.js.map +1 -1
- package/dist/components/combobox-core.d.ts +14 -1
- package/dist/components/combobox-core.js +4 -0
- package/dist/components/combobox-core.js.map +1 -1
- package/dist/components/combobox.js +9 -3
- package/dist/components/combobox.js.map +1 -1
- package/dist/components/data-table-labels.d.ts +5 -0
- package/dist/components/data-table-labels.js +2 -0
- package/dist/components/data-table-labels.js.map +1 -1
- package/dist/components/data-table-mobile.d.ts +36 -1
- package/dist/components/data-table-mobile.js +162 -15
- package/dist/components/data-table-mobile.js.map +1 -1
- package/dist/components/data-table.d.ts +39 -12
- package/dist/components/data-table.js +74 -13
- package/dist/components/data-table.js.map +1 -1
- package/dist/components/inline-entity-combobox.js +10 -3
- package/dist/components/inline-entity-combobox.js.map +1 -1
- package/dist/components/picker-sheet.d.ts +18 -1
- package/dist/components/picker-sheet.js +20 -2
- package/dist/components/picker-sheet.js.map +1 -1
- package/dist/components/tabs.d.ts +26 -2
- package/dist/components/tabs.js +41 -2
- package/dist/components/tabs.js.map +1 -1
- package/dist/components/translation-review-parts.d.ts +2 -1
- package/dist/components/translation-review-parts.js +1 -1
- package/dist/components/translation-review-parts.js.map +1 -1
- package/dist/components/ui-labels.js +3 -1
- package/dist/components/ui-labels.js.map +1 -1
- package/dist/eslint/index.js +1 -1
- package/dist/feedback/feedback-comment-thread.d.ts +8 -1
- package/dist/feedback/feedback-comment-thread.js +26 -1
- package/dist/feedback/feedback-comment-thread.js.map +1 -1
- package/dist/feedback/feedback-labels.d.ts +2 -1
- package/dist/feedback/feedback-labels.js +1 -0
- package/dist/feedback/feedback-labels.js.map +1 -1
- package/dist/feedback/feedback-menu-labels.js +3 -1
- package/dist/feedback/feedback-menu-labels.js.map +1 -1
- package/dist/feedback/feedback-menu.d.ts +31 -24
- package/dist/feedback/feedback-menu.js +16 -7
- package/dist/feedback/feedback-menu.js.map +1 -1
- package/dist/feedback/feedback-public-labels.d.ts +3 -2
- package/dist/feedback/feedback-public-labels.js +1 -1
- package/dist/feedback/feedback-public-labels.js.map +1 -1
- package/dist/feedback/feedback-public-list.d.ts +4 -1
- package/dist/feedback/feedback-public-list.js +67 -55
- package/dist/feedback/feedback-public-list.js.map +1 -1
- package/dist/feedback/feedback-public-types.d.ts +16 -3
- package/dist/feedback/feedback-record.d.ts +20 -3
- package/dist/feedback/feedback-record.js +15 -0
- package/dist/feedback/feedback-record.js.map +1 -1
- package/dist/feedback/feedback-replies.d.ts +13 -2
- package/dist/feedback/feedback-replies.js +67 -33
- package/dist/feedback/feedback-replies.js.map +1 -1
- package/dist/feedback/feedback-rework-entry-chip.d.ts +9 -0
- package/dist/feedback/feedback-rework-entry-chip.js +13 -0
- package/dist/feedback/feedback-rework-entry-chip.js.map +1 -0
- package/dist/feedback/feedback-row-detail.d.ts +31 -8
- package/dist/feedback/feedback-row-detail.js +31 -7
- package/dist/feedback/feedback-row-detail.js.map +1 -1
- package/dist/feedback/feedback-table-labels.js +1 -1
- package/dist/feedback/feedback-table-labels.js.map +1 -1
- package/dist/feedback/feedback-table.d.ts +5 -2
- package/dist/feedback/feedback-table.js +2 -2
- package/dist/feedback/feedback-table.js.map +1 -1
- package/dist/feedback/feedback-thread.js +3 -1
- package/dist/feedback/feedback-thread.js.map +1 -1
- package/dist/feedback/feedback-vocabulary.d.ts +9 -6
- package/dist/feedback/feedback-vocabulary.js +16 -1
- package/dist/feedback/feedback-vocabulary.js.map +1 -1
- package/dist/hooks/use-long-press.d.ts +30 -0
- package/dist/hooks/use-long-press.js +77 -0
- package/dist/hooks/use-long-press.js.map +1 -0
- package/dist/hooks/use-overlay-history.js +37 -3
- package/dist/hooks/use-overlay-history.js.map +1 -1
- package/dist/i18n/german.js +13 -5
- package/dist/i18n/german.js.map +1 -1
- package/dist/i18n/kit-labels.d.ts +3 -0
- package/dist/i18n/kit-labels.js.map +1 -1
- package/dist/i18n/locales/en.js +12 -5
- package/dist/i18n/locales/en.js.map +2 -2
- package/dist/i18n/locales/es.js +13 -5
- package/dist/i18n/locales/es.js.map +1 -1
- package/dist/i18n/locales/fr.js +13 -5
- package/dist/i18n/locales/fr.js.map +1 -1
- package/dist/i18n/locales/hu.js +13 -5
- package/dist/i18n/locales/hu.js.map +1 -1
- package/dist/i18n/locales/it.js +13 -5
- package/dist/i18n/locales/it.js.map +1 -1
- package/dist/i18n/locales/zh.js +13 -5
- package/dist/i18n/locales/zh.js.map +1 -1
- package/dist/i18n/shared-labels.js +1 -1
- package/dist/i18n/shared-labels.js.map +1 -1
- package/dist/shell/app-shell.js +9 -0
- package/dist/shell/app-shell.js.map +1 -1
- package/dist/shell/fill-height.d.ts +38 -0
- package/dist/shell/fill-height.js +12 -0
- package/dist/shell/fill-height.js.map +1 -0
- package/dist/shell.d.ts +2 -0
- package/dist/shell.js +3 -0
- package/dist/shell.js.map +1 -1
- package/package.json +1 -1
- package/src/billing/billing-overview.ts +10 -0
- package/src/components/autocomplete.tsx +5 -1
- package/src/components/combobox-core.tsx +20 -1
- package/src/components/combobox.tsx +9 -3
- package/src/components/data-table-labels.ts +7 -0
- package/src/components/data-table-mobile.tsx +193 -9
- package/src/components/data-table.tsx +141 -24
- package/src/components/inline-entity-combobox.tsx +12 -4
- package/src/components/picker-sheet.tsx +38 -1
- package/src/components/tabs.tsx +73 -3
- package/src/components/translation-review-parts.tsx +3 -2
- package/src/components/ui-labels.ts +2 -0
- package/src/feedback/feedback-comment-thread.tsx +39 -1
- package/src/feedback/feedback-labels.ts +3 -1
- package/src/feedback/feedback-menu-labels.ts +2 -0
- package/src/feedback/feedback-menu.tsx +48 -30
- package/src/feedback/feedback-public-labels.ts +4 -3
- package/src/feedback/feedback-public-list.tsx +15 -2
- package/src/feedback/feedback-public-types.ts +17 -3
- package/src/feedback/feedback-record.ts +34 -3
- package/src/feedback/feedback-replies.tsx +100 -31
- package/src/feedback/feedback-rework-entry-chip.tsx +18 -0
- package/src/feedback/feedback-row-detail.tsx +65 -12
- package/src/feedback/feedback-table-labels.ts +1 -1
- package/src/feedback/feedback-table.tsx +7 -4
- package/src/feedback/feedback-thread.tsx +5 -1
- package/src/feedback/feedback-vocabulary.ts +27 -6
- package/src/hooks/use-long-press.ts +126 -0
- package/src/hooks/use-overlay-history.ts +74 -3
- package/src/i18n/german.ts +10 -2
- package/src/i18n/kit-labels.tsx +3 -0
- package/src/i18n/locales/es.ts +10 -2
- package/src/i18n/locales/fr.ts +10 -2
- package/src/i18n/locales/hu.ts +10 -2
- package/src/i18n/locales/it.ts +10 -2
- package/src/i18n/locales/zh.ts +10 -2
- package/src/i18n/shared-labels.ts +1 -1
- package/src/shell/app-shell.tsx +9 -0
- package/src/shell/fill-height.tsx +45 -0
- package/src/shell.ts +3 -0
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { useCallback, useEffect, useRef, type PointerEvent as ReactPointerEvent } from "react";
|
|
2
|
+
|
|
3
|
+
// The press-and-hold that puts DataTable's phone cards into selection mode (0.40,
|
|
4
|
+
// keksdose live #421). Taken over from keksdose's register list
|
|
5
|
+
// (frontend/src/shared/hooks/use-long-press.ts, its feedback #153) so the kit's cards
|
|
6
|
+
// and kk's register answer the same gesture the same way: 500 ms, an 8 px dead zone,
|
|
7
|
+
// cancelled by a scroll, the trailing click swallowed.
|
|
8
|
+
|
|
9
|
+
const LONG_PRESS_MS = 500;
|
|
10
|
+
/** The same 8 px dead zone `useRowSwipe` locks its axis at: the press is dead by the
|
|
11
|
+
* time the swipe hook takes pointer capture on its (ancestor) layer. */
|
|
12
|
+
const SLOP_PX = 8;
|
|
13
|
+
|
|
14
|
+
const movedBeyondSlop = (from: { x: number; y: number }, x: number, y: number) =>
|
|
15
|
+
Math.hypot(x - from.x, y - from.y) > SLOP_PX;
|
|
16
|
+
|
|
17
|
+
export interface LongPressResult {
|
|
18
|
+
handlers: {
|
|
19
|
+
onPointerDown: (e: ReactPointerEvent) => void;
|
|
20
|
+
onPointerMove: (e: ReactPointerEvent) => void;
|
|
21
|
+
onContextMenu: (e: { preventDefault: () => void }) => void;
|
|
22
|
+
};
|
|
23
|
+
/** True exactly once after a long press fired: call it from an `onClickCapture` to
|
|
24
|
+
* swallow the click the browser still sends when the finger lifts. */
|
|
25
|
+
consumeClick: () => boolean;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* A press-and-hold on a touch row that may ALSO be swipeable.
|
|
30
|
+
*
|
|
31
|
+
* - The cancel listeners live on `window`: `useRowSwipe` captures the pointer on an
|
|
32
|
+
* ancestor once a drag resolves to the x axis, after which the pressed element's
|
|
33
|
+
* own pointer handlers stop firing, and a timer cancelled only there would fire
|
|
34
|
+
* mid-swipe.
|
|
35
|
+
* - A scroll cancels too (`touch-action: pan-y` hands vertical panning to the
|
|
36
|
+
* browser, which sends `pointercancel`; the capture-phase `scroll` is the backstop).
|
|
37
|
+
* - `contextmenu` is suppressed while enabled — Android fires it at ~500 ms. Pair it
|
|
38
|
+
* with `select-none [-webkit-touch-callout:none]` on the element: iOS's callout
|
|
39
|
+
* only yields to that CSS.
|
|
40
|
+
*/
|
|
41
|
+
export function useLongPress(
|
|
42
|
+
onLongPress: () => void,
|
|
43
|
+
{ enabled = true, delay = LONG_PRESS_MS }: { enabled?: boolean; delay?: number } = {},
|
|
44
|
+
): LongPressResult {
|
|
45
|
+
const timer = useRef<number | null>(null);
|
|
46
|
+
const start = useRef({ x: 0, y: 0 });
|
|
47
|
+
const fired = useRef(false);
|
|
48
|
+
const teardown = useRef<(() => void) | null>(null);
|
|
49
|
+
const cbRef = useRef(onLongPress);
|
|
50
|
+
useEffect(() => {
|
|
51
|
+
cbRef.current = onLongPress;
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
const cancel = useCallback(() => {
|
|
55
|
+
if (timer.current !== null) {
|
|
56
|
+
window.clearTimeout(timer.current);
|
|
57
|
+
timer.current = null;
|
|
58
|
+
}
|
|
59
|
+
teardown.current?.();
|
|
60
|
+
teardown.current = null;
|
|
61
|
+
}, []);
|
|
62
|
+
|
|
63
|
+
const onPointerDown = useCallback(
|
|
64
|
+
(e: ReactPointerEvent) => {
|
|
65
|
+
// Cleared above every early return: a press whose trailing click never arrives
|
|
66
|
+
// (the finger lifted over another row) would otherwise leave the latch armed,
|
|
67
|
+
// and it would eat the next real tap once the card has switched modes.
|
|
68
|
+
fired.current = false;
|
|
69
|
+
if (!enabled) return;
|
|
70
|
+
if (e.pointerType === "mouse" && e.button !== 0) return;
|
|
71
|
+
cancel();
|
|
72
|
+
start.current = { x: e.clientX, y: e.clientY };
|
|
73
|
+
|
|
74
|
+
const onEnd = () => cancel();
|
|
75
|
+
const onMove = (ev: PointerEvent) => {
|
|
76
|
+
if (movedBeyondSlop(start.current, ev.clientX, ev.clientY)) cancel();
|
|
77
|
+
};
|
|
78
|
+
window.addEventListener("pointerup", onEnd);
|
|
79
|
+
window.addEventListener("pointercancel", onEnd);
|
|
80
|
+
window.addEventListener("pointermove", onMove);
|
|
81
|
+
window.addEventListener("scroll", onEnd, { capture: true, passive: true });
|
|
82
|
+
teardown.current = () => {
|
|
83
|
+
window.removeEventListener("pointerup", onEnd);
|
|
84
|
+
window.removeEventListener("pointercancel", onEnd);
|
|
85
|
+
window.removeEventListener("pointermove", onMove);
|
|
86
|
+
window.removeEventListener("scroll", onEnd, { capture: true });
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
timer.current = window.setTimeout(() => {
|
|
90
|
+
cancel();
|
|
91
|
+
fired.current = true;
|
|
92
|
+
// The swipe stages' haptic vocabulary; absent on iOS Safari.
|
|
93
|
+
navigator.vibrate?.(20);
|
|
94
|
+
cbRef.current();
|
|
95
|
+
}, delay);
|
|
96
|
+
},
|
|
97
|
+
[cancel, delay, enabled],
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
// Also on the element: it still cancels if an ancestor stops the native event
|
|
101
|
+
// before it reaches `window`.
|
|
102
|
+
const onPointerMove = useCallback(
|
|
103
|
+
(e: ReactPointerEvent) => {
|
|
104
|
+
if (timer.current === null) return;
|
|
105
|
+
if (movedBeyondSlop(start.current, e.clientX, e.clientY)) cancel();
|
|
106
|
+
},
|
|
107
|
+
[cancel],
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
const onContextMenu = useCallback(
|
|
111
|
+
(e: { preventDefault: () => void }) => {
|
|
112
|
+
if (enabled) e.preventDefault();
|
|
113
|
+
},
|
|
114
|
+
[enabled],
|
|
115
|
+
);
|
|
116
|
+
|
|
117
|
+
const consumeClick = useCallback(() => {
|
|
118
|
+
if (!fired.current) return false;
|
|
119
|
+
fired.current = false;
|
|
120
|
+
return true;
|
|
121
|
+
}, []);
|
|
122
|
+
|
|
123
|
+
useEffect(() => cancel, [cancel]);
|
|
124
|
+
|
|
125
|
+
return { handlers: { onPointerDown, onPointerMove, onContextMenu }, consumeClick };
|
|
126
|
+
}
|
|
@@ -48,6 +48,16 @@ import { useEffect, useRef } from "react";
|
|
|
48
48
|
* {@link noteAddress}: an address the overlay LIVED THROUGH (a filter the table wrote
|
|
49
49
|
* while its sheet was up) is still unwound, because the user has acted since.
|
|
50
50
|
*
|
|
51
|
+
* ## Not undoing the owner's replaces either
|
|
52
|
+
*
|
|
53
|
+
* An address the overlay lived through is unwound as an ENTRY, never as an address
|
|
54
|
+
* (keksdose live #412). A report that writes each tick of its payee sheet into the query
|
|
55
|
+
* with `setSearchParams(…, { replace: true })` rewrites the overlay's own entry, and the
|
|
56
|
+
* page entry beneath still carries the address from before the sheet opened — so the
|
|
57
|
+
* traversal that took our entry away also took every tick with it. See {@link carryOnto}:
|
|
58
|
+
* whichever way the entry goes (the unwind after a press, or a Back press), the address it
|
|
59
|
+
* last showed is carried onto the entry it lands on, and the router is told.
|
|
60
|
+
*
|
|
51
61
|
* ## The traversal is deferred
|
|
52
62
|
*
|
|
53
63
|
* And it is *scheduled* rather than issued, because `history.go()` lands a task
|
|
@@ -99,6 +109,10 @@ interface PushedEntry {
|
|
|
99
109
|
key: string | undefined;
|
|
100
110
|
/** {@link routeOf} the address the marker was placed at. */
|
|
101
111
|
route: string;
|
|
112
|
+
/** The entry's address as last OBSERVED, after the user's last gesture had run its
|
|
113
|
+
* handlers — what a Back press must carry down (see {@link carryOnto}). `href` is
|
|
114
|
+
* the snapshot BEFORE the gesture, which the owner's-close check needs instead. */
|
|
115
|
+
seen: string;
|
|
102
116
|
}
|
|
103
117
|
const pushed: PushedEntry[] = [];
|
|
104
118
|
|
|
@@ -197,10 +211,41 @@ function runUnwind(): void {
|
|
|
197
211
|
if (taggedSentinel() === null) buryUnder(job.entries);
|
|
198
212
|
return;
|
|
199
213
|
}
|
|
214
|
+
const bottom = job.entries[0];
|
|
215
|
+
carry = { href: job.href, idx: bottom.idx, key: bottom.key };
|
|
200
216
|
pendingProgrammatic += 1;
|
|
201
217
|
window.history.go(-job.entries.length);
|
|
202
218
|
}
|
|
203
219
|
|
|
220
|
+
/** The address an unwind in flight must carry onto the entry it lands on. */
|
|
221
|
+
let carry: { href: string; idx: number | undefined; key: string | undefined } | null = null;
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Put `href` — the address the overlay's entry last showed — onto the entry a traversal
|
|
225
|
+
* has just landed on, and tell the router (keksdose live #412).
|
|
226
|
+
*
|
|
227
|
+
* Only the query and the hash can differ: an address naming another page is a
|
|
228
|
+
* navigation, never carried. And only onto the page entry the overlay was opened over,
|
|
229
|
+
* which our push copied the router's `{idx, key}` from — a traversal that came to rest
|
|
230
|
+
* anywhere else is not ours to rewrite.
|
|
231
|
+
*
|
|
232
|
+
* The router heard the traversal land on the OLD address in this same event, so a
|
|
233
|
+
* `replaceState` alone would leave it showing the old query under the new one. A
|
|
234
|
+
* synthetic `popstate` makes it read the address again; both reads happen in one event
|
|
235
|
+
* dispatch, so React commits only the second. Ours absorbs it as programmatic.
|
|
236
|
+
*/
|
|
237
|
+
function carryOnto(href: string, mark: { idx: number | undefined; key: string | undefined }): void {
|
|
238
|
+
const here = currentHref();
|
|
239
|
+
if (here === href || routeOf(here) !== routeOf(href)) return;
|
|
240
|
+
const now = routerMark();
|
|
241
|
+
if (mark.idx !== undefined && now.idx !== undefined && mark.idx !== now.idx) return;
|
|
242
|
+
if (mark.key !== undefined && now.key !== undefined && mark.key !== now.key) return;
|
|
243
|
+
const state: unknown = window.history.state;
|
|
244
|
+
window.history.replaceState(state, "", href);
|
|
245
|
+
pendingProgrammatic += 1;
|
|
246
|
+
window.dispatchEvent(new PopStateEvent("popstate", { state }));
|
|
247
|
+
}
|
|
248
|
+
|
|
204
249
|
function currentHref(): string {
|
|
205
250
|
return typeof window === "undefined" ? "" : window.location.href;
|
|
206
251
|
}
|
|
@@ -416,7 +461,25 @@ function noteAddress(): void {
|
|
|
416
461
|
if (!top || top.dead || !stack.some((e) => e.id === top.id)) return;
|
|
417
462
|
const tag = taggedSentinel();
|
|
418
463
|
// Read without `currentSentinel`'s repair: an observation must not write history.
|
|
419
|
-
if (tag === top.id || (tag === null && standing === top.id && isStillOn(top)))
|
|
464
|
+
if (tag === top.id || (tag === null && standing === top.id && isStillOn(top))) {
|
|
465
|
+
top.href = currentHref();
|
|
466
|
+
top.seen = top.href;
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
/** After the user's gesture has run its handlers: the address its entry now shows —
|
|
471
|
+
* what a Back press must carry down (keksdose live #412). Again a little later, for a
|
|
472
|
+
* handler that writes the address a task after the event. */
|
|
473
|
+
function noteSeen(): void {
|
|
474
|
+
const top = pushed[pushed.length - 1];
|
|
475
|
+
if (!top || top.dead || !stack.some((e) => e.id === top.id)) return;
|
|
476
|
+
const tag = taggedSentinel();
|
|
477
|
+
if (tag === top.id || (tag === null && standing === top.id && isStillOn(top))) top.seen = currentHref();
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
function noteSeenNowAndLater(): void {
|
|
481
|
+
noteSeen();
|
|
482
|
+
setTimeout(noteSeen, 0);
|
|
420
483
|
}
|
|
421
484
|
|
|
422
485
|
function handlePop() {
|
|
@@ -428,6 +491,9 @@ function handlePop() {
|
|
|
428
491
|
lastSeen = routerMark();
|
|
429
492
|
if (pendingProgrammatic > 0) {
|
|
430
493
|
pendingProgrammatic -= 1;
|
|
494
|
+
const job = carry;
|
|
495
|
+
carry = null;
|
|
496
|
+
if (job) carryOnto(job.href, job);
|
|
431
497
|
return;
|
|
432
498
|
}
|
|
433
499
|
closeOnPop();
|
|
@@ -451,7 +517,10 @@ function closeOnPop() {
|
|
|
451
517
|
// The browser consumed this entry, so the overlay's own cleanup has nothing left
|
|
452
518
|
// to unwind and nothing to record as owed.
|
|
453
519
|
consumed.add(top.id);
|
|
520
|
+
const record = pushed.find((p) => p.id === top.id);
|
|
454
521
|
forgetPushed(top.id);
|
|
522
|
+
// What the page wrote into the address while we were up stays (#412).
|
|
523
|
+
if (record && !record.dead) carryOnto(record.seen, record);
|
|
455
524
|
top.close();
|
|
456
525
|
}
|
|
457
526
|
|
|
@@ -460,6 +529,7 @@ function ensureListening() {
|
|
|
460
529
|
window.addEventListener("popstate", handlePop);
|
|
461
530
|
window.addEventListener("pointerdown", noteAddress, true);
|
|
462
531
|
window.addEventListener("keydown", noteAddress, true);
|
|
532
|
+
for (const type of ["click", "keyup", "change", "input"]) window.addEventListener(type, noteSeenNowAndLater);
|
|
463
533
|
listening = true;
|
|
464
534
|
}
|
|
465
535
|
|
|
@@ -501,7 +571,7 @@ export function useOverlayHistory(open: boolean, onClose: () => void): void {
|
|
|
501
571
|
// The abandoned ones beneath come back owed; ours takes the top slot.
|
|
502
572
|
for (const owed of inherited.slice(0, -1)) pushed.push({ ...owed, dead: true });
|
|
503
573
|
const was = inherited[inherited.length - 1];
|
|
504
|
-
pushed.push({ id, href: currentHref(), dead: false, idx: was.idx, key: was.key, route: was.route });
|
|
574
|
+
pushed.push({ id, href: currentHref(), seen: currentHref(), dead: false, idx: was.idx, key: was.key, route: was.route });
|
|
505
575
|
standing = id;
|
|
506
576
|
} else {
|
|
507
577
|
// A push DESTROYS every entry ahead of the one we are on, so anything we
|
|
@@ -516,7 +586,8 @@ export function useOverlayHistory(open: boolean, onClose: () => void): void {
|
|
|
516
586
|
// the URL is unchanged, so the router treats popping this as a no-op re-render.
|
|
517
587
|
window.history.pushState(marked, "");
|
|
518
588
|
const page = routerMark();
|
|
519
|
-
|
|
589
|
+
const at = currentHref();
|
|
590
|
+
pushed.push({ id, href: at, seen: at, dead: false, idx: page.idx, key: page.key, route: routeOf(at) });
|
|
520
591
|
standing = id;
|
|
521
592
|
}
|
|
522
593
|
return () => {
|
package/src/i18n/german.ts
CHANGED
|
@@ -85,6 +85,7 @@ export function germanLabels(numberLocale: string): UiKitLabels {
|
|
|
85
85
|
feedbackStatus: {
|
|
86
86
|
OPEN: "Offen",
|
|
87
87
|
READY: "Bereit zur Umsetzung",
|
|
88
|
+
REWORK: "Nacharbeit angefordert",
|
|
88
89
|
IN_PROGRESS: "In Bearbeitung",
|
|
89
90
|
IN_EVALUATION: "Zur Prüfung",
|
|
90
91
|
NEEDS_LIVE_TEST: "Live testen",
|
|
@@ -122,11 +123,13 @@ export function germanLabels(numberLocale: string): UiKitLabels {
|
|
|
122
123
|
myFeedback: "Mein Feedback",
|
|
123
124
|
viewFeedback: "Feedback ansehen",
|
|
124
125
|
allFeedback: "Alle Rückmeldungen",
|
|
126
|
+
discussion: "Feedback-Diskussion",
|
|
127
|
+
inbox: "Feedback-Eingang",
|
|
125
128
|
},
|
|
126
129
|
// 0.38.0 — docs/feedback-harmonization.md §9: the public pages and the two feedback
|
|
127
130
|
// notification types. "Rückmeldungen" and "Eine Person" are the contract's (§9.2, §9.5).
|
|
128
131
|
feedbackPublic: {
|
|
129
|
-
title: "
|
|
132
|
+
title: "Feedback-Diskussion",
|
|
130
133
|
sort: "Sortieren",
|
|
131
134
|
sortNewest: "Neueste",
|
|
132
135
|
sortVotes: "Meistgewünscht",
|
|
@@ -158,7 +161,7 @@ export function germanLabels(numberLocale: string): UiKitLabels {
|
|
|
158
161
|
attachUrl: "Aktuelle Seiten-URL anhängen",
|
|
159
162
|
},
|
|
160
163
|
feedbackPage: {
|
|
161
|
-
title: "Feedback",
|
|
164
|
+
title: "Feedback-Eingang",
|
|
162
165
|
myTitle: "Mein Feedback",
|
|
163
166
|
columnId: "#",
|
|
164
167
|
columnDate: "Datum",
|
|
@@ -344,6 +347,8 @@ export function germanLabels(numberLocale: string): UiKitLabels {
|
|
|
344
347
|
filter: "Filter",
|
|
345
348
|
close: "Schließen",
|
|
346
349
|
selectRow: "Zeile auswählen",
|
|
350
|
+
selectRows: "Zeilen auswählen",
|
|
351
|
+
cancelSelection: "Abbrechen",
|
|
347
352
|
rowDetails: "Details",
|
|
348
353
|
autoSize: "Spaltenbreiten anpassen",
|
|
349
354
|
loading: "Wird geladen…",
|
|
@@ -534,6 +539,8 @@ export function germanLabels(numberLocale: string): UiKitLabels {
|
|
|
534
539
|
// "Tab" is what German UIs say; "Registerkarte" reads like a 1990s manual.
|
|
535
540
|
add: "Tab hinzufügen",
|
|
536
541
|
remove: (tab) => `${tab} entfernen`,
|
|
542
|
+
more: "Weitere Tabs",
|
|
543
|
+
backToFirst: "Zurück zum ersten Tab",
|
|
537
544
|
},
|
|
538
545
|
appShell: {
|
|
539
546
|
collapse: "Seitenleiste einklappen",
|
|
@@ -549,6 +556,7 @@ export function germanLabels(numberLocale: string): UiKitLabels {
|
|
|
549
556
|
},
|
|
550
557
|
pickerSheet: {
|
|
551
558
|
close: "Schließen",
|
|
559
|
+
done: "Fertig",
|
|
552
560
|
},
|
|
553
561
|
dialogFrame: {
|
|
554
562
|
close: "Schließen",
|
package/src/i18n/kit-labels.tsx
CHANGED
|
@@ -279,6 +279,9 @@ export interface TopBarLabels {
|
|
|
279
279
|
|
|
280
280
|
export interface PickerSheetLabels {
|
|
281
281
|
close: string;
|
|
282
|
+
/** The sticky footer button that closes a multi-select sheet once the rows are ticked
|
|
283
|
+
* (0.40) — the ticks are already applied, so it confirms rather than saves. */
|
|
284
|
+
done: string;
|
|
282
285
|
}
|
|
283
286
|
|
|
284
287
|
export interface SwipeableRowLabels {
|
package/src/i18n/locales/es.ts
CHANGED
|
@@ -76,6 +76,7 @@ export function uiKitLabelsEs(numberLocale = "es-ES"): UiKitLabels {
|
|
|
76
76
|
feedbackStatus: {
|
|
77
77
|
OPEN: "Abierto",
|
|
78
78
|
READY: "Listo para implementar",
|
|
79
|
+
REWORK: "Corrección solicitada",
|
|
79
80
|
IN_PROGRESS: "En curso",
|
|
80
81
|
IN_EVALUATION: "En evaluación",
|
|
81
82
|
NEEDS_LIVE_TEST: "Probar en producción",
|
|
@@ -113,11 +114,13 @@ export function uiKitLabelsEs(numberLocale = "es-ES"): UiKitLabels {
|
|
|
113
114
|
myFeedback: "Mis comentarios",
|
|
114
115
|
viewFeedback: "Ver comentarios",
|
|
115
116
|
allFeedback: "Todos los comentarios",
|
|
117
|
+
discussion: "Debate de comentarios",
|
|
118
|
+
inbox: "Comentarios recibidos",
|
|
116
119
|
},
|
|
117
120
|
// 0.38.0 — docs/feedback-harmonization.md §9: the public pages and the two feedback
|
|
118
121
|
// notification types. "Informe" for one report, so it never reads as "comentario".
|
|
119
122
|
feedbackPublic: {
|
|
120
|
-
title: "
|
|
123
|
+
title: "Debate de comentarios",
|
|
121
124
|
sort: "Ordenar",
|
|
122
125
|
sortNewest: "Más recientes",
|
|
123
126
|
sortVotes: "Más deseados",
|
|
@@ -149,7 +152,7 @@ export function uiKitLabelsEs(numberLocale = "es-ES"): UiKitLabels {
|
|
|
149
152
|
attachUrl: "Adjuntar la URL de la página actual",
|
|
150
153
|
},
|
|
151
154
|
feedbackPage: {
|
|
152
|
-
title: "Comentarios",
|
|
155
|
+
title: "Comentarios recibidos",
|
|
153
156
|
myTitle: "Mis comentarios",
|
|
154
157
|
columnId: "#",
|
|
155
158
|
columnDate: "Fecha",
|
|
@@ -335,6 +338,8 @@ export function uiKitLabelsEs(numberLocale = "es-ES"): UiKitLabels {
|
|
|
335
338
|
filter: "Filtrar",
|
|
336
339
|
close: "Cerrar",
|
|
337
340
|
selectRow: "Seleccionar fila",
|
|
341
|
+
selectRows: "Seleccionar filas",
|
|
342
|
+
cancelSelection: "Cancelar",
|
|
338
343
|
rowDetails: "Detalles",
|
|
339
344
|
autoSize: "Ajustar ancho de columnas",
|
|
340
345
|
loading: "Cargando…",
|
|
@@ -521,6 +526,8 @@ export function uiKitLabelsEs(numberLocale = "es-ES"): UiKitLabels {
|
|
|
521
526
|
tabs: {
|
|
522
527
|
add: "Añadir pestaña",
|
|
523
528
|
remove: (tab) => `Quitar ${tab}`,
|
|
529
|
+
more: "Más pestañas",
|
|
530
|
+
backToFirst: "Volver a la primera pestaña",
|
|
524
531
|
},
|
|
525
532
|
appShell: {
|
|
526
533
|
collapse: "Contraer barra lateral",
|
|
@@ -536,6 +543,7 @@ export function uiKitLabelsEs(numberLocale = "es-ES"): UiKitLabels {
|
|
|
536
543
|
},
|
|
537
544
|
pickerSheet: {
|
|
538
545
|
close: "Cerrar",
|
|
546
|
+
done: "Listo",
|
|
539
547
|
},
|
|
540
548
|
dialogFrame: {
|
|
541
549
|
close: "Cerrar",
|
package/src/i18n/locales/fr.ts
CHANGED
|
@@ -76,6 +76,7 @@ export function uiKitLabelsFr(numberLocale = "fr-FR"): UiKitLabels {
|
|
|
76
76
|
feedbackStatus: {
|
|
77
77
|
OPEN: "Ouvert",
|
|
78
78
|
READY: "Prêt à implémenter",
|
|
79
|
+
REWORK: "Reprise demandée",
|
|
79
80
|
IN_PROGRESS: "En cours",
|
|
80
81
|
IN_EVALUATION: "En évaluation",
|
|
81
82
|
NEEDS_LIVE_TEST: "À tester en production",
|
|
@@ -111,11 +112,13 @@ export function uiKitLabelsFr(numberLocale = "fr-FR"): UiKitLabels {
|
|
|
111
112
|
myFeedback: "Mes retours",
|
|
112
113
|
viewFeedback: "Voir les retours",
|
|
113
114
|
allFeedback: "Tous les retours",
|
|
115
|
+
discussion: "Discussion des retours",
|
|
116
|
+
inbox: "Retours reçus",
|
|
114
117
|
},
|
|
115
118
|
// 0.38.0 — docs/feedback-harmonization.md §9: the public pages and the two feedback
|
|
116
119
|
// notification types. "Retour" for a report, as `feedbackMenu`.
|
|
117
120
|
feedbackPublic: {
|
|
118
|
-
title: "
|
|
121
|
+
title: "Discussion des retours",
|
|
119
122
|
sort: "Trier",
|
|
120
123
|
sortNewest: "Plus récents",
|
|
121
124
|
sortVotes: "Plus demandés",
|
|
@@ -147,7 +150,7 @@ export function uiKitLabelsFr(numberLocale = "fr-FR"): UiKitLabels {
|
|
|
147
150
|
attachUrl: "Joindre l’URL de la page actuelle",
|
|
148
151
|
},
|
|
149
152
|
feedbackPage: {
|
|
150
|
-
title: "Retours",
|
|
153
|
+
title: "Retours reçus",
|
|
151
154
|
myTitle: "Mes retours",
|
|
152
155
|
columnId: "#",
|
|
153
156
|
columnDate: "Date",
|
|
@@ -341,6 +344,8 @@ export function uiKitLabelsFr(numberLocale = "fr-FR"): UiKitLabels {
|
|
|
341
344
|
filter: "Filtrer",
|
|
342
345
|
close: "Fermer",
|
|
343
346
|
selectRow: "Sélectionner la ligne",
|
|
347
|
+
selectRows: "Sélectionner des lignes",
|
|
348
|
+
cancelSelection: "Annuler",
|
|
344
349
|
rowDetails: "Détails",
|
|
345
350
|
autoSize: "Ajuster la largeur des colonnes",
|
|
346
351
|
loading: "Chargement…",
|
|
@@ -529,6 +534,8 @@ export function uiKitLabelsFr(numberLocale = "fr-FR"): UiKitLabels {
|
|
|
529
534
|
tabs: {
|
|
530
535
|
add: "Ajouter un onglet",
|
|
531
536
|
remove: (tab) => `Supprimer ${tab}`,
|
|
537
|
+
more: "Autres onglets",
|
|
538
|
+
backToFirst: "Retour au premier onglet",
|
|
532
539
|
},
|
|
533
540
|
appShell: {
|
|
534
541
|
collapse: "Réduire la barre latérale",
|
|
@@ -544,6 +551,7 @@ export function uiKitLabelsFr(numberLocale = "fr-FR"): UiKitLabels {
|
|
|
544
551
|
},
|
|
545
552
|
pickerSheet: {
|
|
546
553
|
close: "Fermer",
|
|
554
|
+
done: "Terminé",
|
|
547
555
|
},
|
|
548
556
|
dialogFrame: {
|
|
549
557
|
close: "Fermer",
|
package/src/i18n/locales/hu.ts
CHANGED
|
@@ -76,6 +76,7 @@ export function uiKitLabelsHu(numberLocale = "hu-HU"): UiKitLabels {
|
|
|
76
76
|
feedbackStatus: {
|
|
77
77
|
OPEN: "Nyitott",
|
|
78
78
|
READY: "Megvalósításra kész",
|
|
79
|
+
REWORK: "Átdolgozás kérve",
|
|
79
80
|
IN_PROGRESS: "Folyamatban",
|
|
80
81
|
IN_EVALUATION: "Értékelés alatt",
|
|
81
82
|
NEEDS_LIVE_TEST: "Élesben tesztelendő",
|
|
@@ -110,11 +111,13 @@ export function uiKitLabelsHu(numberLocale = "hu-HU"): UiKitLabels {
|
|
|
110
111
|
myFeedback: "Visszajelzéseim",
|
|
111
112
|
viewFeedback: "Visszajelzések megtekintése",
|
|
112
113
|
allFeedback: "Összes visszajelzés",
|
|
114
|
+
discussion: "Visszajelzések megvitatása",
|
|
115
|
+
inbox: "Beérkezett visszajelzések",
|
|
113
116
|
},
|
|
114
117
|
// 0.38.0 — docs/feedback-harmonization.md §9: the public pages and the two feedback
|
|
115
118
|
// notification types. A noun after a number stays singular in Hungarian.
|
|
116
119
|
feedbackPublic: {
|
|
117
|
-
title: "
|
|
120
|
+
title: "Visszajelzések megvitatása",
|
|
118
121
|
sort: "Rendezés",
|
|
119
122
|
sortNewest: "Legújabb",
|
|
120
123
|
sortVotes: "Legkeresettebb",
|
|
@@ -146,7 +149,7 @@ export function uiKitLabelsHu(numberLocale = "hu-HU"): UiKitLabels {
|
|
|
146
149
|
attachUrl: "Az aktuális oldal URL-jének csatolása",
|
|
147
150
|
},
|
|
148
151
|
feedbackPage: {
|
|
149
|
-
title: "
|
|
152
|
+
title: "Beérkezett visszajelzések",
|
|
150
153
|
myTitle: "Visszajelzéseim",
|
|
151
154
|
columnId: "#",
|
|
152
155
|
columnDate: "Dátum",
|
|
@@ -333,6 +336,8 @@ export function uiKitLabelsHu(numberLocale = "hu-HU"): UiKitLabels {
|
|
|
333
336
|
filter: "Szűrés",
|
|
334
337
|
close: "Bezárás",
|
|
335
338
|
selectRow: "Sor kijelölése",
|
|
339
|
+
selectRows: "Sorok kijelölése",
|
|
340
|
+
cancelSelection: "Mégse",
|
|
336
341
|
rowDetails: "Részletek",
|
|
337
342
|
autoSize: "Oszlopszélességek igazítása",
|
|
338
343
|
loading: "Betöltés…",
|
|
@@ -519,6 +524,8 @@ export function uiKitLabelsHu(numberLocale = "hu-HU"): UiKitLabels {
|
|
|
519
524
|
tabs: {
|
|
520
525
|
add: "Lap hozzáadása",
|
|
521
526
|
remove: (tab) => `${tab} eltávolítása`,
|
|
527
|
+
more: "További lapok",
|
|
528
|
+
backToFirst: "Vissza az első lapra",
|
|
522
529
|
},
|
|
523
530
|
appShell: {
|
|
524
531
|
collapse: "Oldalsáv összecsukása",
|
|
@@ -534,6 +541,7 @@ export function uiKitLabelsHu(numberLocale = "hu-HU"): UiKitLabels {
|
|
|
534
541
|
},
|
|
535
542
|
pickerSheet: {
|
|
536
543
|
close: "Bezárás",
|
|
544
|
+
done: "Kész",
|
|
537
545
|
},
|
|
538
546
|
dialogFrame: {
|
|
539
547
|
close: "Bezárás",
|
package/src/i18n/locales/it.ts
CHANGED
|
@@ -76,6 +76,7 @@ export function uiKitLabelsIt(numberLocale = "it-IT"): UiKitLabels {
|
|
|
76
76
|
feedbackStatus: {
|
|
77
77
|
OPEN: "Aperto",
|
|
78
78
|
READY: "Pronto da implementare",
|
|
79
|
+
REWORK: "Rielaborazione richiesta",
|
|
79
80
|
IN_PROGRESS: "In corso",
|
|
80
81
|
IN_EVALUATION: "In valutazione",
|
|
81
82
|
NEEDS_LIVE_TEST: "Da testare in produzione",
|
|
@@ -113,11 +114,13 @@ export function uiKitLabelsIt(numberLocale = "it-IT"): UiKitLabels {
|
|
|
113
114
|
myFeedback: "I miei feedback",
|
|
114
115
|
viewFeedback: "Visualizza feedback",
|
|
115
116
|
allFeedback: "Tutti i feedback",
|
|
117
|
+
discussion: "Discussione sui feedback",
|
|
118
|
+
inbox: "Feedback ricevuti",
|
|
116
119
|
},
|
|
117
120
|
// 0.38.0 — docs/feedback-harmonization.md §9: the public pages and the two feedback
|
|
118
121
|
// notification types. "Segnalazione" for one report; formal "Lei", as elsewhere.
|
|
119
122
|
feedbackPublic: {
|
|
120
|
-
title: "
|
|
123
|
+
title: "Discussione sui feedback",
|
|
121
124
|
sort: "Ordina",
|
|
122
125
|
sortNewest: "Più recenti",
|
|
123
126
|
sortVotes: "Più richiesti",
|
|
@@ -149,7 +152,7 @@ export function uiKitLabelsIt(numberLocale = "it-IT"): UiKitLabels {
|
|
|
149
152
|
attachUrl: "Allega l’URL della pagina corrente",
|
|
150
153
|
},
|
|
151
154
|
feedbackPage: {
|
|
152
|
-
title: "Feedback",
|
|
155
|
+
title: "Feedback ricevuti",
|
|
153
156
|
myTitle: "I miei feedback",
|
|
154
157
|
columnId: "#",
|
|
155
158
|
columnDate: "Data",
|
|
@@ -337,6 +340,8 @@ export function uiKitLabelsIt(numberLocale = "it-IT"): UiKitLabels {
|
|
|
337
340
|
filter: "Filtra",
|
|
338
341
|
close: "Chiudi",
|
|
339
342
|
selectRow: "Seleziona riga",
|
|
343
|
+
selectRows: "Seleziona righe",
|
|
344
|
+
cancelSelection: "Annulla",
|
|
340
345
|
rowDetails: "Dettagli",
|
|
341
346
|
autoSize: "Adatta larghezza colonne",
|
|
342
347
|
loading: "Caricamento…",
|
|
@@ -524,6 +529,8 @@ export function uiKitLabelsIt(numberLocale = "it-IT"): UiKitLabels {
|
|
|
524
529
|
tabs: {
|
|
525
530
|
add: "Aggiungi scheda",
|
|
526
531
|
remove: (tab) => `Rimuovi ${tab}`,
|
|
532
|
+
more: "Altre schede",
|
|
533
|
+
backToFirst: "Torna alla prima scheda",
|
|
527
534
|
},
|
|
528
535
|
appShell: {
|
|
529
536
|
collapse: "Comprimi barra laterale",
|
|
@@ -539,6 +546,7 @@ export function uiKitLabelsIt(numberLocale = "it-IT"): UiKitLabels {
|
|
|
539
546
|
},
|
|
540
547
|
pickerSheet: {
|
|
541
548
|
close: "Chiudi",
|
|
549
|
+
done: "Fine",
|
|
542
550
|
},
|
|
543
551
|
dialogFrame: {
|
|
544
552
|
close: "Chiudi",
|
package/src/i18n/locales/zh.ts
CHANGED
|
@@ -69,6 +69,7 @@ export function uiKitLabelsZh(numberLocale = "zh-CN"): UiKitLabels {
|
|
|
69
69
|
feedbackStatus: {
|
|
70
70
|
OPEN: "待处理",
|
|
71
71
|
READY: "待实现",
|
|
72
|
+
REWORK: "已要求返工",
|
|
72
73
|
IN_PROGRESS: "处理中",
|
|
73
74
|
IN_EVALUATION: "评估中",
|
|
74
75
|
NEEDS_LIVE_TEST: "待线上测试",
|
|
@@ -103,11 +104,13 @@ export function uiKitLabelsZh(numberLocale = "zh-CN"): UiKitLabels {
|
|
|
103
104
|
myFeedback: "我的反馈",
|
|
104
105
|
viewFeedback: "查看反馈",
|
|
105
106
|
allFeedback: "全部反馈",
|
|
107
|
+
discussion: "反馈讨论",
|
|
108
|
+
inbox: "反馈收件箱",
|
|
106
109
|
},
|
|
107
110
|
// 0.38.0 — docs/feedback-harmonization.md §9: the public pages and the two feedback
|
|
108
111
|
// notification types.
|
|
109
112
|
feedbackPublic: {
|
|
110
|
-
title: "
|
|
113
|
+
title: "反馈讨论",
|
|
111
114
|
sort: "排序",
|
|
112
115
|
sortNewest: "最新",
|
|
113
116
|
sortVotes: "最多人想要",
|
|
@@ -139,7 +142,7 @@ export function uiKitLabelsZh(numberLocale = "zh-CN"): UiKitLabels {
|
|
|
139
142
|
attachUrl: "附加当前页面 URL",
|
|
140
143
|
},
|
|
141
144
|
feedbackPage: {
|
|
142
|
-
title: "
|
|
145
|
+
title: "反馈收件箱",
|
|
143
146
|
myTitle: "我的反馈",
|
|
144
147
|
columnId: "#",
|
|
145
148
|
columnDate: "日期",
|
|
@@ -325,6 +328,8 @@ export function uiKitLabelsZh(numberLocale = "zh-CN"): UiKitLabels {
|
|
|
325
328
|
filter: "筛选",
|
|
326
329
|
close: "关闭",
|
|
327
330
|
selectRow: "选择行",
|
|
331
|
+
selectRows: "选择多行",
|
|
332
|
+
cancelSelection: "取消",
|
|
328
333
|
rowDetails: "详情",
|
|
329
334
|
autoSize: "自动调整列宽",
|
|
330
335
|
loading: "加载中…",
|
|
@@ -507,6 +512,8 @@ export function uiKitLabelsZh(numberLocale = "zh-CN"): UiKitLabels {
|
|
|
507
512
|
add: "添加标签页",
|
|
508
513
|
// Quoted, so the spacing rule holds whether the tab's name is Han or Latin.
|
|
509
514
|
remove: (tab) => `移除“${tab}”`,
|
|
515
|
+
more: "更多标签页",
|
|
516
|
+
backToFirst: "返回第一个标签页",
|
|
510
517
|
},
|
|
511
518
|
appShell: {
|
|
512
519
|
collapse: "收起侧边栏",
|
|
@@ -522,6 +529,7 @@ export function uiKitLabelsZh(numberLocale = "zh-CN"): UiKitLabels {
|
|
|
522
529
|
},
|
|
523
530
|
pickerSheet: {
|
|
524
531
|
close: "关闭",
|
|
532
|
+
done: "完成",
|
|
525
533
|
},
|
|
526
534
|
dialogFrame: {
|
|
527
535
|
close: "关闭",
|
|
@@ -108,7 +108,7 @@ export const DEFAULT_TOP_BAR_LABELS: TopBarLabels = {
|
|
|
108
108
|
role: (value) => `Role: ${value}`,
|
|
109
109
|
};
|
|
110
110
|
|
|
111
|
-
export const DEFAULT_PICKER_SHEET_LABELS: PickerSheetLabels = { close: "Close" };
|
|
111
|
+
export const DEFAULT_PICKER_SHEET_LABELS: PickerSheetLabels = { close: "Close", done: "Done" };
|
|
112
112
|
|
|
113
113
|
export const DEFAULT_SWIPEABLE_ROW_LABELS: SwipeableRowLabels = { actions: "Row actions" };
|
|
114
114
|
|
package/src/shell/app-shell.tsx
CHANGED
|
@@ -537,6 +537,15 @@ export function AppShell({
|
|
|
537
537
|
<main
|
|
538
538
|
className={cn(
|
|
539
539
|
"relative flex-1 max-w-full overflow-x-clip pb-[calc(var(--app-nav-h,4rem)+1.5rem)] md:pb-0 md:min-h-0 md:overflow-y-auto md:[scrollbar-gutter:stable_both-edges]",
|
|
540
|
+
// The list page's fill (0.40, docs/page-layout-harmonization.md §1.3): while
|
|
541
|
+
// a `fillHeight` DataTable is inside, a flex column — a banner above the
|
|
542
|
+
// page keeps its own height and the page (a `FillHeight`) takes the rest,
|
|
543
|
+
// so `<main>` no longer overflows by the banner. Its children do not shrink
|
|
544
|
+
// (a banner of a fixed height or `overflow-hidden` would): the page grows
|
|
545
|
+
// into the rest from a zero basis, and a window too short for the page's
|
|
546
|
+
// floor scrolls `<main>`. Every other page lays out as before. Below `md`
|
|
547
|
+
// the document scrolls and nothing fills.
|
|
548
|
+
"md:has-[[data-fill-height]]:flex md:has-[[data-fill-height]]:flex-col md:has-[[data-fill-height]]:*:shrink-0",
|
|
540
549
|
// Embedded there is no document scroll to lean on below `md` either.
|
|
541
550
|
embedded && "min-h-0 overflow-y-auto",
|
|
542
551
|
)}
|