@vllnt/ui 0.4.0-canary.cb3c196 → 0.4.0-canary.d173470

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.
@@ -0,0 +1,22 @@
1
+ import { createElement } from "react";
2
+ import { cn } from "../../lib/utils";
3
+ const displayBase = "font-[family-name:var(--font-display)] [font-weight:var(--font-weight-display)] text-[length:var(--font-size-display)] leading-[var(--line-height-display)] text-balance tracking-tight text-foreground";
4
+ const Display = ({
5
+ animated = false,
6
+ as = "div",
7
+ className,
8
+ ref,
9
+ ...props
10
+ }) => createElement(as, {
11
+ className: cn(
12
+ displayBase,
13
+ animated && "motion-safe:animate-[vllnt-animated-text-reveal_0.6s_ease-out_both]",
14
+ className
15
+ ),
16
+ ref,
17
+ ...props
18
+ });
19
+ Display.displayName = "Display";
20
+ export {
21
+ Display
22
+ };
@@ -0,0 +1,4 @@
1
+ import { Display } from "./display";
2
+ export {
3
+ Display
4
+ };
@@ -0,0 +1,40 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { cn } from "../../lib/utils";
3
+ const headingTag = {
4
+ 1: "h1",
5
+ 2: "h2",
6
+ 3: "h3",
7
+ 4: "h4",
8
+ 5: "h5",
9
+ 6: "h6"
10
+ };
11
+ const headingSize = {
12
+ 1: "text-[length:var(--font-size-h1)] leading-[var(--line-height-h1)]",
13
+ 2: "text-[length:var(--font-size-h2)] leading-[var(--line-height-h2)]",
14
+ 3: "text-[length:var(--font-size-h3)] leading-[var(--line-height-h3)]",
15
+ 4: "text-[length:var(--font-size-h4)] leading-[var(--line-height-h4)]",
16
+ 5: "text-[length:var(--font-size-h5)] leading-[var(--line-height-h5)]",
17
+ 6: "text-[length:var(--font-size-h6)] leading-[var(--line-height-h6)]"
18
+ };
19
+ const headingBase = "font-[family-name:var(--font-display)] [font-weight:var(--font-weight-heading)] text-balance tracking-tight text-foreground";
20
+ const Heading = ({
21
+ className,
22
+ level = 2,
23
+ ref,
24
+ size,
25
+ ...props
26
+ }) => {
27
+ const Tag = headingTag[level];
28
+ return /* @__PURE__ */ jsx(
29
+ Tag,
30
+ {
31
+ className: cn(headingBase, headingSize[size ?? level], className),
32
+ ref,
33
+ ...props
34
+ }
35
+ );
36
+ };
37
+ Heading.displayName = "Heading";
38
+ export {
39
+ Heading
40
+ };
@@ -0,0 +1,4 @@
1
+ import { Heading } from "./heading";
2
+ export {
3
+ Heading
4
+ };
@@ -999,6 +999,10 @@ import {
999
999
  PanelHeader,
1000
1000
  PanelTitle
1001
1001
  } from "./panel";
