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 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
@@ -1,8 +1,8 @@
1
1
  "use client";
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);
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
- a as default
7
+ m as default
8
8
  };
@@ -1,8 +1,8 @@
1
1
  "use client";
2
- import { getDefaultExportFromCjs as e } from "./_commonjsHelpers.js";
3
- import { __require as r } from "../node_modules/extend/index.js";
4
- var t = r();
5
- const x = /* @__PURE__ */ e(t);
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
- x as default
7
+ a as default
8
8
  };
@@ -1,8 +1,8 @@
1
1
  "use client";
2
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);
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
- m as default
7
+ x as default
8
8
  };
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "schemaVersion": "1.0.0",
3
- "generatedAt": "2026-09-17T14:06:59.977Z",
3
+ "generatedAt": "2026-09-18T09:11:12.858Z",
4
4
  "package": {
5
5
  "name": "laif-ds",
6
- "version": "1.0.1"
6
+ "version": "1.0.2"
7
7
  },
8
8
  "summary": {
9
9
  "scannedFiles": 404,
@@ -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** → the **Menu** cell takes the pill, with
235
- no `aria-current` and no `aria-expanded="true"`. Five neutral cells read as
236
- "the component failed to work out where I am"; the truthful statement is "the
237
- page you are on is reachable through here", and it is redundant for a screen
238
- reader, so nothing is added to the accessibility tree. With
239
- `showMenu={false}` there is nothing to hand the pill to and the bar does
240
- render entirely neutral — the honest state when every cell is a destination
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-17T14:06:59.635Z",
3
+ "generatedAt": "2026-09-18T09:11:12.439Z",
4
4
  "package": {
5
5
  "name": "laif-ds",
6
- "version": "1.0.1"
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": "6d71f6092cca54ea1fdea59df4b6183f71bc704e35db1492384da4abe5a5d129"
6315
+ "checksum": "1b95270b522d7fdbd54fa834020be6d9bf1b0632fda8a9458556d024398a8574"
6316
6316
  }
@@ -1,13 +1,13 @@
1
1
  "use client";
2
- import { jsxs as m, jsx as o, Fragment as Q } from "react/jsx-runtime";
3
- import * as U from "react";
4
- import { designTokens as V } from "../design-tokens.js";
5
- import { navTokens as P } from "../nav-tokens.js";
6
- import { Icon as W } from "./icon.js";
7
- import { warnOnce as c, someRowBadged as w, normalizeNavBadge as Y, NavBadgeOverlay as Z, NavBadgeDot as A, NavBadgeSrLabel as ee } from "./nav-badge.js";
8
- import { useSidebar as te } from "./sidebar.js";
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 $ = 6, S = (a) => `${a.url} ${a.title}`, T = (a) => !!a.isActive || !!a.subItems?.some((n) => n.isActive), ae = "md:hidden shrink-0 overflow-hidden bg-d-card border-d-border rounded-t-lg border-t pb-[env(safe-area-inset-bottom)]", ne = "flex items-stretch p-1", g = r(
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
- P.item.basePill,
26
- V.focusRing,
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
- ), N = P.item.selectedPill, j = "relative flex size-5 shrink-0 items-center justify-center", d = (a, n) => /* @__PURE__ */ m("span", { className: j, children: [
35
- /* @__PURE__ */ o(W, { name: a, size: "sm", className: "shrink-0" }),
36
- n
37
- ] }), oe = (a, n) => /* @__PURE__ */ m("span", { className: r(j, "[&>svg]:size-full"), children: [
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
- n
40
- ] }), se = "-top-1 -right-1.5", M = "absolute -top-1 -right-1", x = (a, n, p) => /* @__PURE__ */ m(Q, { children: [
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__ */ o("span", { className: "w-full truncate text-center", children: n }),
43
- p
42
+ /* @__PURE__ */ n("span", { className: "w-full truncate text-center", children: o }),
43
+ m
44
44
  ] });
45
- function ue({
45
+ function pe({
46
46
  items: a,
47
- showMenu: n = !0,
48
- menuLabel: p = "Menu",
49
- ariaLabel: D = "Main navigation",
50
- menuIcon: u = "Menu",
51
- menuBadge: z = !1,
52
- linkComponent: I,
53
- linkProps: E = {},
54
- className: R,
55
- ...F
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: B, setOpenMobile: C, mobileNavTarget: K, setMobileNavTarget: L } = te(), v = n ? $ - 1 : $, l = a.slice(0, v), b = a.slice(v);
58
- if (b.length > 0) {
59
- const e = b.map((t) => `"${t.title}"`).join(", ");
60
- c(
61
- `AppBottomNav: ${a.length} items passed, ${v} slots available. Dropped: ${e}.`
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 k = /* @__PURE__ */ new Set();
64
+ const L = /* @__PURE__ */ new Set();
65
65
  for (const e of l) {
66
- const t = S(e);
67
- k.has(t) && c(
66
+ const t = $(e);
67
+ L.has(t) && i(
68
68
  `AppBottomNav: duplicate item "${t}" — one of them is ignored.`
69
- ), k.add(t);
69
+ ), L.add(t);
70
70
  }
71
- const i = l.findIndex(T);
72
- l.filter(T).length > 1 && c(
73
- `AppBottomNav: more than one active item — "${l[i].title}" wins.`
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 y = n && i === -1, G = z || w(b), X = (() => {
76
- const e = G ? /* @__PURE__ */ o(A, { className: M }) : null;
77
- if (typeof u == "string") return d(u, e);
78
- const t = u();
79
- return t == null ? d("Menu", e) : oe(t, e);
80
- })(), O = (e) => {
81
- const t = Y(e.badge, "compact", e.title), s = /* @__PURE__ */ o(ee, { row: e, badge: 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__ */ o(Z, { text: t.text, className: se }),
83
+ visual: /* @__PURE__ */ n(Y, { text: t.text, className: oe }),
84
84
  srLabel: s
85
- } : t?.kind === "dot" || w(e.subItems) ? { visual: /* @__PURE__ */ o(A, { className: M }), srLabel: s } : { visual: null, srLabel: s };
86
- }, q = (e, t) => {
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 ? N : h
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: J } = O(e), _ = x(
99
- d(e.iconName, f),
98
+ }, { visual: f, srLabel: H } = k(e), y = N(
99
+ c(e.iconName, f),
100
100
  e.title,
101
- J
101
+ H
102
102
  );
103
- return I ? /* @__PURE__ */ o(I, { href: e.url, ...s, ...E, children: _ }) : /* @__PURE__ */ o("a", { href: e.url, ...s, children: _ });
104
- }, H = (e, t) => {
105
- const { visual: s, srLabel: f } = O(e);
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__ */ o(
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": B && K === e.title,
118
+ "aria-expanded": I && F === e.title,
119
119
  className: r(
120
120
  g,
121
- t ? N : h
121
+ t ? M : h
122
122
  ),
123
123
  onClick: () => {
124
- L(e.title), C(!0);
124
+ C(e.title), B(!0);
125
125
  },
126
- children: x(d(e.iconName, s), e.title, f)
126
+ children: N(c(e.iconName, s), e.title, f)
127
127
  }
128
128
  )
129
129
  );
130
130
  };
131
- return l.length === 0 && !n ? (c(
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__ */ o(
133
+ ), null) : /* @__PURE__ */ n(
134
134
  "div",
135
135
  {
136
136
  "data-slot": "app-bottom-nav",
137
- className: r(ae, R),
138
- ...F,
139
- children: /* @__PURE__ */ m("nav", { "aria-label": D, className: ne, children: [
140
- l.map((e, t) => /* @__PURE__ */ o(U.Fragment, { children: e.subItems?.length ? H(e, t === i) : q(e, t === i) }, S(e))),
141
- n && /* @__PURE__ */ o(
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
- "data-active": y ? "true" : void 0,
147
- "aria-expanded": B,
148
- className: r(
149
- g,
150
- y ? N : h
151
- ),
146
+ "aria-expanded": I,
147
+ className: r(g, h),
152
148
  onClick: () => {
153
- L(null), C(!0);
149
+ C(null), B(!0);
154
150
  },
155
- children: x(X, p)
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
- ue as AppBottomNav
159
+ pe as AppBottomNav
164
160
  };
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- import e from "../../_virtual/index5.js";
2
+ import e from "../../_virtual/index3.js";
3
3
  export {
4
4
  e as EventEmitter,
5
5
  e as default
@@ -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/index3.js";
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,5 +1,5 @@
1
1
  "use client";
2
- import e from "../../../../_virtual/index5.js";
2
+ import e from "../../../../_virtual/index3.js";
3
3
  var r = new e(), n = "recharts.syncEvent.tooltip";
4
4
  export {
5
5
  n as TOOLTIP_SYNC_EVENT,
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
  import { bail as P } from "../../bail/index.js";
3
- import y from "../../../_virtual/index4.js";
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";
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "laif-ds",
3
3
  "private": false,
4
- "version": "1.0.1",
4
+ "version": "1.0.2",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "module": "dist/index.js",