@silicajs/components 0.1.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/backlinks.d.ts +12 -0
- package/dist/backlinks.js +36 -0
- package/dist/backlinks.js.map +1 -0
- package/dist/breadcrumbs.d.ts +10 -0
- package/dist/breadcrumbs.js +37 -0
- package/dist/breadcrumbs.js.map +1 -0
- package/dist/dark-mode-toggle.d.ts +8 -0
- package/dist/dark-mode-toggle.js +107 -0
- package/dist/dark-mode-toggle.js.map +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.js +45 -0
- package/dist/index.js.map +1 -0
- package/dist/not-allowed.d.ts +14 -0
- package/dist/not-allowed.js +27 -0
- package/dist/not-allowed.js.map +1 -0
- package/dist/not-found.d.ts +14 -0
- package/dist/not-found.js +27 -0
- package/dist/not-found.js.map +1 -0
- package/dist/page-properties.d.ts +10 -0
- package/dist/page-properties.js +80 -0
- package/dist/page-properties.js.map +1 -0
- package/dist/routing.d.ts +22 -0
- package/dist/routing.js +42 -0
- package/dist/routing.js.map +1 -0
- package/dist/search.d.ts +14 -0
- package/dist/search.js +158 -0
- package/dist/search.js.map +1 -0
- package/dist/slug.d.ts +6 -0
- package/dist/slug.js +20 -0
- package/dist/slug.js.map +1 -0
- package/dist/table-of-contents.d.ts +13 -0
- package/dist/table-of-contents.js +25 -0
- package/dist/table-of-contents.js.map +1 -0
- package/dist/tags-list.d.ts +11 -0
- package/dist/tags-list.js +68 -0
- package/dist/tags-list.js.map +1 -0
- package/dist/user-menu.d.ts +9 -0
- package/dist/user-menu.js +41 -0
- package/dist/user-menu.js.map +1 -0
- package/dist/vault-tree.d.ts +15 -0
- package/dist/vault-tree.js +248 -0
- package/dist/vault-tree.js.map +1 -0
- package/package.json +46 -0
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { ChevronRight } from "lucide-react";
|
|
5
|
+
import { cn } from "@silicajs/ui/lib/utils";
|
|
6
|
+
import {
|
|
7
|
+
Collapsible,
|
|
8
|
+
CollapsibleContent,
|
|
9
|
+
CollapsibleTrigger
|
|
10
|
+
} from "@silicajs/ui/components/collapsible";
|
|
11
|
+
import {
|
|
12
|
+
SidebarMenu,
|
|
13
|
+
SidebarMenuAction,
|
|
14
|
+
SidebarMenuButton,
|
|
15
|
+
SidebarMenuItem,
|
|
16
|
+
SidebarMenuSub
|
|
17
|
+
} from "@silicajs/ui/components/sidebar";
|
|
18
|
+
import { useSilicaRouting } from "./routing.js";
|
|
19
|
+
import { prettySegment, slugToHref } from "./slug.js";
|
|
20
|
+
const STORAGE_KEY = "silica-tree-expanded";
|
|
21
|
+
function emptyNode(name, fullPath, sortKey) {
|
|
22
|
+
return { key: fullPath || "/", name, fullPath, sortKey, children: [] };
|
|
23
|
+
}
|
|
24
|
+
function buildTreeFromEntries(entries) {
|
|
25
|
+
const root = emptyNode("", "");
|
|
26
|
+
const byPath = /* @__PURE__ */ new Map([["", root]]);
|
|
27
|
+
let homeEntry;
|
|
28
|
+
for (const entry of entries) {
|
|
29
|
+
if (entry.slug === "index") {
|
|
30
|
+
homeEntry = entry;
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
const segments = entry.slug.split("/");
|
|
34
|
+
const sortSegments = entry.sortKey?.split("/") ?? [];
|
|
35
|
+
let parent = root;
|
|
36
|
+
for (let i = 0; i < segments.length; i++) {
|
|
37
|
+
const segment = segments[i];
|
|
38
|
+
const isLast = i === segments.length - 1;
|
|
39
|
+
const fullPath = segments.slice(0, i + 1).join("/");
|
|
40
|
+
const nodeSortKey = sortSegments.slice(0, i + 1).join("/") || void 0;
|
|
41
|
+
if (isLast && segment === "index") {
|
|
42
|
+
parent.entry = entry;
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
let node = byPath.get(fullPath);
|
|
46
|
+
if (!node) {
|
|
47
|
+
node = emptyNode(segment, fullPath, nodeSortKey);
|
|
48
|
+
byPath.set(fullPath, node);
|
|
49
|
+
parent.children.push(node);
|
|
50
|
+
} else if (!node.sortKey && nodeSortKey) {
|
|
51
|
+
node.sortKey = nodeSortKey;
|
|
52
|
+
}
|
|
53
|
+
if (isLast) node.entry = entry;
|
|
54
|
+
parent = node;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
const sortRecursively = (node) => {
|
|
58
|
+
if (node.children.some((child) => child.sortKey)) {
|
|
59
|
+
node.children.sort(compareOrderedNodes);
|
|
60
|
+
} else {
|
|
61
|
+
const folders = node.children.filter((c) => c.children.length > 0);
|
|
62
|
+
const leaves = node.children.filter((c) => c.children.length === 0);
|
|
63
|
+
folders.sort((a, b) => a.name.localeCompare(b.name));
|
|
64
|
+
leaves.sort((a, b) => {
|
|
65
|
+
const ta = a.entry?.title ?? a.name;
|
|
66
|
+
const tb = b.entry?.title ?? b.name;
|
|
67
|
+
return ta.localeCompare(tb);
|
|
68
|
+
});
|
|
69
|
+
node.children = [...folders, ...leaves];
|
|
70
|
+
}
|
|
71
|
+
for (const child of node.children) sortRecursively(child);
|
|
72
|
+
};
|
|
73
|
+
sortRecursively(root);
|
|
74
|
+
return { nodes: root.children, homeEntry };
|
|
75
|
+
}
|
|
76
|
+
function compareOrderedNodes(a, b) {
|
|
77
|
+
return (a.sortKey ?? fallbackNodeSortKey(a)).localeCompare(
|
|
78
|
+
b.sortKey ?? fallbackNodeSortKey(b)
|
|
79
|
+
) || fallbackNodeLabel(a).localeCompare(fallbackNodeLabel(b));
|
|
80
|
+
}
|
|
81
|
+
function fallbackNodeSortKey(node) {
|
|
82
|
+
return `~~~~~~~~~~:${fallbackNodeLabel(node)}`;
|
|
83
|
+
}
|
|
84
|
+
function fallbackNodeLabel(node) {
|
|
85
|
+
return node.entry?.title ?? node.name;
|
|
86
|
+
}
|
|
87
|
+
function ancestorIdsOf(slug) {
|
|
88
|
+
if (!slug || slug === "index") return [];
|
|
89
|
+
const segments = slug.split("/");
|
|
90
|
+
const out = [];
|
|
91
|
+
for (let i = 1; i < segments.length; i++) {
|
|
92
|
+
out.push(segments.slice(0, i).join("/"));
|
|
93
|
+
}
|
|
94
|
+
return out;
|
|
95
|
+
}
|
|
96
|
+
function activeIdFromSlug(slug) {
|
|
97
|
+
if (!slug || slug === "index") return void 0;
|
|
98
|
+
if (slug.endsWith("/index")) return slug.slice(0, -"/index".length);
|
|
99
|
+
return slug;
|
|
100
|
+
}
|
|
101
|
+
function VaultTree({
|
|
102
|
+
entries,
|
|
103
|
+
currentSlug: currentSlugProp,
|
|
104
|
+
showHomeLink = true
|
|
105
|
+
}) {
|
|
106
|
+
const { Link, currentSlug: routedCurrentSlug } = useSilicaRouting();
|
|
107
|
+
const currentSlug = currentSlugProp ?? routedCurrentSlug;
|
|
108
|
+
const { nodes, homeEntry } = React.useMemo(
|
|
109
|
+
() => buildTreeFromEntries(entries),
|
|
110
|
+
[entries]
|
|
111
|
+
);
|
|
112
|
+
const activeId = activeIdFromSlug(currentSlug);
|
|
113
|
+
const homeIsActive = currentSlug === "index" || currentSlug === void 0;
|
|
114
|
+
const [expanded, setExpanded] = React.useState(/* @__PURE__ */ new Set());
|
|
115
|
+
React.useEffect(() => {
|
|
116
|
+
const next = /* @__PURE__ */ new Set();
|
|
117
|
+
try {
|
|
118
|
+
const raw = window.localStorage.getItem(STORAGE_KEY);
|
|
119
|
+
if (raw) {
|
|
120
|
+
const parsed = JSON.parse(raw);
|
|
121
|
+
if (Array.isArray(parsed)) {
|
|
122
|
+
for (const x of parsed) if (typeof x === "string") next.add(x);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
} catch {
|
|
126
|
+
}
|
|
127
|
+
for (const id of ancestorIdsOf(currentSlug)) next.add(id);
|
|
128
|
+
setExpanded(next);
|
|
129
|
+
}, [currentSlug]);
|
|
130
|
+
const handleToggle = React.useCallback((id, open) => {
|
|
131
|
+
setExpanded((prev) => {
|
|
132
|
+
const next = new Set(prev);
|
|
133
|
+
if (open) next.add(id);
|
|
134
|
+
else next.delete(id);
|
|
135
|
+
try {
|
|
136
|
+
window.localStorage.setItem(STORAGE_KEY, JSON.stringify([...next]));
|
|
137
|
+
} catch {
|
|
138
|
+
}
|
|
139
|
+
return next;
|
|
140
|
+
});
|
|
141
|
+
}, []);
|
|
142
|
+
return /* @__PURE__ */ jsxs(SidebarMenu, { children: [
|
|
143
|
+
showHomeLink ? /* @__PURE__ */ jsx(SidebarMenuItem, { children: /* @__PURE__ */ jsx(SidebarMenuButton, { isActive: homeIsActive, render: /* @__PURE__ */ jsx(Link, { href: "/" }), children: /* @__PURE__ */ jsx("span", { className: "truncate", children: homeEntry?.title ?? "Home" }) }) }) : null,
|
|
144
|
+
nodes.map((node) => /* @__PURE__ */ jsx(
|
|
145
|
+
VaultTreeNode,
|
|
146
|
+
{
|
|
147
|
+
node,
|
|
148
|
+
activeId,
|
|
149
|
+
expanded,
|
|
150
|
+
onToggle: handleToggle,
|
|
151
|
+
Link
|
|
152
|
+
},
|
|
153
|
+
node.key
|
|
154
|
+
))
|
|
155
|
+
] });
|
|
156
|
+
}
|
|
157
|
+
function VaultTreeNode({
|
|
158
|
+
node,
|
|
159
|
+
activeId,
|
|
160
|
+
expanded,
|
|
161
|
+
onToggle,
|
|
162
|
+
Link
|
|
163
|
+
}) {
|
|
164
|
+
const hasChildren = node.children.length > 0;
|
|
165
|
+
const isActive = activeId === node.key;
|
|
166
|
+
const isOpen = expanded.has(node.key);
|
|
167
|
+
const label = node.entry?.title ?? prettySegment(node.name);
|
|
168
|
+
const href = node.entry ? slugToHref(node.entry.slug) : void 0;
|
|
169
|
+
if (!hasChildren) {
|
|
170
|
+
return /* @__PURE__ */ jsx(SidebarMenuItem, { children: /* @__PURE__ */ jsx(
|
|
171
|
+
SidebarMenuButton,
|
|
172
|
+
{
|
|
173
|
+
isActive,
|
|
174
|
+
...href ? { render: /* @__PURE__ */ jsx(Link, { href }) } : {},
|
|
175
|
+
children: /* @__PURE__ */ jsx("span", { className: "truncate", children: label })
|
|
176
|
+
}
|
|
177
|
+
) });
|
|
178
|
+
}
|
|
179
|
+
if (href) {
|
|
180
|
+
return /* @__PURE__ */ jsx(SidebarMenuItem, { children: /* @__PURE__ */ jsxs(
|
|
181
|
+
Collapsible,
|
|
182
|
+
{
|
|
183
|
+
open: isOpen,
|
|
184
|
+
onOpenChange: (open) => onToggle(node.key, open),
|
|
185
|
+
children: [
|
|
186
|
+
/* @__PURE__ */ jsx(SidebarMenuButton, { isActive, render: /* @__PURE__ */ jsx(Link, { href }), children: /* @__PURE__ */ jsx("span", { className: "truncate", children: label }) }),
|
|
187
|
+
/* @__PURE__ */ jsx(
|
|
188
|
+
CollapsibleTrigger,
|
|
189
|
+
{
|
|
190
|
+
render: /* @__PURE__ */ jsx(
|
|
191
|
+
SidebarMenuAction,
|
|
192
|
+
{
|
|
193
|
+
"aria-label": isOpen ? "Collapse" : "Expand",
|
|
194
|
+
className: cn("transition-transform", isOpen && "rotate-90"),
|
|
195
|
+
children: /* @__PURE__ */ jsx(ChevronRight, {})
|
|
196
|
+
}
|
|
197
|
+
)
|
|
198
|
+
}
|
|
199
|
+
),
|
|
200
|
+
/* @__PURE__ */ jsx(CollapsibleContent, { children: /* @__PURE__ */ jsx(SidebarMenuSub, { children: node.children.map((child) => /* @__PURE__ */ jsx(
|
|
201
|
+
VaultTreeNode,
|
|
202
|
+
{
|
|
203
|
+
node: child,
|
|
204
|
+
activeId,
|
|
205
|
+
expanded,
|
|
206
|
+
onToggle,
|
|
207
|
+
Link
|
|
208
|
+
},
|
|
209
|
+
child.key
|
|
210
|
+
)) }) })
|
|
211
|
+
]
|
|
212
|
+
}
|
|
213
|
+
) });
|
|
214
|
+
}
|
|
215
|
+
return /* @__PURE__ */ jsx(SidebarMenuItem, { children: /* @__PURE__ */ jsxs(
|
|
216
|
+
Collapsible,
|
|
217
|
+
{
|
|
218
|
+
open: isOpen,
|
|
219
|
+
onOpenChange: (open) => onToggle(node.key, open),
|
|
220
|
+
children: [
|
|
221
|
+
/* @__PURE__ */ jsxs(SidebarMenuButton, { isActive, render: /* @__PURE__ */ jsx(CollapsibleTrigger, {}), children: [
|
|
222
|
+
/* @__PURE__ */ jsx(
|
|
223
|
+
ChevronRight,
|
|
224
|
+
{
|
|
225
|
+
className: cn("transition-transform", isOpen && "rotate-90")
|
|
226
|
+
}
|
|
227
|
+
),
|
|
228
|
+
/* @__PURE__ */ jsx("span", { className: "truncate", children: label })
|
|
229
|
+
] }),
|
|
230
|
+
/* @__PURE__ */ jsx(CollapsibleContent, { children: /* @__PURE__ */ jsx(SidebarMenuSub, { children: node.children.map((child) => /* @__PURE__ */ jsx(
|
|
231
|
+
VaultTreeNode,
|
|
232
|
+
{
|
|
233
|
+
node: child,
|
|
234
|
+
activeId,
|
|
235
|
+
expanded,
|
|
236
|
+
onToggle,
|
|
237
|
+
Link
|
|
238
|
+
},
|
|
239
|
+
child.key
|
|
240
|
+
)) }) })
|
|
241
|
+
]
|
|
242
|
+
}
|
|
243
|
+
) });
|
|
244
|
+
}
|
|
245
|
+
export {
|
|
246
|
+
VaultTree
|
|
247
|
+
};
|
|
248
|
+
//# sourceMappingURL=vault-tree.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/vault-tree.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport { ChevronRight } from \"lucide-react\";\n\nimport { cn } from \"@silicajs/ui/lib/utils\";\nimport {\n Collapsible,\n CollapsibleContent,\n CollapsibleTrigger,\n} from \"@silicajs/ui/components/collapsible\";\nimport {\n SidebarMenu,\n SidebarMenuAction,\n SidebarMenuButton,\n SidebarMenuItem,\n SidebarMenuSub,\n} from \"@silicajs/ui/components/sidebar\";\n\nimport { useSilicaRouting, type SilicaLinkComponent } from \"./routing.js\";\nimport { prettySegment, slugToHref } from \"./slug.js\";\n\nconst STORAGE_KEY = \"silica-tree-expanded\";\n\nexport type VaultTreeEntry = {\n slug: string;\n title: string;\n sortKey?: string;\n};\n\ntype FolderNode = {\n key: string;\n name: string;\n fullPath: string;\n sortKey?: string;\n entry?: VaultTreeEntry;\n children: FolderNode[];\n};\n\nfunction emptyNode(\n name: string,\n fullPath: string,\n sortKey?: string,\n): FolderNode {\n return { key: fullPath || \"/\", name, fullPath, sortKey, children: [] };\n}\n\nfunction buildTreeFromEntries(entries: VaultTreeEntry[]): {\n nodes: FolderNode[];\n homeEntry?: VaultTreeEntry;\n} {\n const root = emptyNode(\"\", \"\");\n const byPath = new Map<string, FolderNode>([[\"\", root]]);\n let homeEntry: VaultTreeEntry | undefined;\n\n for (const entry of entries) {\n if (entry.slug === \"index\") {\n homeEntry = entry;\n continue;\n }\n const segments = entry.slug.split(\"/\");\n const sortSegments = entry.sortKey?.split(\"/\") ?? [];\n let parent = root;\n for (let i = 0; i < segments.length; i++) {\n const segment = segments[i]!;\n const isLast = i === segments.length - 1;\n const fullPath = segments.slice(0, i + 1).join(\"/\");\n const nodeSortKey = sortSegments.slice(0, i + 1).join(\"/\") || undefined;\n if (isLast && segment === \"index\") {\n parent.entry = entry;\n continue;\n }\n let node = byPath.get(fullPath);\n if (!node) {\n node = emptyNode(segment, fullPath, nodeSortKey);\n byPath.set(fullPath, node);\n parent.children.push(node);\n } else if (!node.sortKey && nodeSortKey) {\n node.sortKey = nodeSortKey;\n }\n if (isLast) node.entry = entry;\n parent = node;\n }\n }\n\n const sortRecursively = (node: FolderNode) => {\n if (node.children.some((child) => child.sortKey)) {\n node.children.sort(compareOrderedNodes);\n } else {\n const folders = node.children.filter((c) => c.children.length > 0);\n const leaves = node.children.filter((c) => c.children.length === 0);\n folders.sort((a, b) => a.name.localeCompare(b.name));\n leaves.sort((a, b) => {\n const ta = a.entry?.title ?? a.name;\n const tb = b.entry?.title ?? b.name;\n return ta.localeCompare(tb);\n });\n node.children = [...folders, ...leaves];\n }\n for (const child of node.children) sortRecursively(child);\n };\n sortRecursively(root);\n\n return { nodes: root.children, homeEntry };\n}\n\nfunction compareOrderedNodes(a: FolderNode, b: FolderNode): number {\n return (\n (a.sortKey ?? fallbackNodeSortKey(a)).localeCompare(\n b.sortKey ?? fallbackNodeSortKey(b),\n ) || fallbackNodeLabel(a).localeCompare(fallbackNodeLabel(b))\n );\n}\n\nfunction fallbackNodeSortKey(node: FolderNode): string {\n return `~~~~~~~~~~:${fallbackNodeLabel(node)}`;\n}\n\nfunction fallbackNodeLabel(node: FolderNode): string {\n return node.entry?.title ?? node.name;\n}\n\nfunction ancestorIdsOf(slug: string | undefined): string[] {\n if (!slug || slug === \"index\") return [];\n const segments = slug.split(\"/\");\n const out: string[] = [];\n for (let i = 1; i < segments.length; i++) {\n out.push(segments.slice(0, i).join(\"/\"));\n }\n return out;\n}\n\nfunction activeIdFromSlug(slug: string | undefined): string | undefined {\n if (!slug || slug === \"index\") return undefined;\n if (slug.endsWith(\"/index\")) return slug.slice(0, -\"/index\".length);\n return slug;\n}\n\nexport type VaultTreeProps = {\n entries: VaultTreeEntry[];\n currentSlug?: string;\n showHomeLink?: boolean;\n};\n\nexport function VaultTree({\n entries,\n currentSlug: currentSlugProp,\n showHomeLink = true,\n}: VaultTreeProps) {\n const { Link, currentSlug: routedCurrentSlug } = useSilicaRouting();\n const currentSlug = currentSlugProp ?? routedCurrentSlug;\n const { nodes, homeEntry } = React.useMemo(\n () => buildTreeFromEntries(entries),\n [entries],\n );\n\n const activeId = activeIdFromSlug(currentSlug);\n const homeIsActive = currentSlug === \"index\" || currentSlug === undefined;\n\n const [expanded, setExpanded] = React.useState<Set<string>>(new Set());\n\n // Hydrate expansion state from localStorage and re-sync ancestor expansion\n // whenever the active slug changes (e.g. on client-side navigation).\n React.useEffect(() => {\n const next = new Set<string>();\n try {\n const raw = window.localStorage.getItem(STORAGE_KEY);\n if (raw) {\n const parsed = JSON.parse(raw) as unknown;\n if (Array.isArray(parsed)) {\n for (const x of parsed) if (typeof x === \"string\") next.add(x);\n }\n }\n } catch {\n // ignore\n }\n for (const id of ancestorIdsOf(currentSlug)) next.add(id);\n setExpanded(next);\n }, [currentSlug]);\n\n const handleToggle = React.useCallback((id: string, open: boolean) => {\n setExpanded((prev) => {\n const next = new Set(prev);\n if (open) next.add(id);\n else next.delete(id);\n try {\n window.localStorage.setItem(STORAGE_KEY, JSON.stringify([...next]));\n } catch {\n // ignore\n }\n return next;\n });\n }, []);\n\n return (\n <SidebarMenu>\n {showHomeLink ? (\n <SidebarMenuItem>\n <SidebarMenuButton isActive={homeIsActive} render={<Link href=\"/\" />}>\n <span className=\"truncate\">{homeEntry?.title ?? \"Home\"}</span>\n </SidebarMenuButton>\n </SidebarMenuItem>\n ) : null}\n {nodes.map((node) => (\n <VaultTreeNode\n key={node.key}\n node={node}\n activeId={activeId}\n expanded={expanded}\n onToggle={handleToggle}\n Link={Link}\n />\n ))}\n </SidebarMenu>\n );\n}\n\ntype VaultTreeNodeProps = {\n node: FolderNode;\n activeId: string | undefined;\n expanded: Set<string>;\n onToggle: (id: string, open: boolean) => void;\n Link: SilicaLinkComponent;\n};\n\nfunction VaultTreeNode({\n node,\n activeId,\n expanded,\n onToggle,\n Link,\n}: VaultTreeNodeProps) {\n const hasChildren = node.children.length > 0;\n const isActive = activeId === node.key;\n const isOpen = expanded.has(node.key);\n const label = node.entry?.title ?? prettySegment(node.name);\n const href = node.entry ? slugToHref(node.entry.slug) : undefined;\n\n if (!hasChildren) {\n return (\n <SidebarMenuItem>\n <SidebarMenuButton\n isActive={isActive}\n {...(href ? { render: <Link href={href} /> } : {})}\n >\n <span className=\"truncate\">{label}</span>\n </SidebarMenuButton>\n </SidebarMenuItem>\n );\n }\n\n // Folder that is also a page: label navigates, separate chevron toggles.\n if (href) {\n return (\n <SidebarMenuItem>\n <Collapsible\n open={isOpen}\n onOpenChange={(open) => onToggle(node.key, open)}\n >\n <SidebarMenuButton isActive={isActive} render={<Link href={href} />}>\n <span className=\"truncate\">{label}</span>\n </SidebarMenuButton>\n <CollapsibleTrigger\n render={\n <SidebarMenuAction\n aria-label={isOpen ? \"Collapse\" : \"Expand\"}\n className={cn(\"transition-transform\", isOpen && \"rotate-90\")}\n >\n <ChevronRight />\n </SidebarMenuAction>\n }\n />\n <CollapsibleContent>\n <SidebarMenuSub>\n {node.children.map((child) => (\n <VaultTreeNode\n key={child.key}\n node={child}\n activeId={activeId}\n expanded={expanded}\n onToggle={onToggle}\n Link={Link}\n />\n ))}\n </SidebarMenuSub>\n </CollapsibleContent>\n </Collapsible>\n </SidebarMenuItem>\n );\n }\n\n // Folder without its own page: whole row toggles.\n return (\n <SidebarMenuItem>\n <Collapsible\n open={isOpen}\n onOpenChange={(open) => onToggle(node.key, open)}\n >\n <SidebarMenuButton isActive={isActive} render={<CollapsibleTrigger />}>\n <ChevronRight\n className={cn(\"transition-transform\", isOpen && \"rotate-90\")}\n />\n <span className=\"truncate\">{label}</span>\n </SidebarMenuButton>\n <CollapsibleContent>\n <SidebarMenuSub>\n {node.children.map((child) => (\n <VaultTreeNode\n key={child.key}\n node={child}\n activeId={activeId}\n expanded={expanded}\n onToggle={onToggle}\n Link={Link}\n />\n ))}\n </SidebarMenuSub>\n </CollapsibleContent>\n </Collapsible>\n </SidebarMenuItem>\n );\n}\n"],"mappings":"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","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@silicajs/components",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Silica-aware, framework-agnostic React composables built on @silicajs/ui.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"publishConfig": {
|
|
8
|
+
"access": "public"
|
|
9
|
+
},
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"import": "./dist/index.js"
|
|
14
|
+
},
|
|
15
|
+
"./routing": {
|
|
16
|
+
"types": "./dist/routing.d.ts",
|
|
17
|
+
"import": "./dist/routing.js"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
"dist"
|
|
22
|
+
],
|
|
23
|
+
"scripts": {
|
|
24
|
+
"build": "tsup",
|
|
25
|
+
"typecheck": "tsc --noEmit",
|
|
26
|
+
"lint": "tsc --noEmit",
|
|
27
|
+
"test": "vitest run --passWithNoTests"
|
|
28
|
+
},
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"@silicajs/core": "^0.1.0",
|
|
31
|
+
"@silicajs/remark-obsidian": "^0.1.0",
|
|
32
|
+
"@silicajs/ui": "^0.1.0",
|
|
33
|
+
"lucide-react": "^1.16.0"
|
|
34
|
+
},
|
|
35
|
+
"peerDependencies": {
|
|
36
|
+
"react": "^19.2.0",
|
|
37
|
+
"react-dom": "^19.2.0"
|
|
38
|
+
},
|
|
39
|
+
"devDependencies": {
|
|
40
|
+
"@types/react": "^19.2.10",
|
|
41
|
+
"@types/react-dom": "^19.2.3",
|
|
42
|
+
"react": "^19.2.6",
|
|
43
|
+
"react-dom": "^19.2.6",
|
|
44
|
+
"tsup": "^8.5.1"
|
|
45
|
+
}
|
|
46
|
+
}
|