1002
+ import { Heading } from "./heading";
1003
+ import { Text, textVariants } from "./text";
1004
+ import { Display } from "./display";
1005
+ import { Prose } from "./prose";
1002
1006
  export {
1003
1007
  AIArtifact,
1004
1008
  AIArtifactContent,
@@ -1186,6 +1190,7 @@ export {
1186
1190
  DialogPortal,
1187
1191
  DialogTitle,
1188
1192
  DialogTrigger,
1193
+ Display,
1189
1194
  Dock,
1190
1195
  DockIcon,
1191
1196
  DocumentSiblingNav,
@@ -1273,6 +1278,7 @@ export {
1273
1278
  H3,
1274
1279
  H4,
1275
1280
  HandoffBeacon,
1281
+ Heading,
1276
1282
  HeatMapOverlay,
1277
1283
  HeatOverlay,
1278
1284
  Highlight,
@@ -1441,6 +1447,7 @@ export {
1441
1447
  PromptInput,
1442
1448
  PromptTemplates,
1443
1449
  PropertySection,
1450
+ Prose,
1444
1451
  QrCode,
1445
1452
  Quiz,
1446
1453
  RadarChart,
@@ -1549,6 +1556,7 @@ export {
1549
1556
  TagGroupItem,
1550
1557
  TagsInput,
1551
1558
  Terminal,
1559
+ Text,
1552
1560
  TextAnimate,
1553
1561
  TextField,
1554
1562
  TextReveal,
@@ -1637,6 +1645,7 @@ export {
1637
1645
  severityBadgeVariants,
1638
1646
  statCardVariants,
1639
1647
  statusIndicatorVariants,
1648
+ textVariants,
1640
1649
  timelineVariants,
1641
1650
  toast,
1642
1651
  toggleVariants,
@@ -0,0 +1,4 @@
1
+ import { Prose } from "./prose";
2
+ export {
3
+ Prose
4
+ };
@@ -0,0 +1,21 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { cn } from "../../lib/utils";
3
+ const proseStyles = cn(
4
+ "font-[family-name:var(--font-sans)] text-[length:var(--font-size-body)] leading-[var(--line-height-body)] text-foreground",
5
+ "[&>*+*]:mt-4",
6
+ "[&_h1]:mt-8 [&_h1]:font-[family-name:var(--font-display)] [&_h1]:[font-weight:var(--font-weight-heading)] [&_h1]:text-[length:var(--font-size-h1)] [&_h1]:leading-[var(--line-height-h1)] [&_h1]:tracking-tight",
7
+ "[&_h2]:mt-8 [&_h2]:font-[family-name:var(--font-display)] [&_h2]:[font-weight:var(--font-weight-heading)] [&_h2]:text-[length:var(--font-size-h2)] [&_h2]:leading-[var(--line-height-h2)] [&_h2]:tracking-tight",
8
+ "[&_h3]:mt-6 [&_h3]:font-[family-name:var(--font-display)] [&_h3]:[font-weight:var(--font-weight-heading)] [&_h3]:text-[length:var(--font-size-h3)] [&_h3]:leading-[var(--line-height-h3)] [&_h3]:tracking-tight",
9
+ "[&_h4]:mt-6 [&_h4]:font-[family-name:var(--font-display)] [&_h4]:[font-weight:var(--font-weight-heading)] [&_h4]:text-[length:var(--font-size-h4)] [&_h4]:leading-[var(--line-height-h4)] [&_h4]:tracking-tight",
10
+ "[&_p]:text-[length:var(--font-size-body)] [&_p]:leading-[var(--line-height-body)]",
11
+ "[&_ul]:my-4 [&_ul]:ml-6 [&_ul]:list-disc [&_ol]:my-4 [&_ol]:ml-6 [&_ol]:list-decimal [&_li]:mt-2",
12
+ "[&_a]:font-medium [&_a]:underline [&_a]:underline-offset-4",
13
+ "[&_blockquote]:mt-6 [&_blockquote]:border-l-2 [&_blockquote]:border-border [&_blockquote]:pl-6 [&_blockquote]:italic",
14
+ "[&_code]:rounded [&_code]:bg-muted [&_code]:px-[0.3rem] [&_code]:py-[0.2rem] [&_code]:font-mono [&_code]:text-[0.9em]",
15
+ "[&_strong]:font-semibold"
16
+ );
17
+ const Prose = ({ className, ref, ...props }) => /* @__PURE__ */ jsx("div", { className: cn(proseStyles, className), ref, ...props });
18
+ Prose.displayName = "Prose";
19
+ export {
20
+ Prose
21
+ };
@@ -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
  ] })
@@ -0,0 +1,5 @@
1
+ import { Text, textVariants } from "./text";
2
+ export {
3
+ Text,
4
+ textVariants
5
+ };
@@ -0,0 +1,48 @@
1
+ import { createElement } from "react";
2
+ import { cva } from "class-variance-authority";
3
+ import { cn } from "../../lib/utils";
4
+ const textVariants = cva(
5
+ "font-[family-name:var(--font-sans)] text-foreground",
6
+ {
7
+ defaultVariants: {
8
+ size: "base",
9
+ tone: "default",
10
+ weight: "normal"
11
+ },
12
+ variants: {
13
+ size: {
14
+ base: "text-[length:var(--font-size-body)] leading-[var(--line-height-body)]",
15
+ caption: "text-[length:var(--font-size-caption)] leading-[var(--line-height-caption)]",
16
+ lead: "text-[length:var(--font-size-body-lg)] leading-[var(--line-height-body-lg)]",
17
+ small: "text-[length:var(--font-size-body-sm)] leading-[var(--line-height-body-sm)]"
18
+ },
19
+ tone: {
20
+ default: "",
21
+ muted: "text-muted-foreground"
22
+ },
23
+ weight: {
24
+ medium: "font-medium",
25
+ normal: "font-normal",
26
+ semibold: "font-semibold"
27
+ }
28
+ }
29
+ }
30
+ );
31
+ const Text = ({
32
+ as = "p",
33
+ className,
34
+ ref,
35
+ size,
36
+ tone,
37
+ weight,
38
+ ...props
39
+ }) => createElement(as, {
40
+ className: cn(textVariants({ size, tone, weight }), className),
41
+ ref,
42
+ ...props
43
+ });
44
+ Text.displayName = "Text";
45
+ export {
46
+ Text,
47
+ textVariants
48
+ };