laif-ds 1.0.1 → 1.0.2
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/CHANGELOG.md +6 -0
- package/dist/_virtual/index3.js +5 -5
- package/dist/_virtual/index4.js +5 -5
- package/dist/_virtual/index5.js +4 -4
- package/dist/agent-docs/adoption-report.json +2 -2
- package/dist/agent-docs/components/AppBottomNav.md +7 -8
- package/dist/agent-docs/manifest.json +3 -3
- package/dist/components/ui/app-bottom-nav.js +74 -78
- package/dist/node_modules/eventemitter3/index.js +1 -1
- package/dist/node_modules/hast-util-to-jsx-runtime/lib/index.js +1 -1
- package/dist/node_modules/recharts/es6/util/Events.js +1 -1
- package/dist/node_modules/unified/lib/index.js +1 -1
- package/package.json +1 -1
package/dist/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,12 @@ All notable technical changes to the laif-ds core will be documented in this fil
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [laif-ds@1.0.2]
|
|
9
|
+
|
|
10
|
+
### 🐛 Fixed
|
|
11
|
+
|
|
12
|
+
- **AppBottomNav**: When the current route matches none of the bar's destinations, the Menu cell no longer takes the active pill — the bar now renders entirely neutral, the same as `showMenu={false}`, since Menu is a disclosure and not a page
|
|
13
|
+
|
|
8
14
|
## [laif-ds@1.0.1]
|
|
9
15
|
|
|
10
16
|
### 🚀 Added
|
package/dist/_virtual/index3.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { getDefaultExportFromCjs as
|
|
3
|
-
import { __require as
|
|
4
|
-
var
|
|
5
|
-
const
|
|
2
|
+
import { getDefaultExportFromCjs as e } from "./_commonjsHelpers.js";
|
|
3
|
+
import { __require as t } from "../node_modules/eventemitter3/index2.js";
|
|
4
|
+
var r = t();
|
|
5
|
+
const m = /* @__PURE__ */ e(r);
|
|
6
6
|
export {
|
|
7
|
-
|
|
7
|
+
m as default
|
|
8
8
|
};
|
package/dist/_virtual/index4.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { getDefaultExportFromCjs as
|
|
3
|
-
import { __require as
|
|
4
|
-
var t =
|
|
5
|
-
const
|
|
2
|
+
import { getDefaultExportFromCjs as r } from "./_commonjsHelpers.js";
|
|
3
|
+
import { __require as e } from "../node_modules/style-to-js/cjs/index.js";
|
|
4
|
+
var t = e();
|
|
5
|
+
const a = /* @__PURE__ */ r(t);
|
|
6
6
|
export {
|
|
7
|
-
|
|
7
|
+
a as default
|
|
8
8
|
};
|
package/dist/_virtual/index5.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { getDefaultExportFromCjs as e } from "./_commonjsHelpers.js";
|
|
3
|
-
import { __require as
|
|
4
|
-
var
|
|
5
|
-
const
|
|
3
|
+
import { __require as r } from "../node_modules/extend/index.js";
|
|
4
|
+
var t = r();
|
|
5
|
+
const x = /* @__PURE__ */ e(t);
|
|
6
6
|
export {
|
|
7
|
-
|
|
7
|
+
x as default
|
|
8
8
|
};
|
|
@@ -231,14 +231,13 @@ claymorphism theme, while the dock around it is a fixed `rounded-t-lg`.
|
|
|
231
231
|
- **Parent whose child is current** (any `subItems[].isActive`) → the cell is a
|
|
232
232
|
`<button>`, marked, **without** `aria-current`: a button is not a page, it is a
|
|
233
233
|
disclosure. So the app only has to mark the leaf.
|
|
234
|
-
- **Nothing in the bar owns the route** →
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
page you are on
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
and none of them is the current one.
|
|
234
|
+
- **Nothing in the bar owns the route** → **no cell is marked**, Menu included.
|
|
235
|
+
The bar renders entirely neutral, exactly as it always has with
|
|
236
|
+
`showMenu={false}`. The Menu cell is a disclosure, not a destination: the pill
|
|
237
|
+
means "this is the page you are on", and handing it to a button that opens a
|
|
238
|
+
panel says that about something which is not a page. A route outside the bar's
|
|
239
|
+
five destinations is a real state, and the honest way to render it is no pill
|
|
240
|
+
at all.
|
|
242
241
|
- Two active items is an app bug: the first in order wins and one warning is
|
|
243
242
|
logged.
|
|
244
243
|
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": "1.1.0",
|
|
3
|
-
"generatedAt": "2026-09-
|
|
3
|
+
"generatedAt": "2026-09-18T09:11:12.439Z",
|
|
4
4
|
"package": {
|
|
5
5
|
"name": "laif-ds",
|
|
6
|
-
"version": "1.0.
|
|
6
|
+
"version": "1.0.2"
|
|
7
7
|
},
|
|
8
8
|
"stats": {
|
|
9
9
|
"documentedComponentCount": 94,
|
|
@@ -6312,5 +6312,5 @@
|
|
|
6312
6312
|
]
|
|
6313
6313
|
}
|
|
6314
6314
|
],
|
|
6315
|
-
"checksum": "
|
|
6315
|
+
"checksum": "1b95270b522d7fdbd54fa834020be6d9bf1b0632fda8a9458556d024398a8574"
|
|
6316
6316
|
}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { jsxs as
|
|
3
|
-
import * as
|
|
4
|
-
import { designTokens as
|
|
5
|
-
import { navTokens as
|
|
6
|
-
import { Icon as
|
|
7
|
-
import { warnOnce as
|
|
8
|
-
import { useSidebar as
|
|
2
|
+
import { jsxs as d, jsx as n, Fragment as J } from "react/jsx-runtime";
|
|
3
|
+
import * as Q from "react";
|
|
4
|
+
import { designTokens as U } from "../design-tokens.js";
|
|
5
|
+
import { navTokens as T } from "../nav-tokens.js";
|
|
6
|
+
import { Icon as V } from "./icon.js";
|
|
7
|
+
import { warnOnce as i, someRowBadged as _, normalizeNavBadge as W, NavBadgeOverlay as Y, NavBadgeDot as w, NavBadgeSrLabel as Z } from "./nav-badge.js";
|
|
8
|
+
import { useSidebar as ee } from "./sidebar.js";
|
|
9
9
|
import { cn as r } from "../../lib/utils.js";
|
|
10
|
-
const
|
|
10
|
+
const O = 6, $ = (a) => `${a.url} ${a.title}`, A = (a) => !!a.isActive || !!a.subItems?.some((o) => o.isActive), te = "md:hidden shrink-0 overflow-hidden bg-d-card border-d-border rounded-t-lg border-t pb-[env(safe-area-inset-bottom)]", ae = "flex items-stretch p-1", g = r(
|
|
11
11
|
// `min-h-11` (44px) written out rather than `sizes.touch`: that token also
|
|
12
12
|
// carries `px-4` and `text-sm`, and 16px of horizontal padding inside a ~61px
|
|
13
13
|
// cell would leave 29px for the label. `min-h-`, never `h-`: a cell must be
|
|
@@ -22,8 +22,8 @@ const $ = 6, S = (a) => `${a.url} ${a.title}`, T = (a) => !!a.isActive || !!a.su
|
|
|
22
22
|
"flex min-h-11 min-w-0 flex-1 cursor-pointer flex-col items-center justify-center gap-0.5 px-1 py-2.5 text-xs",
|
|
23
23
|
// On every cell, not only the marked one: it keeps the hover and press
|
|
24
24
|
// surfaces of an inactive cell the same shape as the pill they can become.
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
T.item.basePill,
|
|
26
|
+
U.focusRing,
|
|
27
27
|
// `ring-inset` because the cells touch each other: an outset ring would spill
|
|
28
28
|
// over the neighbour and read as if two cells were focused.
|
|
29
29
|
"focus-visible:ring-inset"
|
|
@@ -31,63 +31,63 @@ const $ = 6, S = (a) => `${a.url} ${a.title}`, T = (a) => !!a.isActive || !!a.su
|
|
|
31
31
|
"text-d-foreground font-medium",
|
|
32
32
|
"[@media(hover:hover)_and_(pointer:fine)]:hover:bg-d-sidebar-accent [@media(hover:hover)_and_(pointer:fine)]:hover:text-d-sidebar-accent-foreground",
|
|
33
33
|
"active:bg-d-sidebar-accent active:text-d-sidebar-accent-foreground"
|
|
34
|
-
),
|
|
35
|
-
/* @__PURE__ */
|
|
36
|
-
|
|
37
|
-
] }),
|
|
34
|
+
), M = T.item.selectedPill, P = "relative flex size-5 shrink-0 items-center justify-center", c = (a, o) => /* @__PURE__ */ d("span", { className: P, children: [
|
|
35
|
+
/* @__PURE__ */ n(V, { name: a, size: "sm", className: "shrink-0" }),
|
|
36
|
+
o
|
|
37
|
+
] }), ne = (a, o) => /* @__PURE__ */ d("span", { className: r(P, "[&>svg]:size-full"), children: [
|
|
38
38
|
a,
|
|
39
|
-
|
|
40
|
-
] }),
|
|
39
|
+
o
|
|
40
|
+
] }), oe = "-top-1 -right-1.5", S = "absolute -top-1 -right-1", N = (a, o, m) => /* @__PURE__ */ d(J, { children: [
|
|
41
41
|
a,
|
|
42
|
-
/* @__PURE__ */
|
|
43
|
-
|
|
42
|
+
/* @__PURE__ */ n("span", { className: "w-full truncate text-center", children: o }),
|
|
43
|
+
m
|
|
44
44
|
] });
|
|
45
|
-
function
|
|
45
|
+
function pe({
|
|
46
46
|
items: a,
|
|
47
|
-
showMenu:
|
|
48
|
-
menuLabel:
|
|
49
|
-
ariaLabel:
|
|
50
|
-
menuIcon:
|
|
51
|
-
menuBadge:
|
|
52
|
-
linkComponent:
|
|
53
|
-
linkProps:
|
|
54
|
-
className:
|
|
55
|
-
...
|
|
47
|
+
showMenu: o = !0,
|
|
48
|
+
menuLabel: m = "Menu",
|
|
49
|
+
ariaLabel: j = "Main navigation",
|
|
50
|
+
menuIcon: p = "Menu",
|
|
51
|
+
menuBadge: D = !1,
|
|
52
|
+
linkComponent: x,
|
|
53
|
+
linkProps: z = {},
|
|
54
|
+
className: E,
|
|
55
|
+
...R
|
|
56
56
|
}) {
|
|
57
|
-
const { openMobile:
|
|
58
|
-
if (
|
|
59
|
-
const e =
|
|
60
|
-
|
|
61
|
-
`AppBottomNav: ${a.length} items passed, ${
|
|
57
|
+
const { openMobile: I, setOpenMobile: B, mobileNavTarget: F, setMobileNavTarget: C } = ee(), u = o ? O - 1 : O, l = a.slice(0, u), v = a.slice(u);
|
|
58
|
+
if (v.length > 0) {
|
|
59
|
+
const e = v.map((t) => `"${t.title}"`).join(", ");
|
|
60
|
+
i(
|
|
61
|
+
`AppBottomNav: ${a.length} items passed, ${u} slots available. Dropped: ${e}.`
|
|
62
62
|
);
|
|
63
63
|
}
|
|
64
|
-
const
|
|
64
|
+
const L = /* @__PURE__ */ new Set();
|
|
65
65
|
for (const e of l) {
|
|
66
|
-
const t =
|
|
67
|
-
|
|
66
|
+
const t = $(e);
|
|
67
|
+
L.has(t) && i(
|
|
68
68
|
`AppBottomNav: duplicate item "${t}" — one of them is ignored.`
|
|
69
|
-
),
|
|
69
|
+
), L.add(t);
|
|
70
70
|
}
|
|
71
|
-
const
|
|
72
|
-
l.filter(
|
|
73
|
-
`AppBottomNav: more than one active item — "${l[
|
|
71
|
+
const b = l.findIndex(A);
|
|
72
|
+
l.filter(A).length > 1 && i(
|
|
73
|
+
`AppBottomNav: more than one active item — "${l[b].title}" wins.`
|
|
74
74
|
);
|
|
75
|
-
const
|
|
76
|
-
const e =
|
|
77
|
-
if (typeof
|
|
78
|
-
const t =
|
|
79
|
-
return t == null ?
|
|
80
|
-
})(),
|
|
81
|
-
const t =
|
|
75
|
+
const K = D || _(v), G = (() => {
|
|
76
|
+
const e = K ? /* @__PURE__ */ n(w, { className: S }) : null;
|
|
77
|
+
if (typeof p == "string") return c(p, e);
|
|
78
|
+
const t = p();
|
|
79
|
+
return t == null ? c("Menu", e) : ne(t, e);
|
|
80
|
+
})(), k = (e) => {
|
|
81
|
+
const t = W(e.badge, "compact", e.title), s = /* @__PURE__ */ n(Z, { row: e, badge: t });
|
|
82
82
|
return t?.kind === "text" ? {
|
|
83
|
-
visual: /* @__PURE__ */
|
|
83
|
+
visual: /* @__PURE__ */ n(Y, { text: t.text, className: oe }),
|
|
84
84
|
srLabel: s
|
|
85
|
-
} : t?.kind === "dot" ||
|
|
86
|
-
},
|
|
85
|
+
} : t?.kind === "dot" || _(e.subItems) ? { visual: /* @__PURE__ */ n(w, { className: S }), srLabel: s } : { visual: null, srLabel: s };
|
|
86
|
+
}, X = (e, t) => {
|
|
87
87
|
const s = {
|
|
88
88
|
className: r(
|
|
89
89
|
g,
|
|
90
|
-
t ?
|
|
90
|
+
t ? M : h
|
|
91
91
|
),
|
|
92
92
|
"data-slot": "app-bottom-nav-item",
|
|
93
93
|
"data-active": t ? "true" : void 0,
|
|
@@ -95,64 +95,60 @@ function ue({
|
|
|
95
95
|
// the full title is already in the accessibility tree.
|
|
96
96
|
"aria-label": e.ariaLabel,
|
|
97
97
|
"aria-current": t ? "page" : void 0
|
|
98
|
-
}, { visual: f, srLabel:
|
|
99
|
-
|
|
98
|
+
}, { visual: f, srLabel: H } = k(e), y = N(
|
|
99
|
+
c(e.iconName, f),
|
|
100
100
|
e.title,
|
|
101
|
-
|
|
101
|
+
H
|
|
102
102
|
);
|
|
103
|
-
return
|
|
104
|
-
},
|
|
105
|
-
const { visual: s, srLabel: f } =
|
|
103
|
+
return x ? /* @__PURE__ */ n(x, { href: e.url, ...s, ...z, children: y }) : /* @__PURE__ */ n("a", { href: e.url, ...s, children: y });
|
|
104
|
+
}, q = (e, t) => {
|
|
105
|
+
const { visual: s, srLabel: f } = k(e);
|
|
106
106
|
return (
|
|
107
107
|
// A button is not a page, so no `aria-current` even when the indicator is
|
|
108
108
|
// here. No `aria-controls` — the drill panel's id is Radix-generated and
|
|
109
109
|
// unreachable from the bar — and no `aria-haspopup`, which would promise
|
|
110
110
|
// arrow-key menu semantics the drill-down does not implement.
|
|
111
|
-
/* @__PURE__ */
|
|
111
|
+
/* @__PURE__ */ n(
|
|
112
112
|
"button",
|
|
113
113
|
{
|
|
114
114
|
type: "button",
|
|
115
115
|
"data-slot": "app-bottom-nav-item",
|
|
116
116
|
"data-active": t ? "true" : void 0,
|
|
117
117
|
"aria-label": e.ariaLabel,
|
|
118
|
-
"aria-expanded":
|
|
118
|
+
"aria-expanded": I && F === e.title,
|
|
119
119
|
className: r(
|
|
120
120
|
g,
|
|
121
|
-
t ?
|
|
121
|
+
t ? M : h
|
|
122
122
|
),
|
|
123
123
|
onClick: () => {
|
|
124
|
-
|
|
124
|
+
C(e.title), B(!0);
|
|
125
125
|
},
|
|
126
|
-
children:
|
|
126
|
+
children: N(c(e.iconName, s), e.title, f)
|
|
127
127
|
}
|
|
128
128
|
)
|
|
129
129
|
);
|
|
130
130
|
};
|
|
131
|
-
return l.length === 0 && !
|
|
131
|
+
return l.length === 0 && !o ? (i(
|
|
132
132
|
"AppBottomNav: no items and showMenu={false} — nothing to render, the bar is omitted."
|
|
133
|
-
), null) : /* @__PURE__ */
|
|
133
|
+
), null) : /* @__PURE__ */ n(
|
|
134
134
|
"div",
|
|
135
135
|
{
|
|
136
136
|
"data-slot": "app-bottom-nav",
|
|
137
|
-
className: r(
|
|
138
|
-
...
|
|
139
|
-
children: /* @__PURE__ */
|
|
140
|
-
l.map((e, t) => /* @__PURE__ */
|
|
141
|
-
|
|
137
|
+
className: r(te, E),
|
|
138
|
+
...R,
|
|
139
|
+
children: /* @__PURE__ */ d("nav", { "aria-label": j, className: ae, children: [
|
|
140
|
+
l.map((e, t) => /* @__PURE__ */ n(Q.Fragment, { children: e.subItems?.length ? q(e, t === b) : X(e, t === b) }, $(e))),
|
|
141
|
+
o && /* @__PURE__ */ n(
|
|
142
142
|
"button",
|
|
143
143
|
{
|
|
144
144
|
type: "button",
|
|
145
145
|
"data-slot": "app-bottom-nav-item",
|
|
146
|
-
"
|
|
147
|
-
|
|
148
|
-
className: r(
|
|
149
|
-
g,
|
|
150
|
-
y ? N : h
|
|
151
|
-
),
|
|
146
|
+
"aria-expanded": I,
|
|
147
|
+
className: r(g, h),
|
|
152
148
|
onClick: () => {
|
|
153
|
-
|
|
149
|
+
C(null), B(!0);
|
|
154
150
|
},
|
|
155
|
-
children:
|
|
151
|
+
children: N(G, m)
|
|
156
152
|
}
|
|
157
153
|
)
|
|
158
154
|
] })
|
|
@@ -160,5 +156,5 @@ function ue({
|
|
|
160
156
|
);
|
|
161
157
|
}
|
|
162
158
|
export {
|
|
163
|
-
|
|
159
|
+
pe as AppBottomNav
|
|
164
160
|
};
|
|
@@ -3,7 +3,7 @@ import { stringify as w } from "../../comma-separated-tokens/index.js";
|
|
|
3
3
|
import { ok as u } from "../../devlop/lib/default.js";
|
|
4
4
|
import { svg as m, html as C } from "../../property-information/index.js";
|
|
5
5
|
import { stringify as N } from "../../space-separated-tokens/index.js";
|
|
6
|
-
import S from "../../../_virtual/
|
|
6
|
+
import S from "../../../_virtual/index4.js";
|
|
7
7
|
import { whitespace as j } from "../../hast-util-whitespace/lib/index.js";
|
|
8
8
|
import { name as x } from "../../estree-util-is-identifier-name/lib/index.js";
|
|
9
9
|
import { VFileMessage as h } from "../../vfile-message/lib/index.js";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { bail as P } from "../../bail/index.js";
|
|
3
|
-
import y from "../../../_virtual/
|
|
3
|
+
import y from "../../../_virtual/index5.js";
|
|
4
4
|
import z from "../../is-plain-obj/index.js";
|
|
5
5
|
import { CallableInstance as C } from "./callable-instance.js";
|
|
6
6
|
import { trough as A } from "../../trough/lib/index.js";
|