@vllnt/ui 0.3.0 → 0.4.0-canary.56bbaf0

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.
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
3
  import { useEffect, useRef, useState, useSyncExternalStore } from "react";
4
- import { ChevronDown } from "lucide-react";
4
+ import { ChevronDown, ChevronLeft, ChevronRight } from "lucide-react";
5
5
  import Link from "next/link";
6
6
  import { usePathname } from "next/navigation";
7
7
  import { useMounted } from "../../lib/use-mounted";
@@ -94,6 +94,116 @@ function CollapsibleSection({
94
94
  )
95
95
  ] });
96
96
  }
97
+ function FamilyList({
98
+ onOpen,
99
+ sections
100
+ }) {
101
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
102
+ /* @__PURE__ */ jsx("div", { className: "px-3 py-2 text-xs font-semibold text-muted-foreground uppercase tracking-wider", children: "Components" }),
103
+ /* @__PURE__ */ jsx("div", { className: "space-y-0.5", children: sections.map((section) => /* @__PURE__ */ jsxs(
104
+ "button",
105
+ {
106
+ className: "flex w-full items-center justify-between px-3 py-1.5 rounded-md text-sm text-muted-foreground hover:bg-accent hover:text-accent-foreground transition-colors",
107
+ onClick: () => {
108
+ onOpen(section.title ?? "");
109
+ },
110
+ type: "button",
111
+ children: [
112
+ /* @__PURE__ */ jsx("span", { children: section.title }),
113
+ /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1 text-xs", children: [
114
+ section.items.length,
115
+ /* @__PURE__ */ jsx(ChevronRight, { className: "size-3" })
116
+ ] })
117
+ ]
118
+ },
119
+ section.title
120
+ )) })
121
+ ] });
122
+ }
123
+ function FamilyItems({
124
+ isMobile,
125
+ onBack,
126
+ onNavigate,
127
+ pathname,
128
+ section
129
+ }) {
130
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
131
+ /* @__PURE__ */ jsxs(
132
+ "button",
133
+ {
134
+ className: "flex w-full items-center gap-1.5 px-3 py-2 text-xs font-semibold text-muted-foreground uppercase tracking-wider hover:text-foreground transition-colors",
135
+ onClick: onBack,
136
+ type: "button",
137
+ children: [
138
+ /* @__PURE__ */ jsx(ChevronLeft, { className: "size-3" }),
139
+ /* @__PURE__ */ jsx("span", { children: "All families" })
140
+ ]
141
+ }
142
+ ),
143
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-3 pb-1", children: [
144
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-semibold", children: section.title }),
145
+ /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: section.items.length })
146
+ ] }),
147
+ /* @__PURE__ */ jsx("div", { className: "space-y-0.5", children: section.items.map((item) => /* @__PURE__ */ jsx(
148
+ Link,
149
+ {
150
+ "aria-current": pathname === item.href ? "page" : void 0,
151
+ className: cn(
152
+ "block px-3 py-1.5 rounded-md text-sm transition-colors",
153
+ pathname === item.href ? "bg-accent text-accent-foreground font-medium" : "text-muted-foreground hover:bg-accent hover:text-accent-foreground"
154
+ ),
155
+ href: item.href,
156
+ onClick: () => {
157
+ if (isMobile) {
158
+ onNavigate();
159
+ }
160
+ },
161
+ children: item.title
162
+ },
163
+ item.href
164
+ )) })
165
+ ] });
166
+ }
167
+ function FamilyNav({
168
+ isMobile,
169
+ onNavigate,
170
+ pathname,
171
+ sections
172
+ }) {
173
+ const activeTitle = sections.find(
174
+ (section) => section.items.some((item) => item.href === pathname)
175
+ )?.title ?? null;
176
+ const [routeKey, setRouteKey] = useState(pathname);
177
+ const [openTitle, setOpenTitle] = useState(activeTitle);
178
+ if (routeKey !== pathname) {
179
+ setRouteKey(pathname);
180
+ setOpenTitle(activeTitle);
181
+ }
182
+ const openSection = openTitle === null ? null : sections.find((section) => section.title === openTitle) ?? null;
183
+ if (openSection) {
184
+ return /* @__PURE__ */ jsx(
185
+ FamilyItems,
186
+ {
187
+ isMobile,
188
+ onBack: () => {
189
+ setOpenTitle(null);
190
+ },
191
+ onNavigate,
192
+ pathname,
193
+ section: openSection
194
+ }
195
+ );
196
+ }
197
+ return /* @__PURE__ */ jsx(
198
+ FamilyList,
199
+ {
200
+ onOpen: (title) => {
201
+ setOpenTitle(title);
202
+ },
203
+ sections
204
+ }
205
+ );
206
+ }
97
207
  function Sidebar({ sections }) {
98
208
  const pathname = usePathname();
99
209
  const { open, setOpen } = useSidebar();
@@ -104,6 +214,8 @@ function Sidebar({ sections }) {
104
214
  scrollContainerReference
105
215
  );
106
216
  const collapsed = mounted && !isMobile && !open;
217
+ const familySections = sections.filter((section) => section.family);
218
+ const otherSections = sections.filter((section) => !section.family);
107
219
  return /* @__PURE__ */ jsxs(Fragment, { children: [
108
220
  isMobile && open ? /* @__PURE__ */ jsx(
109
221
  "div",
@@ -145,42 +257,55 @@ function Sidebar({ sections }) {
145
257
  {
146
258
  className: "flex-1 p-4 overflow-y-auto overscroll-contain h-full [scrollbar-width:none] [&::-webkit-scrollbar]:hidden",
147
259
  ref: scrollContainerReference,
148
- children: /* @__PURE__ */ jsx("div", { className: "space-y-4", children: sections.map((section, sectionIndex) => {
149
- const sectionItems = /* @__PURE__ */ jsx("div", { className: section.title ? "space-y-0.5" : "space-y-1", children: section.items.map((item) => /* @__PURE__ */ jsx(
150
- Link,
151
- {
152
- className: cn(
153
- section.title ? "block px-3 py-1.5 rounded-md text-sm transition-colors" : "flex items-center px-3 py-2 rounded-md text-sm font-medium transition-colors",
154
- pathname === item.href || item.href === "/" && pathname === "/" ? "bg-accent text-accent-foreground" : section.title ? "text-muted-foreground hover:bg-accent hover:text-accent-foreground" : "hover:bg-accent hover:text-accent-foreground",
155
- section.title && pathname === item.href && "font-medium"
156
- ),
157
- href: item.href,
158
- onClick: () => {
159
- if (isMobile) {
160
- setOpen(false);
161
- }
260
+ children: /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
261
+ otherSections.map((section, sectionIndex) => {
262
+ const sectionItems = /* @__PURE__ */ jsx("div", { className: section.title ? "space-y-0.5" : "space-y-1", children: section.items.map((item) => /* @__PURE__ */ jsx(
263
+ Link,
264
+ {
265
+ className: cn(
266
+ section.title ? "block px-3 py-1.5 rounded-md text-sm transition-colors" : "flex items-center px-3 py-2 rounded-md text-sm font-medium transition-colors",
267
+ pathname === item.href || item.href === "/" && pathname === "/" ? "bg-accent text-accent-foreground" : section.title ? "text-muted-foreground hover:bg-accent hover:text-accent-foreground" : "hover:bg-accent hover:text-accent-foreground",
268
+ section.title && pathname === item.href && "font-medium"
269
+ ),
270
+ href: item.href,
271
+ onClick: () => {
272
+ if (isMobile) {
273
+ setOpen(false);
274
+ }
275
+ },
276
+ children: item.title
162
277
  },
163
- children: item.title
164
- },
165
- item.href
166
- )) });
167
- return /* @__PURE__ */ jsx(
168
- "div",
278
+ item.href
279
+ )) });
280
+ return /* @__PURE__ */ jsx(
281
+ "div",
282
+ {
283
+ className: "space-y-1",
284
+ children: section.title ? /* @__PURE__ */ jsx(
285
+ CollapsibleSection,
286
+ {
287
+ collapsible: section.collapsible,
288
+ defaultOpen: section.defaultOpen ?? true,
289
+ title: section.title,
290
+ children: sectionItems
291
+ }
292
+ ) : sectionItems
293
+ },
294
+ section.title || sectionIndex
295
+ );
296
+ }),
297
+ familySections.length > 0 ? /* @__PURE__ */ jsx(
298
+ FamilyNav,
169
299
  {
170
- className: "space-y-1",
171
- children: section.title ? /* @__PURE__ */ jsx(
172
- CollapsibleSection,
173
- {
174
- collapsible: section.collapsible,
175
- defaultOpen: section.defaultOpen ?? true,
176
- title: section.title,
177
- children: sectionItems
178
- }
179
- ) : sectionItems
180
- },
181
- section.title || sectionIndex
182
- );
183
- }) })
300
+ isMobile,
301
+ onNavigate: () => {
302
+ setOpen(false);
303
+ },
304
+ pathname,
305
+ sections: familySections
306
+ }
307
+ ) : null
308
+ ] })
184
309
  }
185
310
  )
186
311
  ] })
package/dist/index.d.ts CHANGED
@@ -5049,6 +5049,7 @@ type SidebarItem = {
5049
5049
  type SidebarSection = {
5050
5050
  collapsible?: boolean;
5051
5051
  defaultOpen?: boolean;
5052
+ family?: boolean;
5052
5053
  items: SidebarItem[];
5053
5054
  title?: string;
5054
5055
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vllnt/ui",
3
- "version": "0.3.0",
3
+ "version": "0.4.0-canary.56bbaf0",
4
4
  "description": "React component library — 309 components built on Radix UI, Tailwind CSS, and CVA",
5
5
  "license": "MIT",
6
6
  "author": "vllnt",