@burdenoff/fe-libs 2026.1027.6 → 2026.1027.8
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.
|
@@ -26,7 +26,15 @@ export interface MobileTabBarProps {
|
|
|
26
26
|
*/
|
|
27
27
|
hideWhenKeyboardOpen?: boolean;
|
|
28
28
|
className?: string;
|
|
29
|
+
/**
|
|
30
|
+
* Controlled open state for the More sheet, so a header hamburger button
|
|
31
|
+
* can open the SAME sheet instead of a second, divergent one. Omit to let
|
|
32
|
+
* the tab bar manage it internally (the default, tap-the-More-tab-only
|
|
33
|
+
* behavior).
|
|
34
|
+
*/
|
|
35
|
+
open?: boolean;
|
|
36
|
+
onOpenChange?: (open: boolean) => void;
|
|
29
37
|
}
|
|
30
|
-
export declare function MobileTabBar({ appName, logo, groupOrder, groupLabels, maxTabs, moreLabel, mobileActions, hideWhenKeyboardOpen, className, }: MobileTabBarProps): import('react/jsx-runtime').JSX.Element;
|
|
38
|
+
export declare function MobileTabBar({ appName, logo, groupOrder, groupLabels, maxTabs, moreLabel, mobileActions, hideWhenKeyboardOpen, className, open, onOpenChange, }: MobileTabBarProps): import('react/jsx-runtime').JSX.Element;
|
|
31
39
|
export { useMobileTabBarVisible } from './mobileTabBar/useMobileTabBarVisible';
|
|
32
40
|
export { selectMobileTabs } from './mobileTabBar/selectTabs';
|
|
@@ -5,19 +5,19 @@ import { useShellLabel as o } from "../shared/providers/shell/useShellLabel.js";
|
|
|
5
5
|
import { appendContextToPath as s, useCurrentContextSearchParams as c } from "../shared/hooks/useCurrentContextSearchParams.js";
|
|
6
6
|
import "./sideNavigation/navVisibility.js";
|
|
7
7
|
import { useVisibleNavItems as l } from "./mobileTabBar/useVisibleNavItems.js";
|
|
8
|
-
import {
|
|
9
|
-
import { resolveTabPath as
|
|
8
|
+
import { findAncestorIds as u, isItemOrChildActive as d } from "./sideNavigation/helpers.js";
|
|
9
|
+
import { resolveTabPath as f, selectMobileTabs as p } from "./mobileTabBar/selectTabs.js";
|
|
10
10
|
import "./mobileTabBar/useMobileTabBarVisible.js";
|
|
11
|
-
import { useCallback as
|
|
12
|
-
import { MoreHorizontal as
|
|
13
|
-
import { Fragment as
|
|
14
|
-
import { useLocation as
|
|
11
|
+
import { useCallback as m, useEffect as h, useLayoutEffect as g, useMemo as _, useRef as v, useState as y } from "react";
|
|
12
|
+
import { ChevronDown as b, ChevronRight as x, MoreHorizontal as S } from "lucide-react";
|
|
13
|
+
import { Fragment as C, jsx as w, jsxs as T } from "react/jsx-runtime";
|
|
14
|
+
import { useLocation as E, useNavigate as ee } from "react-router";
|
|
15
15
|
//#region src/chrome/MobileTabBar.tsx
|
|
16
|
-
var
|
|
17
|
-
function
|
|
16
|
+
var D = "--mobile-tabbar-height";
|
|
17
|
+
function O() {
|
|
18
18
|
a()?.selection?.();
|
|
19
19
|
}
|
|
20
|
-
function
|
|
20
|
+
function k(e, t, n) {
|
|
21
21
|
let r = /* @__PURE__ */ new Map();
|
|
22
22
|
for (let t of e) {
|
|
23
23
|
if (t.id.startsWith("__nav_more__:") && t.children) {
|
|
@@ -39,42 +39,57 @@ function D(e, t, n) {
|
|
|
39
39
|
items: r.get(e) ?? []
|
|
40
40
|
}));
|
|
41
41
|
}
|
|
42
|
-
function
|
|
43
|
-
let
|
|
42
|
+
function A({ appName: a, logo: b, groupOrder: x = [], groupLabels: A = {}, maxTabs: M = 4, moreLabel: N, mobileActions: P, hideWhenKeyboardOpen: te = !0, className: ne, open: re, onOpenChange: ie }) {
|
|
43
|
+
let F = o(), I = N ?? F("nav.more", "More"), L = ee(), R = E(), z = c(), { items: B } = l(), [V, H] = y(!1), U = re ?? V, W = ie ?? H, G = v(null), { tabs: K, more: q, hasMore: J } = _(() => p(B, M), [B, M]), ae = _(() => k(q, x, A), [
|
|
44
44
|
q,
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
]),
|
|
45
|
+
x,
|
|
46
|
+
A
|
|
47
|
+
]), Y = !!P && P.length > 0, X = J || Y, [oe, Z] = y(/* @__PURE__ */ new Set());
|
|
48
48
|
h(() => {
|
|
49
|
+
let e = u(q, R.pathname);
|
|
50
|
+
e.size !== 0 && Z((t) => {
|
|
51
|
+
let n = new Set(t), r = !1;
|
|
52
|
+
return e.forEach((e) => {
|
|
53
|
+
n.has(e) || (n.add(e), r = !0);
|
|
54
|
+
}), r ? n : t;
|
|
55
|
+
});
|
|
56
|
+
}, [q, R.pathname]);
|
|
57
|
+
let se = m((e) => {
|
|
58
|
+
Z((t) => {
|
|
59
|
+
let n = new Set(t);
|
|
60
|
+
return n.has(e) ? n.delete(e) : n.add(e), n;
|
|
61
|
+
});
|
|
62
|
+
}, []);
|
|
63
|
+
g(() => {
|
|
49
64
|
let e = G.current;
|
|
50
65
|
if (!e || typeof window > "u") return;
|
|
51
|
-
let t = document.documentElement, n = () => t.style.setProperty(
|
|
66
|
+
let t = document.documentElement, n = () => t.style.setProperty(D, `${e.offsetHeight}px`);
|
|
52
67
|
n();
|
|
53
68
|
let r = typeof ResizeObserver < "u" ? new ResizeObserver(n) : null;
|
|
54
69
|
return r?.observe(e), () => {
|
|
55
|
-
r?.disconnect(), t.style.removeProperty(
|
|
70
|
+
r?.disconnect(), t.style.removeProperty(D);
|
|
56
71
|
};
|
|
57
|
-
}, []),
|
|
72
|
+
}, []), h(() => {
|
|
58
73
|
W(!1);
|
|
59
|
-
}, [
|
|
60
|
-
let Q =
|
|
61
|
-
|
|
62
|
-
}, [
|
|
74
|
+
}, [R.pathname, W]);
|
|
75
|
+
let Q = m((e) => {
|
|
76
|
+
O(), L(s(e, z));
|
|
77
|
+
}, [L, z]), $ = _(() => !!J && q.some((e) => d(e, R.pathname)), [
|
|
63
78
|
J,
|
|
64
79
|
q,
|
|
65
|
-
|
|
80
|
+
R.pathname
|
|
66
81
|
]);
|
|
67
|
-
return /* @__PURE__ */
|
|
82
|
+
return /* @__PURE__ */ T(C, { children: [/* @__PURE__ */ T("nav", {
|
|
68
83
|
ref: G,
|
|
69
84
|
role: "tablist",
|
|
70
|
-
"aria-label":
|
|
85
|
+
"aria-label": F("nav.primaryNavigation", `${a} navigation`),
|
|
71
86
|
"data-mobile-tabbar": "",
|
|
72
87
|
"data-shell-chrome": "",
|
|
73
|
-
"data-keyboard-keep":
|
|
74
|
-
className: e("fixed inset-x-0 bottom-0 z-[60] flex items-stretch", "bg-bg-surface text-text-primary",
|
|
88
|
+
"data-keyboard-keep": te ? void 0 : "",
|
|
89
|
+
className: e("fixed inset-x-0 bottom-0 z-[60] flex items-stretch", "bg-bg-surface text-text-primary", ne),
|
|
75
90
|
children: [K.map((t) => {
|
|
76
|
-
let n =
|
|
77
|
-
return /* @__PURE__ */
|
|
91
|
+
let n = d(t, R.pathname);
|
|
92
|
+
return /* @__PURE__ */ T("button", {
|
|
78
93
|
type: "button",
|
|
79
94
|
role: "tab",
|
|
80
95
|
"aria-selected": n,
|
|
@@ -83,91 +98,102 @@ function O({ appName: a, logo: O, groupOrder: A = [], groupLabels: j = {}, maxTa
|
|
|
83
98
|
"data-mobile-tab": t.id,
|
|
84
99
|
className: e("mobile-tab relative flex min-w-0 flex-1 flex-col items-center justify-center gap-0.5", "text-text-muted transition-colors duration-150", n && "text-text-link"),
|
|
85
100
|
onClick: () => {
|
|
86
|
-
n && !t.children?.length || Q(
|
|
101
|
+
n && !t.children?.length || Q(f(t));
|
|
87
102
|
},
|
|
88
|
-
children: [/* @__PURE__ */
|
|
103
|
+
children: [/* @__PURE__ */ T("span", {
|
|
89
104
|
className: "mobile-tab__icon relative inline-flex items-center justify-center",
|
|
90
105
|
"aria-hidden": "true",
|
|
91
|
-
children: [t.icon, t.badge ? /* @__PURE__ */
|
|
106
|
+
children: [t.icon, t.badge ? /* @__PURE__ */ w("span", {
|
|
92
107
|
className: "absolute -top-1 -right-2 min-w-4 rounded-full bg-status-error-bg px-1 text-[10px] font-semibold leading-4 text-status-error-text",
|
|
93
108
|
children: t.badge > 99 ? "99+" : t.badge
|
|
94
109
|
}) : null]
|
|
95
|
-
}), /* @__PURE__ */
|
|
110
|
+
}), /* @__PURE__ */ w("span", {
|
|
96
111
|
className: "mobile-tab__label max-w-full truncate",
|
|
97
112
|
children: t.label
|
|
98
113
|
})]
|
|
99
114
|
}, t.id);
|
|
100
|
-
}),
|
|
115
|
+
}), X ? /* @__PURE__ */ T("button", {
|
|
101
116
|
type: "button",
|
|
102
117
|
role: "tab",
|
|
103
118
|
"aria-selected": $,
|
|
104
119
|
"aria-haspopup": "dialog",
|
|
105
120
|
"aria-expanded": U,
|
|
106
|
-
"aria-label":
|
|
121
|
+
"aria-label": I,
|
|
107
122
|
"data-active": $ ? "" : void 0,
|
|
108
123
|
"data-mobile-tab": "__more",
|
|
109
124
|
className: e("mobile-tab relative flex min-w-0 flex-1 flex-col items-center justify-center gap-0.5", "text-text-muted transition-colors duration-150", $ && "text-text-link"),
|
|
110
125
|
onClick: () => {
|
|
111
|
-
|
|
126
|
+
O(), W(!0);
|
|
112
127
|
},
|
|
113
|
-
children: [/* @__PURE__ */
|
|
128
|
+
children: [/* @__PURE__ */ w("span", {
|
|
114
129
|
className: "mobile-tab__icon inline-flex items-center justify-center",
|
|
115
130
|
"aria-hidden": "true",
|
|
116
|
-
children: /* @__PURE__ */
|
|
117
|
-
}), /* @__PURE__ */
|
|
131
|
+
children: /* @__PURE__ */ w(S, {})
|
|
132
|
+
}), /* @__PURE__ */ w("span", {
|
|
118
133
|
className: "mobile-tab__label max-w-full truncate",
|
|
119
|
-
children:
|
|
134
|
+
children: I
|
|
120
135
|
})]
|
|
121
136
|
}) : null]
|
|
122
|
-
}),
|
|
137
|
+
}), X ? /* @__PURE__ */ w(t, {
|
|
123
138
|
open: U,
|
|
124
139
|
onOpenChange: W,
|
|
125
|
-
children: /* @__PURE__ */
|
|
126
|
-
"aria-label":
|
|
140
|
+
children: /* @__PURE__ */ T(n, {
|
|
141
|
+
"aria-label": I,
|
|
127
142
|
"data-swipe-ignore": "",
|
|
128
|
-
children: [/* @__PURE__ */
|
|
143
|
+
children: [/* @__PURE__ */ T(r, { children: [b ? /* @__PURE__ */ T("div", {
|
|
129
144
|
className: "mb-1 flex items-center gap-2",
|
|
130
|
-
children: [/* @__PURE__ */
|
|
145
|
+
children: [/* @__PURE__ */ w("div", {
|
|
131
146
|
className: "flex size-8 flex-shrink-0 items-center justify-center",
|
|
132
|
-
children:
|
|
133
|
-
}), /* @__PURE__ */
|
|
147
|
+
children: b
|
|
148
|
+
}), /* @__PURE__ */ w("span", {
|
|
134
149
|
className: "text-heading-h4 font-semibold text-text-primary",
|
|
135
150
|
children: a
|
|
136
151
|
})]
|
|
137
|
-
}) : null, /* @__PURE__ */
|
|
152
|
+
}) : null, /* @__PURE__ */ w(i, { children: I })] }), /* @__PURE__ */ T("div", {
|
|
138
153
|
className: "flex flex-col gap-4 pb-2",
|
|
139
154
|
"data-mobile-tabbar-more": "",
|
|
140
|
-
children: [
|
|
155
|
+
children: [ae.map((e) => /* @__PURE__ */ T("section", {
|
|
141
156
|
"aria-label": e.label ?? void 0,
|
|
142
|
-
children: [e.label ? /* @__PURE__ */
|
|
157
|
+
children: [e.label ? /* @__PURE__ */ w("p", {
|
|
143
158
|
className: "mb-1 px-1 text-[11px] font-medium uppercase tracking-wider text-text-muted",
|
|
144
159
|
children: e.label
|
|
145
|
-
}) : null, /* @__PURE__ */
|
|
160
|
+
}) : null, /* @__PURE__ */ w("ul", {
|
|
146
161
|
className: "flex flex-col",
|
|
147
162
|
children: e.items.map((e) => {
|
|
148
|
-
let t =
|
|
149
|
-
return /* @__PURE__ */
|
|
163
|
+
let t = d(e, R.pathname), n = !!e.children && e.children.length > 0, r = oe.has(e.id);
|
|
164
|
+
return /* @__PURE__ */ T("li", { children: [/* @__PURE__ */ w(j, {
|
|
150
165
|
icon: e.icon,
|
|
151
166
|
label: e.label,
|
|
152
167
|
badge: e.badge,
|
|
153
168
|
active: t,
|
|
154
|
-
|
|
155
|
-
|
|
169
|
+
expandable: n,
|
|
170
|
+
expanded: r,
|
|
171
|
+
onSelect: () => n ? se(e.id) : Q(f(e))
|
|
172
|
+
}), n && r ? /* @__PURE__ */ w("ul", {
|
|
173
|
+
className: "flex flex-col pl-7",
|
|
174
|
+
children: e.children.map((e) => /* @__PURE__ */ w("li", { children: /* @__PURE__ */ w(j, {
|
|
175
|
+
icon: e.icon,
|
|
176
|
+
label: e.label,
|
|
177
|
+
badge: e.badge,
|
|
178
|
+
active: d(e, R.pathname),
|
|
179
|
+
onSelect: () => Q(f(e))
|
|
180
|
+
}) }, e.id))
|
|
181
|
+
}) : null] }, e.id);
|
|
156
182
|
})
|
|
157
183
|
})]
|
|
158
|
-
}, e.key || "__ungrouped")),
|
|
159
|
-
"aria-label":
|
|
160
|
-
children: [/* @__PURE__ */
|
|
184
|
+
}, e.key || "__ungrouped")), Y ? /* @__PURE__ */ T("section", {
|
|
185
|
+
"aria-label": F("appShell.quickActions", "Quick Actions"),
|
|
186
|
+
children: [/* @__PURE__ */ w("p", {
|
|
161
187
|
className: "mb-1 px-1 text-[11px] font-medium uppercase tracking-wider text-text-muted",
|
|
162
|
-
children:
|
|
163
|
-
}), /* @__PURE__ */
|
|
188
|
+
children: F("appShell.quickActions", "Quick Actions")
|
|
189
|
+
}), /* @__PURE__ */ w("ul", {
|
|
164
190
|
className: "flex flex-col",
|
|
165
|
-
children: P?.map((e) => /* @__PURE__ */
|
|
191
|
+
children: P?.map((e) => /* @__PURE__ */ w("li", { children: /* @__PURE__ */ w(j, {
|
|
166
192
|
icon: e.icon,
|
|
167
193
|
label: e.label,
|
|
168
194
|
active: !!e.isToggle && !!e.isActive,
|
|
169
195
|
onSelect: () => {
|
|
170
|
-
|
|
196
|
+
O(), e.onClick(), W(!1);
|
|
171
197
|
}
|
|
172
198
|
}) }, e.id))
|
|
173
199
|
})]
|
|
@@ -176,23 +202,29 @@ function O({ appName: a, logo: O, groupOrder: A = [], groupLabels: j = {}, maxTa
|
|
|
176
202
|
})
|
|
177
203
|
}) : null] });
|
|
178
204
|
}
|
|
179
|
-
function
|
|
180
|
-
return /* @__PURE__ */
|
|
205
|
+
function j({ icon: t, label: n, badge: r, active: i, onSelect: a, expandable: o, expanded: s }) {
|
|
206
|
+
return /* @__PURE__ */ T("button", {
|
|
181
207
|
type: "button",
|
|
182
208
|
onClick: a,
|
|
183
|
-
"aria-current": i ? "page" : void 0,
|
|
209
|
+
"aria-current": !o && i ? "page" : void 0,
|
|
210
|
+
"aria-expanded": o ? s : void 0,
|
|
184
211
|
className: e("flex w-full min-h-11 items-center gap-3 rounded-button px-3 py-2 text-left text-body-sm", "transition-colors duration-150", i ? "bg-[var(--color-accent-soft)] text-text-primary font-medium" : "text-text-secondary hover:bg-bg-sunken hover:text-text-primary"),
|
|
185
212
|
children: [
|
|
186
|
-
t ? /* @__PURE__ */
|
|
213
|
+
t ? /* @__PURE__ */ w("span", {
|
|
187
214
|
className: "inline-flex size-5 shrink-0 items-center justify-center",
|
|
188
215
|
"aria-hidden": "true",
|
|
189
216
|
children: t
|
|
190
217
|
}) : null,
|
|
191
|
-
/* @__PURE__ */
|
|
218
|
+
/* @__PURE__ */ w("span", {
|
|
192
219
|
className: "min-w-0 flex-1 truncate",
|
|
193
220
|
children: n
|
|
194
221
|
}),
|
|
195
|
-
|
|
222
|
+
o ? /* @__PURE__ */ w("span", {
|
|
223
|
+
className: "inline-flex size-4 shrink-0 items-center justify-center text-text-muted",
|
|
224
|
+
"aria-hidden": "true",
|
|
225
|
+
children: w(s ? b : x, { className: "size-4" })
|
|
226
|
+
}) : null,
|
|
227
|
+
r ? /* @__PURE__ */ w("span", {
|
|
196
228
|
className: "rounded-full bg-status-error-bg px-1.5 text-[10px] font-semibold leading-4 text-status-error-text",
|
|
197
229
|
children: r > 99 ? "99+" : r
|
|
198
230
|
}) : null
|
|
@@ -200,4 +232,4 @@ function k({ icon: t, label: n, badge: r, active: i, onSelect: a }) {
|
|
|
200
232
|
});
|
|
201
233
|
}
|
|
202
234
|
//#endregion
|
|
203
|
-
export {
|
|
235
|
+
export { A as MobileTabBar };
|
package/package.json
CHANGED
|
@@ -252,10 +252,27 @@ body.keyboard-open [data-native-shell] main {
|
|
|
252
252
|
backdrop-filter: saturate(180%) blur(20px);
|
|
253
253
|
}
|
|
254
254
|
|
|
255
|
+
/* Normal flow, not absolutely centered: with 5+ trailing actions (context,
|
|
256
|
+
search, notifications, profile, plus a leading hamburger) an
|
|
257
|
+
absolutely-positioned title ignores the row's actual layout and visually
|
|
258
|
+
overlaps the icons instead of yielding space to them. Flex "centers" it
|
|
259
|
+
well enough when lead/trailing are similar widths, and truncates instead
|
|
260
|
+
of overlapping when they are not — same mechanism Android already used
|
|
261
|
+
below, just keeping iOS's centered alignment. */
|
|
255
262
|
.platform-ios [data-native-topbar] .native-topbar__title {
|
|
263
|
+
position: static;
|
|
264
|
+
margin: 0;
|
|
265
|
+
max-width: none;
|
|
266
|
+
min-width: 0;
|
|
267
|
+
flex: 1 1 auto;
|
|
256
268
|
text-align: center;
|
|
257
269
|
}
|
|
258
270
|
|
|
271
|
+
.platform-ios [data-native-topbar] .native-topbar__lead,
|
|
272
|
+
.platform-ios [data-native-topbar] .native-topbar__actions {
|
|
273
|
+
flex: 0 0 auto;
|
|
274
|
+
}
|
|
275
|
+
|
|
259
276
|
/* Android: opaque 56px bar, title left-aligned next to the back arrow, and no
|
|
260
277
|
iOS-style back TEXT label. */
|
|
261
278
|
.platform-android [data-native-topbar] {
|