@kopexa/sidebar 17.2.0 → 17.3.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/dist/chunk-5VE25P3M.mjs +369 -0
- package/dist/{chunk-WA2NSEYE.mjs → chunk-6H2EH7LL.mjs} +3 -3
- package/dist/chunk-BFZFZSUC.mjs +27 -0
- package/dist/{chunk-CMYTESJM.mjs → chunk-G2J7EJQ6.mjs} +33 -26
- package/dist/{chunk-PZFEB2PM.mjs → chunk-WIP5GNGJ.mjs} +9 -15
- package/dist/{chunk-3L2F566G.mjs → chunk-XBTONQ3L.mjs} +9 -1
- package/dist/index.js +170 -250
- package/dist/index.mjs +6 -6
- package/dist/v2/app-shell.js +9 -14
- package/dist/v2/app-shell.mjs +3 -2
- package/dist/v2/components.d.mts +7 -1
- package/dist/v2/components.d.ts +7 -1
- package/dist/v2/components.js +128 -208
- package/dist/v2/components.mjs +3 -3
- package/dist/v2/context.d.mts +3 -0
- package/dist/v2/context.d.ts +3 -0
- package/dist/v2/context.js +20 -1
- package/dist/v2/context.mjs +2 -1
- package/dist/v2/from-config.js +151 -219
- package/dist/v2/from-config.mjs +4 -4
- package/dist/v2/index.d.mts +1 -0
- package/dist/v2/index.d.ts +1 -0
- package/dist/v2/index.js +170 -250
- package/dist/v2/index.mjs +6 -6
- package/dist/v2/types.d.mts +20 -1
- package/dist/v2/types.d.ts +20 -1
- package/dist/v2/types.js +17 -2
- package/dist/v2/types.mjs +7 -3
- package/package.json +11 -11
- package/dist/chunk-EIXUCY5M.mjs +0 -458
- package/dist/chunk-SDMGFB6V.mjs +0 -14
package/dist/v2/components.js
CHANGED
|
@@ -39,23 +39,29 @@ module.exports = __toCommonJS(components_exports);
|
|
|
39
39
|
var import_button = require("@kopexa/button");
|
|
40
40
|
var import_icons = require("@kopexa/icons");
|
|
41
41
|
var import_shared_utils = require("@kopexa/shared-utils");
|
|
42
|
-
var
|
|
42
|
+
var import_theme2 = require("@kopexa/theme");
|
|
43
43
|
var import_tooltip2 = require("@kopexa/tooltip");
|
|
44
44
|
var import_react2 = require("react");
|
|
45
45
|
|
|
46
46
|
// src/v2/context.tsx
|
|
47
47
|
var import_react_utils = require("@kopexa/react-utils");
|
|
48
|
+
var import_theme = require("@kopexa/theme");
|
|
48
49
|
var import_tooltip = require("@kopexa/tooltip");
|
|
49
50
|
var import_use_is_mobile = require("@kopexa/use-is-mobile");
|
|
50
51
|
var import_react = require("react");
|
|
51
|
-
var import_jsx_runtime = require("react/jsx-runtime");
|
|
52
|
-
var PIN_COOKIE_MAX_AGE = 60 * 60 * 24 * 7;
|
|
53
|
-
var [Provider, useSidebarV2] = (0, import_react_utils.createContext)({
|
|
54
|
-
name: "SidebarV2Context",
|
|
55
|
-
errorMessage: "useSidebarV2 must be used within <SidebarV2> (the provider component)."
|
|
56
|
-
});
|
|
57
52
|
|
|
58
53
|
// src/v2/types.ts
|
|
54
|
+
function normalizePath(href) {
|
|
55
|
+
const path = href.split("#")[0].split("?")[0].replace(/\/+$/, "");
|
|
56
|
+
return path === "" ? "/" : path;
|
|
57
|
+
}
|
|
58
|
+
function pathMatchLength(currentPath, href) {
|
|
59
|
+
const target = normalizePath(href);
|
|
60
|
+
if (currentPath === target) return target.length;
|
|
61
|
+
if (target !== "/" && currentPath.startsWith(`${target}/`))
|
|
62
|
+
return target.length;
|
|
63
|
+
return -1;
|
|
64
|
+
}
|
|
59
65
|
function panelItemHasChildren(item) {
|
|
60
66
|
return "children" in item && Array.isArray(item.children);
|
|
61
67
|
}
|
|
@@ -63,43 +69,37 @@ function panelItemIsSection(item) {
|
|
|
63
69
|
return "section" in item;
|
|
64
70
|
}
|
|
65
71
|
|
|
72
|
+
// src/v2/context.tsx
|
|
73
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
74
|
+
var PIN_COOKIE_MAX_AGE = 60 * 60 * 24 * 7;
|
|
75
|
+
var [Provider, useSidebarV2] = (0, import_react_utils.createContext)({
|
|
76
|
+
name: "SidebarV2Context",
|
|
77
|
+
errorMessage: "useSidebarV2 must be used within <SidebarV2> (the provider component)."
|
|
78
|
+
});
|
|
79
|
+
|
|
66
80
|
// src/v2/components.tsx
|
|
67
81
|
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
68
82
|
function SidebarV2Inset({
|
|
69
83
|
className,
|
|
70
84
|
...props
|
|
71
85
|
}) {
|
|
72
|
-
const {
|
|
86
|
+
const { styles } = useSidebarV2();
|
|
73
87
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
74
88
|
"main",
|
|
75
89
|
{
|
|
76
90
|
"data-slot": "sidebar-v2-inset",
|
|
77
|
-
className: (
|
|
78
|
-
"relative flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden bg-background",
|
|
79
|
-
"md:m-2 md:rounded-xl md:shadow-sm",
|
|
80
|
-
// On a light surround the white card needs a hairline to define its
|
|
81
|
-
// edge; on the dark surround a border would read as a seam.
|
|
82
|
-
tone === "light" && "md:border md:border-border/70",
|
|
83
|
-
className
|
|
84
|
-
),
|
|
91
|
+
className: styles.inset({ className }),
|
|
85
92
|
...props
|
|
86
93
|
}
|
|
87
94
|
);
|
|
88
95
|
}
|
|
89
96
|
function SidebarV2Rail({ className, ...props }) {
|
|
90
|
-
const {
|
|
91
|
-
const light = tone === "light";
|
|
97
|
+
const { styles } = useSidebarV2();
|
|
92
98
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
93
99
|
"nav",
|
|
94
100
|
{
|
|
95
101
|
"data-slot": "sidebar-v2-rail",
|
|
96
|
-
className: (
|
|
97
|
-
"flex w-(--kpx-rail-width) shrink-0 flex-col overflow-hidden bg-sidebar py-2 text-sidebar-foreground",
|
|
98
|
-
// Light tone: the dark rail floats as a rounded card on the light
|
|
99
|
-
// surround. Dark tone: full-height, flush to the edge.
|
|
100
|
-
light ? "m-2 rounded-2xl shadow-sm" : "h-full",
|
|
101
|
-
className
|
|
102
|
-
),
|
|
102
|
+
className: styles.rail({ className }),
|
|
103
103
|
...props
|
|
104
104
|
}
|
|
105
105
|
);
|
|
@@ -108,6 +108,7 @@ function SidebarV2RailSpacer() {
|
|
|
108
108
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { "aria-hidden": true, className: "flex-1" });
|
|
109
109
|
}
|
|
110
110
|
var SidebarV2Workspace = (0, import_react2.forwardRef)(({ name, role, logo, className, appearance = "rail", ...props }, ref) => {
|
|
111
|
+
const { styles } = useSidebarV2();
|
|
111
112
|
if (appearance === "bar") {
|
|
112
113
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
113
114
|
"button",
|
|
@@ -116,19 +117,15 @@ var SidebarV2Workspace = (0, import_react2.forwardRef)(({ name, role, logo, clas
|
|
|
116
117
|
type: "button",
|
|
117
118
|
"data-slot": "sidebar-v2-workspace",
|
|
118
119
|
"aria-label": role ? `${name} \u2013 ${role}` : name,
|
|
119
|
-
className: (
|
|
120
|
-
"group/ws flex cursor-pointer items-center gap-2 rounded-lg py-1 pr-2 pl-1",
|
|
121
|
-
"outline-hidden ring-ring transition-colors hover:bg-foreground/5 focus-visible:ring-2",
|
|
122
|
-
className
|
|
123
|
-
),
|
|
120
|
+
className: styles.workspaceBar({ className }),
|
|
124
121
|
...props,
|
|
125
122
|
children: [
|
|
126
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className:
|
|
127
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className:
|
|
128
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className:
|
|
129
|
-
role && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className:
|
|
123
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: styles.workspaceBarLogo(), children: logo != null ? logo : name.charAt(0).toUpperCase() }),
|
|
124
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: styles.workspaceBarText(), children: [
|
|
125
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: styles.workspaceBarName(), children: name }),
|
|
126
|
+
role && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: styles.workspaceBarRole(), children: role })
|
|
130
127
|
] }),
|
|
131
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_icons.ChevronDownIcon, { className:
|
|
128
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_icons.ChevronDownIcon, { className: styles.workspaceBarChevron() })
|
|
132
129
|
]
|
|
133
130
|
}
|
|
134
131
|
);
|
|
@@ -140,48 +137,25 @@ var SidebarV2Workspace = (0, import_react2.forwardRef)(({ name, role, logo, clas
|
|
|
140
137
|
type: "button",
|
|
141
138
|
"data-slot": "sidebar-v2-workspace",
|
|
142
139
|
"aria-label": role ? `${name} \u2013 ${role}` : name,
|
|
143
|
-
className: (
|
|
144
|
-
"group/ws relative mx-auto mt-1 flex cursor-pointer items-center justify-center rounded-lg p-1",
|
|
145
|
-
"outline-hidden ring-sidebar-ring transition-colors",
|
|
146
|
-
"hover:bg-sidebar-accent focus-visible:ring-2",
|
|
147
|
-
className
|
|
148
|
-
),
|
|
140
|
+
className: styles.workspaceRail({ className }),
|
|
149
141
|
...props,
|
|
150
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className:
|
|
142
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: styles.workspaceRailLogo(), children: [
|
|
151
143
|
logo != null ? logo : name.charAt(0).toUpperCase(),
|
|
152
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_icons.ChevronDownIcon, { className:
|
|
144
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_icons.ChevronDownIcon, { className: styles.workspaceRailChevron() })
|
|
153
145
|
] })
|
|
154
146
|
}
|
|
155
147
|
);
|
|
156
148
|
});
|
|
157
149
|
SidebarV2Workspace.displayName = "SidebarV2Workspace";
|
|
158
|
-
function railButtonClasses(active) {
|
|
159
|
-
return (0, import_shared_utils.cn)(
|
|
160
|
-
"group/rail relative mx-auto flex size-11 shrink-0 cursor-pointer items-center justify-center rounded-xl",
|
|
161
|
-
"outline-hidden ring-sidebar-ring transition-colors",
|
|
162
|
-
"text-sidebar-foreground/85 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground",
|
|
163
|
-
"focus-visible:ring-2",
|
|
164
|
-
active && "bg-sidebar-accent text-sidebar-accent-foreground"
|
|
165
|
-
);
|
|
166
|
-
}
|
|
167
150
|
function RailInner({
|
|
168
151
|
icon: Icon,
|
|
169
|
-
active,
|
|
170
152
|
badge
|
|
171
153
|
}) {
|
|
154
|
+
const { styles } = useSidebarV2();
|
|
172
155
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
|
|
173
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
"aria-hidden": true,
|
|
177
|
-
className: (0, import_shared_utils.cn)(
|
|
178
|
-
"absolute top-1/2 left-0 h-5 w-0.5 -translate-x-[0.6rem] -translate-y-1/2 rounded-r bg-primary transition-opacity",
|
|
179
|
-
active ? "opacity-100" : "opacity-0"
|
|
180
|
-
)
|
|
181
|
-
}
|
|
182
|
-
),
|
|
183
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Icon, { className: "size-5 shrink-0" }),
|
|
184
|
-
badge != null && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "absolute -top-0.5 -right-0.5 flex h-4 min-w-4 items-center justify-center rounded-full bg-primary px-1 text-[0.5625rem] font-semibold text-primary-foreground", children: badge })
|
|
156
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { "aria-hidden": true, className: styles.railIndicator() }),
|
|
157
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Icon, { className: styles.railIcon() }),
|
|
158
|
+
badge != null && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: styles.railBadge(), children: badge })
|
|
185
159
|
] });
|
|
186
160
|
}
|
|
187
161
|
function SidebarV2RailLink({
|
|
@@ -190,18 +164,18 @@ function SidebarV2RailLink({
|
|
|
190
164
|
href,
|
|
191
165
|
badge
|
|
192
166
|
}) {
|
|
193
|
-
const { renderLink, isActive, resetPanelSelection } = useSidebarV2();
|
|
167
|
+
const { renderLink, isActive, resetPanelSelection, styles } = useSidebarV2();
|
|
194
168
|
const active = isActive(href);
|
|
195
169
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_tooltip2.Tooltip, { content: label, side: "right", children: renderLink({
|
|
196
170
|
href,
|
|
197
|
-
className:
|
|
171
|
+
className: styles.railButton(),
|
|
198
172
|
"data-active": active,
|
|
199
173
|
"aria-current": active ? "page" : void 0,
|
|
200
174
|
"aria-label": label,
|
|
201
175
|
// Navigating to a destination link clears any open panel preview,
|
|
202
176
|
// even when the route doesn't change (e.g. already on it).
|
|
203
177
|
onClick: resetPanelSelection,
|
|
204
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(RailInner, { icon,
|
|
178
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(RailInner, { icon, badge })
|
|
205
179
|
}) });
|
|
206
180
|
}
|
|
207
181
|
function SidebarV2RailItem({
|
|
@@ -214,6 +188,7 @@ function SidebarV2RailItem({
|
|
|
214
188
|
onMouseLeave,
|
|
215
189
|
badge
|
|
216
190
|
}) {
|
|
191
|
+
const { styles } = useSidebarV2();
|
|
217
192
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_tooltip2.Tooltip, { content: label, side: "right", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
218
193
|
"button",
|
|
219
194
|
{
|
|
@@ -224,8 +199,8 @@ function SidebarV2RailItem({
|
|
|
224
199
|
onClick,
|
|
225
200
|
onMouseEnter,
|
|
226
201
|
onMouseLeave,
|
|
227
|
-
className:
|
|
228
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(RailInner, { icon,
|
|
202
|
+
className: styles.railButton(),
|
|
203
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(RailInner, { icon, badge })
|
|
229
204
|
}
|
|
230
205
|
) });
|
|
231
206
|
}
|
|
@@ -238,54 +213,18 @@ function SidebarV2Panel({
|
|
|
238
213
|
children,
|
|
239
214
|
className
|
|
240
215
|
}) {
|
|
241
|
-
const { togglePin, pinned,
|
|
242
|
-
const light = tone === "light";
|
|
216
|
+
const { togglePin, pinned, styles } = useSidebarV2();
|
|
243
217
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
244
218
|
"div",
|
|
245
219
|
{
|
|
246
220
|
"data-slot": "sidebar-v2-panel",
|
|
247
|
-
"data-floating": floating,
|
|
248
|
-
className: (
|
|
249
|
-
"flex h-full w-(--kpx-panel-width) shrink-0 flex-col",
|
|
250
|
-
// Surface. The flyout is a distinct floating card (white on light),
|
|
251
|
-
// so it reads as an overlay rather than a flat full-height slab.
|
|
252
|
-
floating ? light ? "bg-background text-foreground" : "bg-sidebar text-sidebar-foreground" : light ? "bg-muted text-foreground" : "bg-sidebar text-sidebar-foreground",
|
|
253
|
-
floating ? (
|
|
254
|
-
// Floating card: rounded, soft layered shadow, hairline ring.
|
|
255
|
-
(0, import_shared_utils.cn)(
|
|
256
|
-
"overflow-hidden rounded-2xl shadow-2xl shadow-black/20 ring-1",
|
|
257
|
-
light ? "ring-black/5" : "ring-white/10"
|
|
258
|
-
)
|
|
259
|
-
) : (
|
|
260
|
-
// Pinned: light blends into the surround (no border); dark keeps a
|
|
261
|
-
// hairline against the rail.
|
|
262
|
-
light ? "" : "border-l border-sidebar-border/40"
|
|
263
|
-
),
|
|
264
|
-
className
|
|
265
|
-
),
|
|
221
|
+
"data-floating": floating ? "true" : "false",
|
|
222
|
+
className: styles.panel({ className }),
|
|
266
223
|
children: [
|
|
267
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className:
|
|
224
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: styles.panelHeader(), children: [
|
|
268
225
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "min-w-0 flex-1", children: [
|
|
269
|
-
title && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
270
|
-
|
|
271
|
-
{
|
|
272
|
-
className: (0, import_shared_utils.cn)(
|
|
273
|
-
"truncate text-sm font-semibold",
|
|
274
|
-
light ? "text-foreground" : "text-sidebar-foreground"
|
|
275
|
-
),
|
|
276
|
-
children: title
|
|
277
|
-
}
|
|
278
|
-
),
|
|
279
|
-
subtitle && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
280
|
-
"div",
|
|
281
|
-
{
|
|
282
|
-
className: (0, import_shared_utils.cn)(
|
|
283
|
-
"truncate text-xs",
|
|
284
|
-
light ? "text-muted-foreground" : "text-sidebar-foreground/70"
|
|
285
|
-
),
|
|
286
|
-
children: subtitle
|
|
287
|
-
}
|
|
288
|
-
)
|
|
226
|
+
title && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: styles.panelTitle(), children: title }),
|
|
227
|
+
subtitle && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: styles.panelSubtitle(), children: subtitle })
|
|
289
228
|
] }),
|
|
290
229
|
action != null ? action : !hidePin && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
291
230
|
import_tooltip2.Tooltip,
|
|
@@ -299,41 +238,28 @@ function SidebarV2Panel({
|
|
|
299
238
|
size: "sm",
|
|
300
239
|
"aria-label": pinned ? "Panel l\xF6sen" : "Panel anheften",
|
|
301
240
|
onClick: togglePin,
|
|
302
|
-
className: (
|
|
303
|
-
"-mr-1 shrink-0",
|
|
304
|
-
light ? "text-muted-foreground hover:bg-foreground/5 hover:text-foreground" : "text-sidebar-foreground/60 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground"
|
|
305
|
-
),
|
|
241
|
+
className: styles.panelPin(),
|
|
306
242
|
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_icons.PanelLeftIcon, { className: "size-4" })
|
|
307
243
|
}
|
|
308
244
|
)
|
|
309
245
|
}
|
|
310
246
|
)
|
|
311
247
|
] }),
|
|
312
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className:
|
|
248
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: styles.panelBody(), children })
|
|
313
249
|
]
|
|
314
250
|
}
|
|
315
251
|
);
|
|
316
252
|
}
|
|
317
|
-
function panelRowLight(active) {
|
|
318
|
-
return (0, import_shared_utils.cn)(
|
|
319
|
-
"flex h-8 w-full items-center gap-2.5 rounded-md px-2 text-sm outline-hidden ring-ring transition-colors focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0",
|
|
320
|
-
active ? "bg-primary/10 font-medium text-primary" : "text-foreground/80 hover:bg-foreground/5"
|
|
321
|
-
);
|
|
322
|
-
}
|
|
323
253
|
function SidebarV2PanelLabel({
|
|
324
254
|
className,
|
|
325
255
|
...props
|
|
326
256
|
}) {
|
|
327
|
-
const {
|
|
257
|
+
const { styles } = useSidebarV2();
|
|
328
258
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
329
259
|
"div",
|
|
330
260
|
{
|
|
331
261
|
"data-slot": "sidebar-v2-panel-label",
|
|
332
|
-
className: (
|
|
333
|
-
"px-2 pt-3 pb-1 text-[0.6875rem] font-medium uppercase tracking-wide",
|
|
334
|
-
tone === "light" ? "text-muted-foreground" : "text-sidebar-foreground/50",
|
|
335
|
-
className
|
|
336
|
-
),
|
|
262
|
+
className: styles.panelLabel({ className }),
|
|
337
263
|
...props
|
|
338
264
|
}
|
|
339
265
|
);
|
|
@@ -342,7 +268,7 @@ function SidebarV2PanelLeaf({
|
|
|
342
268
|
item,
|
|
343
269
|
active: activeProp
|
|
344
270
|
}) {
|
|
345
|
-
const { renderLink, isActive, tone } = useSidebarV2();
|
|
271
|
+
const { renderLink, isActive, tone, styles } = useSidebarV2();
|
|
346
272
|
const light = tone === "light";
|
|
347
273
|
const Icon = item.icon;
|
|
348
274
|
const active = activeProp != null ? activeProp : isActive(item.href);
|
|
@@ -350,51 +276,40 @@ function SidebarV2PanelLeaf({
|
|
|
350
276
|
href: item.href,
|
|
351
277
|
"data-active": active,
|
|
352
278
|
"aria-current": active ? "page" : void 0,
|
|
353
|
-
|
|
279
|
+
// Light tone uses the recipe's leaf slot (group/leaf + data-active);
|
|
280
|
+
// dark tone reuses the existing sidebarMenuButton recipe.
|
|
281
|
+
className: light ? styles.panelLeaf() : (0, import_theme2.sidebarMenuButton)({ size: "md" }),
|
|
354
282
|
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
|
|
355
|
-
Icon && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
light ? active ? void 0 : "text-muted-foreground" : "text-sidebar-foreground/75"
|
|
360
|
-
)
|
|
361
|
-
}
|
|
362
|
-
),
|
|
363
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "min-w-0 flex-1 truncate", children: item.label }),
|
|
364
|
-
item.badge != null && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
365
|
-
"span",
|
|
366
|
-
{
|
|
367
|
-
className: (0, import_shared_utils.cn)(
|
|
368
|
-
"ml-auto rounded-full px-1.5 text-[0.625rem] font-medium",
|
|
369
|
-
light ? "bg-foreground/10 text-foreground/70" : "bg-sidebar-accent text-sidebar-accent-foreground"
|
|
370
|
-
),
|
|
371
|
-
children: item.badge
|
|
372
|
-
}
|
|
373
|
-
)
|
|
283
|
+
Icon && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Icon, { className: styles.panelLeafIcon() }),
|
|
284
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: styles.panelLeafLabel(), children: item.label }),
|
|
285
|
+
item.tag && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: styles.panelLeafTag(), children: item.tag }),
|
|
286
|
+
item.badge != null && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: styles.panelLeafBadge(), children: item.badge })
|
|
374
287
|
] })
|
|
375
288
|
}) });
|
|
376
289
|
}
|
|
377
290
|
function SidebarV2PanelGroup({
|
|
378
|
-
item
|
|
291
|
+
item,
|
|
292
|
+
winningHref
|
|
379
293
|
}) {
|
|
380
294
|
var _a;
|
|
381
|
-
const { openGroup, toggleGroup, activeHref, renderLink, tone } = useSidebarV2();
|
|
295
|
+
const { openGroup, toggleGroup, activeHref, renderLink, tone, styles } = useSidebarV2();
|
|
382
296
|
const light = tone === "light";
|
|
383
297
|
const Icon = item.icon;
|
|
384
298
|
const key = (_a = item.value) != null ? _a : item.label;
|
|
385
|
-
let
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
299
|
+
let winner = winningHref;
|
|
300
|
+
if (winner === void 0) {
|
|
301
|
+
const current = normalizePath(activeHref);
|
|
302
|
+
let len = -1;
|
|
303
|
+
winner = null;
|
|
304
|
+
for (const c of item.children) {
|
|
305
|
+
const l = pathMatchLength(current, c.href);
|
|
306
|
+
if (l > len) {
|
|
307
|
+
len = l;
|
|
308
|
+
winner = normalizePath(c.href);
|
|
309
|
+
}
|
|
395
310
|
}
|
|
396
311
|
}
|
|
397
|
-
const containsActive =
|
|
312
|
+
const containsActive = winner != null && item.children.some((c) => normalizePath(c.href) === winner);
|
|
398
313
|
const open = openGroup === key || openGroup === null && containsActive;
|
|
399
314
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
|
|
400
315
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
@@ -402,71 +317,76 @@ function SidebarV2PanelGroup({
|
|
|
402
317
|
{
|
|
403
318
|
type: "button",
|
|
404
319
|
"data-state": open ? "open" : "closed",
|
|
320
|
+
"data-contains-active": containsActive,
|
|
405
321
|
"aria-expanded": open,
|
|
406
322
|
onClick: () => toggleGroup(key),
|
|
407
323
|
className: (0, import_shared_utils.cn)(
|
|
408
|
-
light ?
|
|
409
|
-
|
|
410
|
-
containsActive && (light ? "font-medium text-foreground" : "font-medium")
|
|
324
|
+
light ? styles.panelLeaf() : (0, import_theme2.sidebarMenuButton)({ size: "md" }),
|
|
325
|
+
styles.panelGroupButton()
|
|
411
326
|
),
|
|
412
327
|
children: [
|
|
413
|
-
Icon && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
className: light ? "text-muted-foreground" : "text-sidebar-foreground/75"
|
|
417
|
-
}
|
|
418
|
-
),
|
|
419
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "min-w-0 flex-1 truncate text-left", children: item.label }),
|
|
420
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
421
|
-
import_icons.ChevronRightIcon,
|
|
422
|
-
{
|
|
423
|
-
className: (0, import_shared_utils.cn)(
|
|
424
|
-
"size-3.5! shrink-0 transition-transform",
|
|
425
|
-
light ? "text-muted-foreground" : "text-sidebar-foreground/60",
|
|
426
|
-
open && "rotate-90"
|
|
427
|
-
)
|
|
428
|
-
}
|
|
429
|
-
)
|
|
328
|
+
Icon && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Icon, { className: styles.panelGroupIcon() }),
|
|
329
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: styles.panelGroupLabel(), children: item.label }),
|
|
330
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_icons.ChevronRightIcon, { className: styles.panelGroupChevron() })
|
|
430
331
|
]
|
|
431
332
|
}
|
|
432
333
|
),
|
|
433
|
-
open && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
434
|
-
|
|
435
|
-
{
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
),
|
|
440
|
-
children:
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
href: child.href,
|
|
444
|
-
"data-active": active,
|
|
445
|
-
"aria-current": active ? "page" : void 0,
|
|
446
|
-
className: (0, import_shared_utils.cn)(
|
|
447
|
-
"relative block rounded-md px-2 py-1.5 text-[0.8125rem] outline-hidden transition-colors focus-visible:ring-2",
|
|
448
|
-
"before:absolute before:top-1/2 before:-left-3 before:h-px before:w-2.5",
|
|
449
|
-
light ? active ? "bg-primary/10 font-medium text-primary ring-ring before:bg-primary" : "text-muted-foreground ring-ring hover:bg-foreground/5 hover:text-foreground before:bg-border" : active ? "bg-sidebar-accent font-medium text-sidebar-accent-foreground ring-sidebar-ring before:bg-primary" : "text-sidebar-foreground/80 ring-sidebar-ring hover:bg-sidebar-accent/60 hover:text-sidebar-accent-foreground before:bg-sidebar-foreground/30"
|
|
450
|
-
),
|
|
451
|
-
children: child.label
|
|
452
|
-
}) }, child.href);
|
|
453
|
-
})
|
|
454
|
-
}
|
|
455
|
-
)
|
|
334
|
+
open && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: styles.panelTree(), children: item.children.map((child) => {
|
|
335
|
+
const active = normalizePath(child.href) === winner;
|
|
336
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: renderLink({
|
|
337
|
+
href: child.href,
|
|
338
|
+
"data-active": active,
|
|
339
|
+
"aria-current": active ? "page" : void 0,
|
|
340
|
+
className: styles.subItem(),
|
|
341
|
+
children: child.label
|
|
342
|
+
}) }, child.href);
|
|
343
|
+
}) })
|
|
456
344
|
] });
|
|
457
345
|
}
|
|
458
346
|
function SidebarV2PanelItems({
|
|
459
347
|
items
|
|
460
348
|
}) {
|
|
349
|
+
const { activeHref } = useSidebarV2();
|
|
350
|
+
const winningHref = (0, import_react2.useMemo)(() => {
|
|
351
|
+
const current = normalizePath(activeHref);
|
|
352
|
+
let href = null;
|
|
353
|
+
let len = -1;
|
|
354
|
+
for (const item of items) {
|
|
355
|
+
if (panelItemIsSection(item)) continue;
|
|
356
|
+
const hrefs = panelItemHasChildren(item) ? item.children.map((c) => c.href) : [item.href];
|
|
357
|
+
for (const h of hrefs) {
|
|
358
|
+
const l = pathMatchLength(current, h);
|
|
359
|
+
if (l > len) {
|
|
360
|
+
len = l;
|
|
361
|
+
href = normalizePath(h);
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
return href;
|
|
366
|
+
}, [items, activeHref]);
|
|
461
367
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children: items.map((item, idx) => {
|
|
462
368
|
var _a;
|
|
463
369
|
if (panelItemIsSection(item)) {
|
|
464
370
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(SidebarV2PanelLabel, { children: item.section }, `section-${item.section}-${idx}`);
|
|
465
371
|
}
|
|
466
372
|
if (panelItemHasChildren(item)) {
|
|
467
|
-
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
373
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
374
|
+
SidebarV2PanelGroup,
|
|
375
|
+
{
|
|
376
|
+
item,
|
|
377
|
+
winningHref
|
|
378
|
+
},
|
|
379
|
+
(_a = item.value) != null ? _a : item.label
|
|
380
|
+
);
|
|
468
381
|
}
|
|
469
|
-
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
382
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
383
|
+
SidebarV2PanelLeaf,
|
|
384
|
+
{
|
|
385
|
+
item,
|
|
386
|
+
active: winningHref != null && normalizePath(item.href) === winningHref
|
|
387
|
+
},
|
|
388
|
+
item.href
|
|
389
|
+
);
|
|
470
390
|
}) });
|
|
471
391
|
}
|
|
472
392
|
function SidebarV2Trigger({
|
package/dist/v2/components.mjs
CHANGED
|
@@ -13,9 +13,9 @@ import {
|
|
|
13
13
|
SidebarV2RailSpacer,
|
|
14
14
|
SidebarV2Trigger,
|
|
15
15
|
SidebarV2Workspace
|
|
16
|
-
} from "../chunk-
|
|
17
|
-
import "../chunk-
|
|
18
|
-
import "../chunk-
|
|
16
|
+
} from "../chunk-5VE25P3M.mjs";
|
|
17
|
+
import "../chunk-XBTONQ3L.mjs";
|
|
18
|
+
import "../chunk-BFZFZSUC.mjs";
|
|
19
19
|
export {
|
|
20
20
|
SidebarV2Inset,
|
|
21
21
|
SidebarV2Panel,
|
package/dist/v2/context.d.mts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { sidebarV2 } from '@kopexa/theme';
|
|
2
3
|
import { ReactNode } from 'react';
|
|
3
4
|
import { SidebarV2LinkProps } from './types.mjs';
|
|
4
5
|
|
|
@@ -13,6 +14,8 @@ type SidebarV2FlyoutTrigger = "click" | "hover";
|
|
|
13
14
|
type SidebarV2ContextValue = {
|
|
14
15
|
/** Visual tone of the panel + surround. */
|
|
15
16
|
tone: SidebarV2Tone;
|
|
17
|
+
/** Resolved tailwind-variants styles (from @kopexa/theme) for the tone. */
|
|
18
|
+
styles: ReturnType<typeof sidebarV2>;
|
|
16
19
|
/** Pinned = persistent two-column. Unpinned = rail only + flyout panel. */
|
|
17
20
|
pinned: boolean;
|
|
18
21
|
togglePin: () => void;
|
package/dist/v2/context.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { sidebarV2 } from '@kopexa/theme';
|
|
2
3
|
import { ReactNode } from 'react';
|
|
3
4
|
import { SidebarV2LinkProps } from './types.js';
|
|
4
5
|
|
|
@@ -13,6 +14,8 @@ type SidebarV2FlyoutTrigger = "click" | "hover";
|
|
|
13
14
|
type SidebarV2ContextValue = {
|
|
14
15
|
/** Visual tone of the panel + surround. */
|
|
15
16
|
tone: SidebarV2Tone;
|
|
17
|
+
/** Resolved tailwind-variants styles (from @kopexa/theme) for the tone. */
|
|
18
|
+
styles: ReturnType<typeof sidebarV2>;
|
|
16
19
|
/** Pinned = persistent two-column. Unpinned = rail only + flyout panel. */
|
|
17
20
|
pinned: boolean;
|
|
18
21
|
togglePin: () => void;
|
package/dist/v2/context.js
CHANGED
|
@@ -27,9 +27,25 @@ __export(context_exports, {
|
|
|
27
27
|
});
|
|
28
28
|
module.exports = __toCommonJS(context_exports);
|
|
29
29
|
var import_react_utils = require("@kopexa/react-utils");
|
|
30
|
+
var import_theme = require("@kopexa/theme");
|
|
30
31
|
var import_tooltip = require("@kopexa/tooltip");
|
|
31
32
|
var import_use_is_mobile = require("@kopexa/use-is-mobile");
|
|
32
33
|
var import_react = require("react");
|
|
34
|
+
|
|
35
|
+
// src/v2/types.ts
|
|
36
|
+
function normalizePath(href) {
|
|
37
|
+
const path = href.split("#")[0].split("?")[0].replace(/\/+$/, "");
|
|
38
|
+
return path === "" ? "/" : path;
|
|
39
|
+
}
|
|
40
|
+
function pathMatchLength(currentPath, href) {
|
|
41
|
+
const target = normalizePath(href);
|
|
42
|
+
if (currentPath === target) return target.length;
|
|
43
|
+
if (target !== "/" && currentPath.startsWith(`${target}/`))
|
|
44
|
+
return target.length;
|
|
45
|
+
return -1;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// src/v2/context.tsx
|
|
33
49
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
34
50
|
var PIN_COOKIE = "kpx_sidebar_v2_pinned";
|
|
35
51
|
var PIN_COOKIE_MAX_AGE = 60 * 60 * 24 * 7;
|
|
@@ -66,6 +82,7 @@ function SidebarV2Provider({
|
|
|
66
82
|
}, []);
|
|
67
83
|
const panelOverrideActive = overrideCount > 0;
|
|
68
84
|
const navPreviewActive = pinned ? selectedRail !== null : flyoutValue !== null;
|
|
85
|
+
const styles = (0, import_react.useMemo)(() => (0, import_theme.sidebarV2)({ tone }), [tone]);
|
|
69
86
|
const setPinned = (0, import_react.useCallback)(
|
|
70
87
|
(value2) => {
|
|
71
88
|
onPinnedChange == null ? void 0 : onPinnedChange(value2);
|
|
@@ -95,12 +112,13 @@ function SidebarV2Provider({
|
|
|
95
112
|
setOpenGroup((curr) => curr === key ? null : key);
|
|
96
113
|
}, []);
|
|
97
114
|
const isActive = (0, import_react.useCallback)(
|
|
98
|
-
(href) => activeHref
|
|
115
|
+
(href) => pathMatchLength(normalizePath(activeHref), href) >= 0,
|
|
99
116
|
[activeHref]
|
|
100
117
|
);
|
|
101
118
|
const value = (0, import_react.useMemo)(
|
|
102
119
|
() => ({
|
|
103
120
|
tone,
|
|
121
|
+
styles,
|
|
104
122
|
pinned,
|
|
105
123
|
togglePin,
|
|
106
124
|
setPinned,
|
|
@@ -129,6 +147,7 @@ function SidebarV2Provider({
|
|
|
129
147
|
}),
|
|
130
148
|
[
|
|
131
149
|
tone,
|
|
150
|
+
styles,
|
|
132
151
|
pinned,
|
|
133
152
|
togglePin,
|
|
134
153
|
setPinned,
|