basalt-ui 1.18.0 → 1.19.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/AGENTS.md +1 -1
- package/CHANGELOG.md +7 -0
- package/agent/rules/basalt-mantine.md +71 -6
- package/agent/rules/basalt-router.md +129 -30
- package/agent/rules/basalt-tokens.md +2 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -0
- package/dist/nav/types.d.ts +110 -0
- package/dist/nav/types.d.ts.map +1 -0
- package/dist/nav/types.js +0 -0
- package/dist/router-tanstack/index.d.ts +9 -2
- package/dist/router-tanstack/index.d.ts.map +1 -1
- package/dist/router-tanstack/index.js +7 -0
- package/dist/router-tanstack/nav.d.ts +163 -0
- package/dist/router-tanstack/nav.d.ts.map +1 -0
- package/dist/router-tanstack/nav.js +38 -0
- package/dist/router-tanstack/nav.test.d.ts +2 -0
- package/dist/router-tanstack/nav.test.d.ts.map +1 -0
- package/dist/router-tanstack/search-param-store.d.ts +19 -9
- package/dist/router-tanstack/search-param-store.d.ts.map +1 -1
- package/dist/router-tanstack/use-nav.d.ts +30 -0
- package/dist/router-tanstack/use-nav.d.ts.map +1 -0
- package/dist/router-tanstack/use-nav.js +71 -0
- package/dist/shell/app-breadcrumbs.d.ts +7 -9
- package/dist/shell/app-breadcrumbs.d.ts.map +1 -1
- package/dist/shell/app-breadcrumbs.js +8 -4
- package/dist/shell/app-mobile-nav.d.ts +23 -24
- package/dist/shell/app-mobile-nav.d.ts.map +1 -1
- package/dist/shell/app-mobile-nav.js +290 -68
- package/dist/shell/app-mobile-nav.module.css +166 -11
- package/dist/shell/app-mobile-nav.module.css.d.ts +11 -2
- package/dist/shell/app-mobile-nav.test.d.ts +2 -0
- package/dist/shell/app-mobile-nav.test.d.ts.map +1 -0
- package/dist/shell/app-sidebar.d.ts +3 -28
- package/dist/shell/app-sidebar.d.ts.map +1 -1
- package/dist/shell/app-sidebar.js +40 -174
- package/dist/shell/app-sidebar.module.css +3 -2
- package/dist/shell/app-sidebar.module.css.d.ts +0 -2
- package/dist/shell/index.d.ts +22 -65
- package/dist/shell/index.d.ts.map +1 -1
- package/dist/shell/index.js +38 -76
- package/dist/shell/mobile-nav-model.d.ts +41 -0
- package/dist/shell/mobile-nav-model.d.ts.map +1 -0
- package/dist/shell/mobile-nav-model.js +244 -0
- package/dist/shell/mobile-nav-model.test.d.ts +2 -0
- package/dist/shell/mobile-nav-model.test.d.ts.map +1 -0
- package/dist/shell/nav-count-badge.d.ts +11 -0
- package/dist/shell/nav-count-badge.d.ts.map +1 -0
- package/dist/shell/nav-count-badge.js +29 -0
- package/dist/surfaces.d.ts +1 -1
- package/dist/surfaces.js +1 -1
- package/dist/theme/index.d.ts.map +1 -1
- package/dist/theme/index.js +8 -7
- package/dist/theme/nav-link.module.css +4 -2
- package/dist/tokens/index.d.ts.map +1 -1
- package/dist/tokens/index.js +2 -0
- package/dist/tokens/palette.d.ts +15 -0
- package/dist/tokens/palette.d.ts.map +1 -1
- package/dist/tokens/palette.js +13 -0
- package/dist/tokens.css +2 -0
- package/llms.txt +3 -3
- package/package.json +1 -1
- package/src/index.ts +15 -5
- package/src/nav/types.ts +115 -0
- package/src/router-tanstack/index.ts +21 -2
- package/src/router-tanstack/nav.test.ts +111 -0
- package/src/router-tanstack/nav.ts +205 -0
- package/src/router-tanstack/search-param-store.ts +19 -9
- package/src/router-tanstack/use-nav.ts +146 -0
- package/src/shell/app-breadcrumbs.tsx +21 -19
- package/src/shell/app-mobile-nav.module.css +166 -11
- package/src/shell/app-mobile-nav.module.css.d.ts +11 -2
- package/src/shell/app-mobile-nav.test.tsx +369 -0
- package/src/shell/app-mobile-nav.tsx +436 -102
- package/src/shell/app-sidebar.module.css +3 -2
- package/src/shell/app-sidebar.module.css.d.ts +0 -2
- package/src/shell/app-sidebar.test.tsx +6 -10
- package/src/shell/app-sidebar.tsx +49 -206
- package/src/shell/index.test.tsx +62 -7
- package/src/shell/index.tsx +105 -164
- package/src/shell/mobile-nav-model.test.ts +296 -0
- package/src/shell/mobile-nav-model.ts +389 -0
- package/src/shell/nav-count-badge.tsx +39 -0
- package/src/surfaces.ts +1 -1
- package/src/theme/density-relations.test.ts +19 -1
- package/src/theme/index.ts +8 -7
- package/src/theme/nav-link.module.css +4 -2
- package/src/theme/spacing.test.ts +11 -0
- package/src/tokens/density.test.ts +2 -0
- package/src/tokens/index.ts +8 -5
- package/src/tokens/palette.ts +16 -0
package/dist/shell/index.js
CHANGED
|
@@ -1,44 +1,28 @@
|
|
|
1
1
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { AppShell
|
|
3
|
-
import {
|
|
2
|
+
import { AppShell } from "@mantine/core";
|
|
3
|
+
import { useLocalStorage } from "@mantine/hooks";
|
|
4
|
+
import { useMemo } from "react";
|
|
4
5
|
import { AppSidebar } from "./app-sidebar.js";
|
|
5
|
-
import { MobileNav } from "./app-mobile-nav.js";
|
|
6
|
+
import { MobileNav, accountRowCount } from "./app-mobile-nav.js";
|
|
7
|
+
import { projectMobileNav } from "./mobile-nav-model.js";
|
|
6
8
|
import { AppBreadcrumbs } from "./app-breadcrumbs.js";
|
|
7
9
|
import { PageActionsOutlet, PageHeaderProvider } from "./page-header.js";
|
|
8
|
-
import { VX } from "../tokens/index.js";
|
|
9
10
|
import { useBasaltSpacing } from "../theme/index.js";
|
|
10
11
|
import headerClasses from "./app-header.module.css";
|
|
12
|
+
import mobileNavClasses from "./app-mobile-nav.module.css";
|
|
11
13
|
import { AppSidebar as AppSidebar2 } from "./app-sidebar.js";
|
|
14
|
+
import { NavCountBadge } from "./nav-count-badge.js";
|
|
12
15
|
import { SidebarSearch } from "./sidebar-search.js";
|
|
13
16
|
import { SidebarAccount } from "./app-sidebar-account.js";
|
|
17
|
+
import { MobileNav as MobileNav2 } from "./app-mobile-nav.js";
|
|
14
18
|
import {
|
|
15
|
-
|
|
16
|
-
|
|
19
|
+
projectMobileNav as projectMobileNav2,
|
|
20
|
+
MOBILE_MAX_TABS_DEFAULT,
|
|
21
|
+
MOBILE_MENU_MAX_DEFAULT,
|
|
22
|
+
MOBILE_MORE_KEY
|
|
23
|
+
} from "./mobile-nav-model.js";
|
|
17
24
|
import { AppBreadcrumbs as AppBreadcrumbs2 } from "./app-breadcrumbs.js";
|
|
18
25
|
import { PageHeaderProvider as PageHeaderProvider2, PageActions, PageActionsOutlet as PageActionsOutlet2 } from "./page-header.js";
|
|
19
|
-
function NavCountBadge({ count }) {
|
|
20
|
-
if (!count) return null;
|
|
21
|
-
return /* @__PURE__ */ jsx(
|
|
22
|
-
Badge,
|
|
23
|
-
{
|
|
24
|
-
size: "sm",
|
|
25
|
-
styles: {
|
|
26
|
-
root: {
|
|
27
|
-
backgroundColor: "color-mix(in srgb, var(--vx-ink) 8%, transparent)",
|
|
28
|
-
color: "var(--vx-muted)",
|
|
29
|
-
fontFamily: "var(--basalt-font-mono)",
|
|
30
|
-
fontSize: VX.text.micro,
|
|
31
|
-
fontWeight: 500,
|
|
32
|
-
height: 16,
|
|
33
|
-
padding: "0 5px",
|
|
34
|
-
marginLeft: "auto",
|
|
35
|
-
borderRadius: "var(--vx-radius-tight)"
|
|
36
|
-
}
|
|
37
|
-
},
|
|
38
|
-
children: count
|
|
39
|
-
}
|
|
40
|
-
);
|
|
41
|
-
}
|
|
42
26
|
function findActiveCrumb(sections) {
|
|
43
27
|
for (const section of sections) {
|
|
44
28
|
const found = findActiveWithParent(section.items);
|
|
@@ -46,67 +30,38 @@ function findActiveCrumb(sections) {
|
|
|
46
30
|
return {
|
|
47
31
|
section: section.label,
|
|
48
32
|
parent: found.parent,
|
|
33
|
+
parentAnchor: found.parentAnchor,
|
|
49
34
|
parentHref: found.parentHref,
|
|
50
35
|
page: found.page
|
|
51
36
|
};
|
|
52
37
|
}
|
|
53
38
|
return void 0;
|
|
54
39
|
}
|
|
55
|
-
function findActiveWithParent(items, parentLabel, parentHref) {
|
|
40
|
+
function findActiveWithParent(items, parentLabel, parentAnchor, parentHref) {
|
|
56
41
|
for (const item of items) {
|
|
57
42
|
if (item.children) {
|
|
58
|
-
const found = findActiveWithParent(item.children, item.label, item.href);
|
|
43
|
+
const found = findActiveWithParent(item.children, item.label, item.Anchor, item.href);
|
|
59
44
|
if (found) return found;
|
|
60
45
|
}
|
|
61
|
-
if (item.active) return { parent: parentLabel, parentHref, page: item.label };
|
|
46
|
+
if (item.active) return { parent: parentLabel, parentAnchor, parentHref, page: item.label };
|
|
62
47
|
}
|
|
63
48
|
return void 0;
|
|
64
49
|
}
|
|
65
|
-
function toMobileSections(sections, closeMobile) {
|
|
66
|
-
return sections.filter((s) => s.mobileTab !== false).map((s) => ({
|
|
67
|
-
key: s.label,
|
|
68
|
-
label: s.label,
|
|
69
|
-
icon: s.icon,
|
|
70
|
-
active: s.items.some((i) => i.active),
|
|
71
|
-
items: flattenSidebarItems(s.items).map(
|
|
72
|
-
(i) => ({
|
|
73
|
-
key: i.key,
|
|
74
|
-
label: i.label,
|
|
75
|
-
icon: i.icon,
|
|
76
|
-
...i.href !== void 0 && { href: i.href },
|
|
77
|
-
...i.active !== void 0 && { active: i.active },
|
|
78
|
-
onClick: (e) => {
|
|
79
|
-
i.onClick?.(e);
|
|
80
|
-
closeMobile();
|
|
81
|
-
}
|
|
82
|
-
})
|
|
83
|
-
)
|
|
84
|
-
}));
|
|
85
|
-
}
|
|
86
|
-
function flattenSidebarItems(items) {
|
|
87
|
-
return items.flatMap((item) => [
|
|
88
|
-
item,
|
|
89
|
-
...item.children ? flattenSidebarItems(item.children) : []
|
|
90
|
-
]);
|
|
91
|
-
}
|
|
92
50
|
function BasaltShell({
|
|
93
51
|
brand,
|
|
94
52
|
sections,
|
|
95
|
-
|
|
53
|
+
mobileNav,
|
|
96
54
|
globalActions,
|
|
97
|
-
sidebarFooterExtra,
|
|
98
55
|
sidebarNavExtra,
|
|
99
56
|
settingsMenuItems,
|
|
100
57
|
storageKey = "basalt-sidebar-collapsed",
|
|
101
58
|
collapsed: collapsedProp,
|
|
102
59
|
onCollapsedChange,
|
|
103
|
-
renderBreadcrumbLink,
|
|
104
60
|
account,
|
|
105
61
|
search,
|
|
106
62
|
children
|
|
107
63
|
}) {
|
|
108
64
|
const { step } = useBasaltSpacing();
|
|
109
|
-
const [mobileOpened, { toggle: toggleMobile, close: closeMobile }] = useDisclosure();
|
|
110
65
|
const [storedCollapsed, setStoredCollapsed] = useLocalStorage({
|
|
111
66
|
key: storageKey,
|
|
112
67
|
defaultValue: false,
|
|
@@ -120,7 +75,11 @@ function BasaltShell({
|
|
|
120
75
|
onCollapsedChange?.(next);
|
|
121
76
|
};
|
|
122
77
|
const activeCrumb = findActiveCrumb(sections);
|
|
123
|
-
const
|
|
78
|
+
const extraMoreRows = accountRowCount(account) + (settingsMenuItems?.length ?? 0) + (mobileNav?.moreExtra ? 1 : 0);
|
|
79
|
+
const model = useMemo(
|
|
80
|
+
() => projectMobileNav(sections, { config: mobileNav, extraMoreRows }),
|
|
81
|
+
[sections, mobileNav, extraMoreRows]
|
|
82
|
+
);
|
|
124
83
|
return /* @__PURE__ */ jsx(PageHeaderProvider, { children: /* @__PURE__ */ jsxs(
|
|
125
84
|
AppShell,
|
|
126
85
|
{
|
|
@@ -135,13 +94,14 @@ function BasaltShell({
|
|
|
135
94
|
sm: collapsed ? step.appShellNavbarRailWidth : step.appShellNavbarWidth
|
|
136
95
|
},
|
|
137
96
|
breakpoint: "sm",
|
|
138
|
-
|
|
97
|
+
// No mobile sidebar drawer, ever — the bottom bar is the entire mobile nav.
|
|
98
|
+
collapsed: { mobile: true }
|
|
139
99
|
},
|
|
140
|
-
footer: { height: { base:
|
|
100
|
+
footer: { height: { base: step.mobileNavBarHeight, sm: 0 } },
|
|
141
101
|
padding: "sm",
|
|
142
102
|
children: [
|
|
143
103
|
/* @__PURE__ */ jsx(AppShell.Header, { px: "md", withBorder: false, children: /* @__PURE__ */ jsxs("div", { className: headerClasses.bar, children: [
|
|
144
|
-
/* @__PURE__ */ jsx("div", { className: headerClasses.lead, children: /* @__PURE__ */ jsx(AppBreadcrumbs, { ...activeCrumb
|
|
104
|
+
/* @__PURE__ */ jsx("div", { className: headerClasses.lead, children: /* @__PURE__ */ jsx(AppBreadcrumbs, { ...activeCrumb }) }),
|
|
145
105
|
/* @__PURE__ */ jsx(PageActionsOutlet, { className: headerClasses.pageActions }),
|
|
146
106
|
globalActions && /* @__PURE__ */ jsx("div", { className: headerClasses.global, children: globalActions })
|
|
147
107
|
] }) }),
|
|
@@ -152,22 +112,20 @@ function BasaltShell({
|
|
|
152
112
|
sections,
|
|
153
113
|
collapsed,
|
|
154
114
|
onToggleCollapse: toggleCollapse,
|
|
155
|
-
onClose: closeMobile,
|
|
156
|
-
footerExtra: sidebarFooterExtra,
|
|
157
115
|
navExtra: sidebarNavExtra,
|
|
158
|
-
...renderNavLink !== void 0 && { renderNavLink },
|
|
159
116
|
...settingsMenuItems !== void 0 && { settingsMenuItems },
|
|
160
117
|
...account !== void 0 && { account },
|
|
161
118
|
...search !== void 0 && { search }
|
|
162
119
|
}
|
|
163
120
|
) }),
|
|
164
|
-
/* @__PURE__ */ jsx(AppShell.Main, { children }),
|
|
165
|
-
/* @__PURE__ */ jsx(AppShell.Footer, { hiddenFrom: "sm", p: 0, children: /* @__PURE__ */ jsx(
|
|
121
|
+
/* @__PURE__ */ jsx(AppShell.Main, { className: mobileNavClasses.mainSafeArea, children }),
|
|
122
|
+
/* @__PURE__ */ jsx(AppShell.Footer, { hiddenFrom: "sm", p: 0, withBorder: false, children: /* @__PURE__ */ jsx(
|
|
166
123
|
MobileNav,
|
|
167
124
|
{
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
...
|
|
125
|
+
model,
|
|
126
|
+
config: mobileNav,
|
|
127
|
+
...account !== void 0 && { account },
|
|
128
|
+
...settingsMenuItems !== void 0 && { settingsMenuItems }
|
|
171
129
|
}
|
|
172
130
|
) })
|
|
173
131
|
]
|
|
@@ -178,11 +136,15 @@ export {
|
|
|
178
136
|
AppBreadcrumbs2 as AppBreadcrumbs,
|
|
179
137
|
AppSidebar2 as AppSidebar,
|
|
180
138
|
BasaltShell,
|
|
139
|
+
MOBILE_MAX_TABS_DEFAULT,
|
|
140
|
+
MOBILE_MENU_MAX_DEFAULT,
|
|
141
|
+
MOBILE_MORE_KEY,
|
|
181
142
|
MobileNav2 as MobileNav,
|
|
182
143
|
NavCountBadge,
|
|
183
144
|
PageActions,
|
|
184
145
|
PageActionsOutlet2 as PageActionsOutlet,
|
|
185
146
|
PageHeaderProvider2 as PageHeaderProvider,
|
|
186
147
|
SidebarAccount,
|
|
187
|
-
SidebarSearch
|
|
148
|
+
SidebarSearch,
|
|
149
|
+
projectMobileNav2 as projectMobileNav
|
|
188
150
|
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The mobile-bar projection — `SidebarSection[]` + `MobileNavConfig` → `MobileNavModel`.
|
|
3
|
+
*
|
|
4
|
+
* PURE BY CONTRACT: no React, no Mantine, no DOM, no JSX. Everything the bottom bar decides —
|
|
5
|
+
* which destinations get a slot, which slot is a plain navigation link and which raises a surface,
|
|
6
|
+
* whether that surface is a menu or a sheet, what falls into the overflow "More" slot — is decided
|
|
7
|
+
* here and unit-testable with no renderer. `app-mobile-nav.tsx` only paints the result.
|
|
8
|
+
*
|
|
9
|
+
* The law it implements is the interaction model, not a heuristic: a slot is a DESTINATION, so a
|
|
10
|
+
* tap navigates with no overlay to dismiss. An overlay exists only where a slot genuinely holds
|
|
11
|
+
* more than one destination, and its surface is INFERRED from how many rows it holds rather than
|
|
12
|
+
* configured — six rows is the arithmetic ceiling for a menu that pops out of a 56px bar without
|
|
13
|
+
* ever rendering below the fold (6 x 44px + 8px padding = 272px against 415px of headroom on the
|
|
14
|
+
* smallest supported viewport), so past that the surface becomes a bottom sheet.
|
|
15
|
+
*/
|
|
16
|
+
import type { MobileNavConfig, MobileNavModel, SidebarSection } from '../nav/types.js';
|
|
17
|
+
/** Hard cap on bar slots, INCLUDING More. Five 72px slots is the widest a 360px viewport holds. */
|
|
18
|
+
export declare const MOBILE_MAX_TABS_DEFAULT = 5;
|
|
19
|
+
/**
|
|
20
|
+
* Rows a slot may hold before it becomes a sheet instead of a menu. Arithmetic, not taste — see
|
|
21
|
+
* the module doc: six rows is the last count a bottom-anchored, non-flipping menu fits above the
|
|
22
|
+
* bar on the smallest supported viewport.
|
|
23
|
+
*/
|
|
24
|
+
export declare const MOBILE_MENU_MAX_DEFAULT = 6;
|
|
25
|
+
/** The overflow slot's reserved key. A slot like any other — it just exists only when needed. */
|
|
26
|
+
export declare const MOBILE_MORE_KEY = "__more";
|
|
27
|
+
export type ProjectMobileNavOptions = {
|
|
28
|
+
config?: MobileNavConfig | undefined;
|
|
29
|
+
/**
|
|
30
|
+
* Extra rows the More surface will hold — account + settings + `moreExtra`. Drives both
|
|
31
|
+
* `needsMore` and the menu-vs-sheet threshold. The model cannot see those rows (they are
|
|
32
|
+
* Mantine-rendered chrome, not `SidebarItem`s), so the shell counts them and passes the total.
|
|
33
|
+
*/
|
|
34
|
+
extraMoreRows?: number;
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* Projects `sections` onto the bar. Implements §2.3's thirteen rules in order, and is the ONLY
|
|
38
|
+
* place slot selection happens — `MobileNav` receives a finished model and paints it.
|
|
39
|
+
*/
|
|
40
|
+
export declare function projectMobileNav(sections: SidebarSection[], opts?: ProjectMobileNavOptions): MobileNavModel;
|
|
41
|
+
//# sourceMappingURL=mobile-nav-model.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mobile-nav-model.d.ts","sourceRoot":"","sources":["../../src/shell/mobile-nav-model.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,KAAK,EACV,eAAe,EAEf,cAAc,EAId,cAAc,EACf,MAAM,cAAc,CAAA;AAErB,mGAAmG;AACnG,eAAO,MAAM,uBAAuB,IAAI,CAAA;AAExC;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,IAAI,CAAA;AAExC,iGAAiG;AACjG,eAAO,MAAM,eAAe,WAAW,CAAA;AAEvC,MAAM,MAAM,uBAAuB,GAAG;IACpC,MAAM,CAAC,EAAE,eAAe,GAAG,SAAS,CAAA;IACpC;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB,CAAA;AAoQD;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,cAAc,EAAE,EAC1B,IAAI,CAAC,EAAE,uBAAuB,GAC7B,cAAc,CA2EhB"}
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
const MOBILE_MAX_TABS_DEFAULT = 5;
|
|
2
|
+
const MOBILE_MENU_MAX_DEFAULT = 6;
|
|
3
|
+
const MOBILE_MORE_KEY = "__more";
|
|
4
|
+
const DEV = process.env["NODE_ENV"] !== "production";
|
|
5
|
+
function placementOf(item, sectionHidden) {
|
|
6
|
+
if (sectionHidden) return "hidden";
|
|
7
|
+
const mobile = item.mobile;
|
|
8
|
+
if (mobile === void 0) return "more";
|
|
9
|
+
if (mobile === true) return "tab";
|
|
10
|
+
if (mobile === false) return "hidden";
|
|
11
|
+
return mobile;
|
|
12
|
+
}
|
|
13
|
+
function isSectionHidden(section) {
|
|
14
|
+
return section.mobile === false;
|
|
15
|
+
}
|
|
16
|
+
function hasActiveDestination(item) {
|
|
17
|
+
if (item.active) return true;
|
|
18
|
+
return item.children?.some(hasActiveDestination) ?? false;
|
|
19
|
+
}
|
|
20
|
+
function countRows(items) {
|
|
21
|
+
return items.reduce((total, item) => total + 1 + countRows(item.children ?? []), 0);
|
|
22
|
+
}
|
|
23
|
+
function collectKeys(items, out) {
|
|
24
|
+
for (const item of items) {
|
|
25
|
+
out.add(item.key);
|
|
26
|
+
collectKeys(item.children ?? [], out);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
function flattenItems(items, out) {
|
|
30
|
+
for (const item of items) {
|
|
31
|
+
out.push(item);
|
|
32
|
+
flattenItems(item.children ?? [], out);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
function pruneTree(items, keep) {
|
|
36
|
+
const out = [];
|
|
37
|
+
for (const item of items) {
|
|
38
|
+
const children = pruneTree(item.children ?? [], keep);
|
|
39
|
+
if (!keep(item)) {
|
|
40
|
+
out.push(...children);
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
const next = { ...item };
|
|
44
|
+
if (children.length > 0) next.children = children;
|
|
45
|
+
else delete next.children;
|
|
46
|
+
out.push(next);
|
|
47
|
+
}
|
|
48
|
+
return out;
|
|
49
|
+
}
|
|
50
|
+
function itemCandidate(item) {
|
|
51
|
+
return {
|
|
52
|
+
key: item.key,
|
|
53
|
+
covered: /* @__PURE__ */ new Set([item.key]),
|
|
54
|
+
toSlot: () => ({
|
|
55
|
+
kind: "link",
|
|
56
|
+
key: item.key,
|
|
57
|
+
label: item.label,
|
|
58
|
+
short: item.short ?? item.label,
|
|
59
|
+
icon: item.icon,
|
|
60
|
+
active: hasActiveDestination(item),
|
|
61
|
+
item
|
|
62
|
+
})
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
function sectionCandidate(section, menuMax) {
|
|
66
|
+
const mobile = section.mobile === false || section.mobile === void 0 ? void 0 : section.mobile;
|
|
67
|
+
const items = pruneTree(section.items, (item) => placementOf(item, false) !== "hidden");
|
|
68
|
+
const covered = /* @__PURE__ */ new Set();
|
|
69
|
+
collectKeys(items, covered);
|
|
70
|
+
const label = mobile?.label ?? section.label;
|
|
71
|
+
const rows = countRows(items);
|
|
72
|
+
const only = items[0];
|
|
73
|
+
return {
|
|
74
|
+
key: section.label,
|
|
75
|
+
covered,
|
|
76
|
+
toSlot: () => {
|
|
77
|
+
if (rows === 0) return void 0;
|
|
78
|
+
if (rows === 1 && only !== void 0 && !only.disabled) {
|
|
79
|
+
return {
|
|
80
|
+
kind: "link",
|
|
81
|
+
key: only.key,
|
|
82
|
+
label,
|
|
83
|
+
short: label,
|
|
84
|
+
// The section's own identity wins when it declares one — the consumer configured the
|
|
85
|
+
// SLOT — and falls back to the single destination's icon when it does not.
|
|
86
|
+
icon: mobile?.icon ?? section.icon ?? only.icon,
|
|
87
|
+
active: hasActiveDestination(only),
|
|
88
|
+
item: only
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
return {
|
|
92
|
+
kind: rows <= menuMax ? "menu" : "sheet",
|
|
93
|
+
key: section.label,
|
|
94
|
+
label,
|
|
95
|
+
short: label,
|
|
96
|
+
icon: mobile?.icon ?? section.icon,
|
|
97
|
+
active: items.some(hasActiveDestination),
|
|
98
|
+
// One section, so the rows need no group heading — the tab itself names them.
|
|
99
|
+
groups: [{ key: section.label, items }],
|
|
100
|
+
isMore: false
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
function buildCandidates(sections, config, maxTabs, menuMax) {
|
|
106
|
+
const flat = [];
|
|
107
|
+
for (const section of sections) {
|
|
108
|
+
if (isSectionHidden(section)) continue;
|
|
109
|
+
flattenItems(section.items, flat);
|
|
110
|
+
}
|
|
111
|
+
const tabbable = (item) => {
|
|
112
|
+
if (!item.disabled) return true;
|
|
113
|
+
if (DEV) {
|
|
114
|
+
console.warn(
|
|
115
|
+
`[basalt] MobileNav: "${item.key}" asks for a bar slot but is disabled \u2014 a disabled destination never becomes a tab. It still renders, disabled, in the More surface.`
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
return false;
|
|
119
|
+
};
|
|
120
|
+
if (config?.tabs !== void 0) {
|
|
121
|
+
const candidates2 = [];
|
|
122
|
+
for (const id of config.tabs) {
|
|
123
|
+
const item = flat.find((candidate) => candidate.key === id);
|
|
124
|
+
if (item !== void 0) {
|
|
125
|
+
if (tabbable(item)) candidates2.push(itemCandidate(item));
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
const section = sections.find((s) => s.label === id && !isSectionHidden(s));
|
|
129
|
+
if (section !== void 0) {
|
|
130
|
+
candidates2.push(sectionCandidate(section, menuMax));
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
133
|
+
if (DEV) {
|
|
134
|
+
console.warn(
|
|
135
|
+
`[basalt] MobileNav: mobileNav.tabs names "${id}", which is neither a destination key nor a visible section label \u2014 ignoring it.`
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
return candidates2;
|
|
140
|
+
}
|
|
141
|
+
const candidates = [];
|
|
142
|
+
for (const section of sections) {
|
|
143
|
+
if (isSectionHidden(section)) continue;
|
|
144
|
+
if (section.mobile !== void 0 && section.mobile !== false && section.mobile.tab === true) {
|
|
145
|
+
candidates.push(sectionCandidate(section, menuMax));
|
|
146
|
+
continue;
|
|
147
|
+
}
|
|
148
|
+
const items = [];
|
|
149
|
+
flattenItems(section.items, items);
|
|
150
|
+
for (const item of items) {
|
|
151
|
+
if (placementOf(item, false) !== "tab") continue;
|
|
152
|
+
if (tabbable(item)) candidates.push(itemCandidate(item));
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
if (candidates.length > 0) return candidates;
|
|
156
|
+
const fallback = [];
|
|
157
|
+
for (const section of sections) {
|
|
158
|
+
if (isSectionHidden(section)) continue;
|
|
159
|
+
for (const item of section.items) {
|
|
160
|
+
if (fallback.length >= maxTabs - 1) return fallback;
|
|
161
|
+
if (item.disabled) continue;
|
|
162
|
+
if (placementOf(item, false) === "hidden") continue;
|
|
163
|
+
fallback.push(itemCandidate(item));
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
return fallback;
|
|
167
|
+
}
|
|
168
|
+
function buildOverflow(sections, covered) {
|
|
169
|
+
const groups = [];
|
|
170
|
+
for (const section of sections) {
|
|
171
|
+
const hidden = isSectionHidden(section);
|
|
172
|
+
if (hidden) continue;
|
|
173
|
+
const items = pruneTree(
|
|
174
|
+
section.items,
|
|
175
|
+
(item) => placementOf(item, hidden) !== "hidden" && !covered.has(item.key)
|
|
176
|
+
);
|
|
177
|
+
if (items.length === 0) continue;
|
|
178
|
+
groups.push({ key: section.label, label: section.label, items });
|
|
179
|
+
}
|
|
180
|
+
return groups;
|
|
181
|
+
}
|
|
182
|
+
function projectMobileNav(sections, opts) {
|
|
183
|
+
const config = opts?.config;
|
|
184
|
+
const maxTabs = Math.max(1, config?.maxTabs ?? MOBILE_MAX_TABS_DEFAULT);
|
|
185
|
+
const menuMax = Math.max(1, config?.menuMax ?? MOBILE_MENU_MAX_DEFAULT);
|
|
186
|
+
const extraMoreRows = opts?.extraMoreRows ?? 0;
|
|
187
|
+
const candidates = buildCandidates(sections, config, maxTabs, menuMax);
|
|
188
|
+
const coveredByAll = /* @__PURE__ */ new Set();
|
|
189
|
+
for (const candidate of candidates) for (const key of candidate.covered) coveredByAll.add(key);
|
|
190
|
+
const overflowIfNoneDropped = buildOverflow(sections, coveredByAll);
|
|
191
|
+
const needsMore = countRows(overflowIfNoneDropped.flatMap((group) => group.items)) > 0 || extraMoreRows > 0 || candidates.length > maxTabs;
|
|
192
|
+
const limit = needsMore ? maxTabs - 1 : maxTabs;
|
|
193
|
+
const kept = candidates.slice(0, limit);
|
|
194
|
+
const dropped = candidates.slice(limit);
|
|
195
|
+
if (DEV && dropped.length > 0) {
|
|
196
|
+
console.warn(
|
|
197
|
+
`[basalt] MobileNav: ${candidates.length} slot candidates for ${limit} available slot(s) \u2014 the last ${dropped.length} moved into the More surface: ${dropped.map((candidate) => `"${candidate.key}"`).join(", ")}. Raise mobileNav.maxTabs or drop a mobile: 'tab'.`
|
|
198
|
+
);
|
|
199
|
+
}
|
|
200
|
+
const covered = /* @__PURE__ */ new Set();
|
|
201
|
+
for (const candidate of kept) for (const key of candidate.covered) covered.add(key);
|
|
202
|
+
const slots = [];
|
|
203
|
+
for (const candidate of kept) {
|
|
204
|
+
const slot = candidate.toSlot();
|
|
205
|
+
if (slot !== void 0) slots.push(slot);
|
|
206
|
+
}
|
|
207
|
+
if (!needsMore) return { slots };
|
|
208
|
+
const groups = buildOverflow(sections, covered);
|
|
209
|
+
const overflowItems = groups.flatMap((group) => group.items);
|
|
210
|
+
const rows = countRows(overflowItems) + extraMoreRows;
|
|
211
|
+
if (rows === 0) return { slots };
|
|
212
|
+
const label = config?.moreLabel ?? "More";
|
|
213
|
+
const only = overflowItems[0];
|
|
214
|
+
if (rows === 1 && extraMoreRows === 0 && only !== void 0 && !only.disabled) {
|
|
215
|
+
slots.push({
|
|
216
|
+
kind: "link",
|
|
217
|
+
key: only.key,
|
|
218
|
+
label: only.label,
|
|
219
|
+
short: only.short ?? only.label,
|
|
220
|
+
icon: only.icon,
|
|
221
|
+
active: hasActiveDestination(only),
|
|
222
|
+
item: only
|
|
223
|
+
});
|
|
224
|
+
return { slots };
|
|
225
|
+
}
|
|
226
|
+
slots.push({
|
|
227
|
+
kind: rows <= menuMax ? "menu" : "sheet",
|
|
228
|
+
key: MOBILE_MORE_KEY,
|
|
229
|
+
label,
|
|
230
|
+
short: label,
|
|
231
|
+
// No icon: the More glyph is chrome the renderer owns, and this module holds no JSX.
|
|
232
|
+
icon: void 0,
|
|
233
|
+
active: overflowItems.some(hasActiveDestination),
|
|
234
|
+
groups,
|
|
235
|
+
isMore: true
|
|
236
|
+
});
|
|
237
|
+
return { slots };
|
|
238
|
+
}
|
|
239
|
+
export {
|
|
240
|
+
MOBILE_MAX_TABS_DEFAULT,
|
|
241
|
+
MOBILE_MENU_MAX_DEFAULT,
|
|
242
|
+
MOBILE_MORE_KEY,
|
|
243
|
+
projectMobileNav
|
|
244
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mobile-nav-model.test.d.ts","sourceRoot":"","sources":["../../src/shell/mobile-nav-model.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sidebar nav count badge (docs/DESIGN-SPEC.md §5): mono 10.5px, ink-8% bg, radius 5, height 16,
|
|
3
|
+
* padding 0 5px, muted text; `marginLeft: auto` pins it to the row end on any render path.
|
|
4
|
+
* `styles` (inline) rather than a token color prop, since none of Mantine's variant/color
|
|
5
|
+
* combinations land on the ink-tint idiom. Returns `null` for a zero/empty count so the badge slot
|
|
6
|
+
* stays clean ("ink earns its color", DESIGN.md).
|
|
7
|
+
*/
|
|
8
|
+
export declare function NavCountBadge({ count }: {
|
|
9
|
+
count: number;
|
|
10
|
+
}): import("react").JSX.Element | null;
|
|
11
|
+
//# sourceMappingURL=nav-count-badge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nav-count-badge.d.ts","sourceRoot":"","sources":["../../src/shell/nav-count-badge.tsx"],"names":[],"mappings":"AASA;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,EAAE,KAAK,EAAE,EAAE;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,sCAsBzD"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Badge } from "@mantine/core";
|
|
3
|
+
import { VX } from "../tokens/index.js";
|
|
4
|
+
function NavCountBadge({ count }) {
|
|
5
|
+
if (!count) return null;
|
|
6
|
+
return /* @__PURE__ */ jsx(
|
|
7
|
+
Badge,
|
|
8
|
+
{
|
|
9
|
+
size: "sm",
|
|
10
|
+
styles: {
|
|
11
|
+
root: {
|
|
12
|
+
backgroundColor: "color-mix(in srgb, var(--vx-ink) 8%, transparent)",
|
|
13
|
+
color: "var(--vx-muted)",
|
|
14
|
+
fontFamily: "var(--basalt-font-mono)",
|
|
15
|
+
fontSize: VX.text.micro,
|
|
16
|
+
fontWeight: 500,
|
|
17
|
+
height: 16,
|
|
18
|
+
padding: "0 5px",
|
|
19
|
+
marginLeft: "auto",
|
|
20
|
+
borderRadius: "var(--vx-radius-tight)"
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
children: count
|
|
24
|
+
}
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
export {
|
|
28
|
+
NavCountBadge
|
|
29
|
+
};
|
package/dist/surfaces.d.ts
CHANGED
|
@@ -209,7 +209,7 @@ export declare const SURFACES: {
|
|
|
209
209
|
readonly rule: "router";
|
|
210
210
|
readonly skill: readonly ["basalt-app"];
|
|
211
211
|
readonly guardKinds: readonly [];
|
|
212
|
-
readonly description: "TanStack Router bridge: useBasaltNav (active route) + useRouterBreadcrumbs + createSearchParamStore (single-select URL-state store) + createMultiSearchParamStore (multi-select URL-state store)";
|
|
212
|
+
readonly description: "TanStack Router bridge: defineNav/navGroup/navTarget (one typed nav definition) + useNav (sections + mobileNav, spread onto BasaltShell) + useBasaltNav (active route) + useRouterBreadcrumbs + createSearchParamStore (single-select URL-state store) + createMultiSearchParamStore (multi-select URL-state store)";
|
|
213
213
|
readonly optionalPeers: readonly ["@tanstack/react-router"];
|
|
214
214
|
readonly globs: {
|
|
215
215
|
readonly shipped: readonly [];
|
package/dist/surfaces.js
CHANGED
|
@@ -120,7 +120,7 @@ const SURFACES = {
|
|
|
120
120
|
rule: "router",
|
|
121
121
|
skill: ["basalt-app"],
|
|
122
122
|
guardKinds: [],
|
|
123
|
-
description: "TanStack Router bridge: useBasaltNav (active route) + useRouterBreadcrumbs + createSearchParamStore (single-select URL-state store) + createMultiSearchParamStore (multi-select URL-state store)",
|
|
123
|
+
description: "TanStack Router bridge: defineNav/navGroup/navTarget (one typed nav definition) + useNav (sections + mobileNav, spread onto BasaltShell) + useBasaltNav (active route) + useRouterBreadcrumbs + createSearchParamStore (single-select URL-state store) + createMultiSearchParamStore (multi-select URL-state store)",
|
|
124
124
|
optionalPeers: ["@tanstack/react-router"],
|
|
125
125
|
globs: {
|
|
126
126
|
shipped: [],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/theme/index.ts"],"names":[],"mappings":"AA+DA,OAAO,KAAK,EACV,oBAAoB,EAGpB,oBAAoB,EAErB,MAAM,eAAe,CAAA;AAStB,OAAO,KAAK,EAAe,YAAY,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAE/E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAEpD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;AAOlD;;;;;GAKG;AACH,YAAY,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;AAIlD,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AASvD,OAAO,QAAQ,eAAe,CAAC;IAC7B,UAAU,iBAAiB;QACzB,YAAY,CAAC,EAAE,YAAY,CAAA;QAC3B,WAAW,CAAC,EAAE,iBAAiB,CAAA;QAC/B,YAAY,CAAC,EAAE,YAAY,CAAA;QAC3B,aAAa,CAAC,EAAE,WAAW,CAAA;KAC5B;CACF;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/theme/index.ts"],"names":[],"mappings":"AA+DA,OAAO,KAAK,EACV,oBAAoB,EAGpB,oBAAoB,EAErB,MAAM,eAAe,CAAA;AAStB,OAAO,KAAK,EAAe,YAAY,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAE/E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAEpD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;AAOlD;;;;;GAKG;AACH,YAAY,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;AAIlD,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AASvD,OAAO,QAAQ,eAAe,CAAC;IAC7B,UAAU,iBAAiB;QACzB,YAAY,CAAC,EAAE,YAAY,CAAA;QAC3B,WAAW,CAAC,EAAE,iBAAiB,CAAA;QAC/B,YAAY,CAAC,EAAE,YAAY,CAAA;QAC3B,aAAa,CAAC,EAAE,WAAW,CAAA;KAC5B;CACF;AAm5BD;+EAC+E;AAC/E,eAAO,MAAM,SAAS,EAAE,oBAAuD,CAAA;AAmJ/E;;8FAE8F;AAC9F,eAAO,MAAM,oBAAoB,EAAE,oBACc,CAAA;AAEjD,kEAAkE;AAClE,MAAM,MAAM,wBAAwB,GAAG;IACrC;;;;;;;;;;;OAWG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,CAAA;IAE9B;;;;;;;;;;;;;;;;OAgBG;IACH,KAAK,CAAC,EAAE,iBAAiB,CAAA;IAEzB;;;;;;;;;;;;;;;;OAgBG;IACH,MAAM,CAAC,EAAE,MAAM,CAAA;IAEf;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB,CAAA;AAYD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,iBAAiB,CAC/B,SAAS,CAAC,EAAE,oBAAoB,EAChC,OAAO,CAAC,EAAE,wBAAwB,GACjC,oBAAoB,CA+BtB"}
|
package/dist/theme/index.js
CHANGED
|
@@ -304,10 +304,10 @@ function buildTheme(data, options = {}) {
|
|
|
304
304
|
// panel-filled row read as a button sitting in the nav rather than as the current location.
|
|
305
305
|
// Selection is carried by the tint + ink text + weight 600 + the accent icon instead. Forced
|
|
306
306
|
// here at the THEME level via NavLink's `--nl-*` vars so it holds for every render path —
|
|
307
|
-
// including a consumer's router `<Link>`
|
|
308
|
-
// module; the active ICON is accent-colored via `nav-link.module.css`
|
|
309
|
-
// `[data-position='left']` leftSection, which the flat `vars`/`styles` API
|
|
310
|
-
// conditionally on `[data-active]`).
|
|
307
|
+
// including a consumer's router `<Link>` hosted through `SidebarItem.Anchor`, which never
|
|
308
|
+
// sees the shell CSS module; the active ICON is accent-colored via `nav-link.module.css`
|
|
309
|
+
// (targets the `[data-position='left']` leftSection, which the flat `vars`/`styles` API
|
|
310
|
+
// can't express conditionally on `[data-active]`).
|
|
311
311
|
//
|
|
312
312
|
// `--nl-hover` (ink-13%) only ever reaches an ACTIVE row in practice — the inactive hover is
|
|
313
313
|
// set at ink-6% by higher-specificity `:not([data-active])` rules in `nav-link.module.css` /
|
|
@@ -323,9 +323,10 @@ function buildTheme(data, options = {}) {
|
|
|
323
323
|
children: {}
|
|
324
324
|
}),
|
|
325
325
|
// Dense, rounded nav rows — applied at the THEME level so they survive EVERY render path,
|
|
326
|
-
// including a consumer's router `<Link>`
|
|
327
|
-
// module (the module's `.link` only reaches the shell's own fallback
|
|
328
|
-
// reasoning as the `--nl-*` fill above: layout is single-sourced here,
|
|
326
|
+
// including a consumer's router `<Link>` hosted through `SidebarItem.Anchor`, which never
|
|
327
|
+
// sees the shell CSS module (the module's `.link` only reaches the shell's own fallback
|
|
328
|
+
// `<NavLink>`). Same reasoning as the `--nl-*` fill above: layout is single-sourced here,
|
|
329
|
+
// not in two places.
|
|
329
330
|
// The active-weight/shadow/icon-accent state selectors can't live in `styles` (flat inline
|
|
330
331
|
// props only) — they're in nav-link.module.css, wired via `classNames` so they reach the
|
|
331
332
|
// same every-render-path scope.
|
|
@@ -5,7 +5,8 @@
|
|
|
5
5
|
* tint rather than as a button, so the row never competes with the real filled controls around it.
|
|
6
6
|
*
|
|
7
7
|
* Applied at the THEME level via `classNames` so it reaches EVERY NavLink render path — including a
|
|
8
|
-
* consumer's router `<Link>` mounted through `
|
|
8
|
+
* consumer's router `<Link>` mounted through `SidebarItem.Anchor`, which a shell-scoped CSS
|
|
9
|
+
* module never
|
|
9
10
|
* sees. Mantine's `styles` prop only takes flat inline properties (a nested `&[data-active]` there
|
|
10
11
|
* throws a React warning), so the state selectors live here. React Router's NavLink marks the
|
|
11
12
|
* active item via `aria-current` rather than the `active` prop's `data-active`, so both states are
|
|
@@ -42,7 +43,8 @@
|
|
|
42
43
|
|
|
43
44
|
/*
|
|
44
45
|
* Inactive hover — the ink-6% ghost tint + ink text/icon (docs/DESIGN-SPEC.md §5). Lives here (not
|
|
45
|
-
* only in the shell module) so a consumer's `
|
|
46
|
+
* only in the shell module) so a consumer's `SidebarItem.Anchor` path gets the same hover;
|
|
47
|
+
* Mantine's own
|
|
46
48
|
* hover fill uses `:where(scheme) .m_*:hover` (gray-0/dark-6), which this outranks on specificity.
|
|
47
49
|
* Active rows keep their panel fill + `--nl-hover` untouched.
|
|
48
50
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tokens/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAYH,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AAMvE,OAAO,EAAE,EAAE,EAAE,CAAC,EAAE,MAAM,WAAW,CAAA;AAOjC,OAAO,EAAE,qBAAqB,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAA;AACnF,YAAY,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AAM5D,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AACxC,YAAY,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAO7C,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAA;AACzC,YAAY,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AAE5C,wFAAwF;AACxF,MAAM,MAAM,SAAS,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAA;AAEvD,8FAA8F;AAC9F,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAA;AAEjD;;;;;;GAMG;AACH,eAAO,MAAM,KAAK,GAAI,OAAO,MAAM,EAAE,GAAG,MAAM,KAAG,MACoB,CAAA;AAsCrE,eAAO,MAAM,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyIL,CAAA;AAEV,kFAAkF;AAClF,MAAM,MAAM,WAAW,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAA;AAEtF;;;;;;;;;;;;;GAaG;AACH,wBAAgB,WAAW,CAAC,IAAI,CAAC,EAAE;IACjC,4DAA4D;IAC5D,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,IAAI,CAAC,EAAE,MAAM,CAAA;CACd,GAAG,WAAW,CAUd;AAOD;;;;;;;;GAQG;AACH,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAExC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tokens/index.ts"],"names":[],"mappings":"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"}
|
package/dist/tokens/index.js
CHANGED
|
@@ -357,6 +357,8 @@ function spaceDecls(space) {
|
|
|
357
357
|
decl("space-sidebar-child-row-indent", `${space.step.sidebarChildRowIndent}px`),
|
|
358
358
|
decl("space-app-header-mobile-actions-height", `${space.step.appHeaderMobileActionsHeight}px`),
|
|
359
359
|
decl("space-mobile-nav-tab-gap", `${space.step.mobileNavTabGap}px`),
|
|
360
|
+
decl("space-mobile-nav-icon-size", `${space.step.mobileNavIconSize}px`),
|
|
361
|
+
decl("space-mobile-nav-row-height", `${space.step.mobileNavRowHeight}px`),
|
|
360
362
|
decl("space-agent-rail-inset-x", `${space.step.agentRailInsetX}px`),
|
|
361
363
|
decl("space-agent-part-gap-top", `${space.step.agentPartGapTop}px`),
|
|
362
364
|
decl("space-agent-code-inset", `${space.step.agentCodeInset}px`),
|