@nikala-ui/core 0.11.0 → 0.12.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/package.json +43 -2
- package/registry/api-table.json +21 -0
- package/registry/banner.json +1 -1
- package/registry/button.json +1 -1
- package/registry/callout.json +19 -0
- package/registry/checkbox.json +4 -1
- package/registry/code-block.json +26 -0
- package/registry/code-group.json +20 -0
- package/registry/combobox.json +1 -1
- package/registry/command.json +3 -2
- package/registry/component-viewer.json +25 -0
- package/registry/container.json +18 -0
- package/registry/context-menu.json +1 -1
- package/registry/create-app-updater.json +13 -0
- package/registry/create-document-tabs.json +13 -0
- package/registry/create-global-shortcut.json +13 -0
- package/registry/create-tauri-window.json +13 -0
- package/registry/create-tiptap-editor.json +34 -0
- package/registry/dialog.json +1 -1
- package/registry/dropdown-menu.json +3 -2
- package/registry/field.json +1 -1
- package/registry/file-tree.json +21 -0
- package/registry/footer.json +1 -1
- package/registry/form-message.json +3 -2
- package/registry/icon-button.json +1 -1
- package/registry/index.json +336 -5
- package/registry/navbar.json +1 -1
- package/registry/navigation-menu.json +1 -1
- package/registry/number-input.json +1 -1
- package/registry/package-manager-tabs.json +24 -0
- package/registry/pager.json +21 -0
- package/registry/popover.json +4 -1
- package/registry/resizable.json +1 -1
- package/registry/rich-text-editor.json +95 -0
- package/registry/scroll-area.json +1 -1
- package/registry/section-heading.json +21 -0
- package/registry/select.json +3 -2
- package/registry/sheet.json +1 -1
- package/registry/sidebar.json +1 -1
- package/registry/status.json +1 -1
- package/registry/steps.json +20 -0
- package/registry/switch.json +4 -1
- package/registry/table-of-contents.json +23 -0
- package/registry/tabs.json +4 -1
- package/registry/theme-manager.json +6 -5
- package/registry/titlebar-tabs.json +24 -0
- package/registry/titlebar.json +26 -0
- package/registry/toggle-group.json +1 -1
- package/registry/updater-modal.json +26 -0
- package/src/index.ts +48 -0
- package/src/registry/components/ui/api-table.tsx +117 -0
- package/src/registry/components/ui/banner.tsx +0 -2
- package/src/registry/components/ui/button.tsx +1 -1
- package/src/registry/components/ui/callout.tsx +137 -0
- package/src/registry/components/ui/checkbox.tsx +1 -1
- package/src/registry/components/ui/code-block.tsx +326 -0
- package/src/registry/components/ui/code-group.tsx +105 -0
- package/src/registry/components/ui/combobox.tsx +83 -18
- package/src/registry/components/ui/command.tsx +110 -106
- package/src/registry/components/ui/component-viewer.tsx +363 -0
- package/src/registry/components/ui/container.tsx +45 -0
- package/src/registry/components/ui/context-menu.tsx +67 -22
- package/src/registry/components/ui/dialog.tsx +42 -32
- package/src/registry/components/ui/dropdown-menu.tsx +69 -31
- package/src/registry/components/ui/field.tsx +7 -3
- package/src/registry/components/ui/file-tree.tsx +181 -0
- package/src/registry/components/ui/footer.tsx +1 -1
- package/src/registry/components/ui/form-message.tsx +2 -2
- package/src/registry/components/ui/icon-button.tsx +1 -1
- package/src/registry/components/ui/navbar.tsx +18 -11
- package/src/registry/components/ui/navigation-menu.tsx +2 -2
- package/src/registry/components/ui/number-input.tsx +3 -3
- package/src/registry/components/ui/package-manager-tabs.tsx +226 -0
- package/src/registry/components/ui/pager.tsx +102 -0
- package/src/registry/components/ui/popover.tsx +1 -1
- package/src/registry/components/ui/resizable.tsx +3 -1
- package/src/registry/components/ui/rich-text-editor/bubble-menu.tsx +236 -0
- package/src/registry/components/ui/rich-text-editor/editor.tsx +308 -0
- package/src/registry/components/ui/rich-text-editor/extensions.ts +116 -0
- package/src/registry/components/ui/rich-text-editor/footer.tsx +36 -0
- package/src/registry/components/ui/rich-text-editor/image-dialog.tsx +75 -0
- package/src/registry/components/ui/rich-text-editor/index.ts +11 -0
- package/src/registry/components/ui/rich-text-editor/link-dialog.tsx +48 -0
- package/src/registry/components/ui/rich-text-editor/markdown.ts +170 -0
- package/src/registry/components/ui/rich-text-editor/slash-command.tsx +301 -0
- package/src/registry/components/ui/rich-text-editor/table-controls.tsx +68 -0
- package/src/registry/components/ui/rich-text-editor/toolbar.tsx +465 -0
- package/src/registry/components/ui/rich-text-editor/use-editor.ts +231 -0
- package/src/registry/components/ui/scroll-area.tsx +12 -2
- package/src/registry/components/ui/section-heading.tsx +108 -0
- package/src/registry/components/ui/select.tsx +16 -19
- package/src/registry/components/ui/sheet.tsx +58 -53
- package/src/registry/components/ui/sidebar.tsx +4 -4
- package/src/registry/components/ui/status.tsx +7 -5
- package/src/registry/components/ui/steps.tsx +198 -0
- package/src/registry/components/ui/switch.tsx +1 -1
- package/src/registry/components/ui/table-of-contents.tsx +131 -0
- package/src/registry/components/ui/tabs.tsx +1 -1
- package/src/registry/components/ui/theme-toggle.tsx +175 -139
- package/src/registry/components/ui/titlebar-tabs.tsx +773 -0
- package/src/registry/components/ui/titlebar.tsx +468 -0
- package/src/registry/components/ui/toggle-group.tsx +1 -1
- package/src/registry/components/ui/updater-modal.tsx +254 -0
- package/src/registry/metadata.ts +167 -6
- package/src/registry/providers/theme-provider.tsx +16 -8
- package/src/registry/providers/theme-script.tsx +29 -9
- package/src/registry/providers/theme-transitions.ts +81 -50
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Show,
|
|
3
|
+
splitProps,
|
|
4
|
+
type Component,
|
|
5
|
+
type ParentComponent,
|
|
6
|
+
type JSX,
|
|
7
|
+
} from "solid-js";
|
|
8
|
+
import {
|
|
9
|
+
Dialog,
|
|
10
|
+
DialogContent,
|
|
11
|
+
DialogHeader,
|
|
12
|
+
DialogTitle,
|
|
13
|
+
DialogDescription,
|
|
14
|
+
DialogFooter,
|
|
15
|
+
} from "@/components/ui/dialog";
|
|
16
|
+
import { Button } from "@/components/ui/button";
|
|
17
|
+
import { Badge } from "@/components/ui/badge";
|
|
18
|
+
import { Progress } from "@/components/ui/progress";
|
|
19
|
+
import { Alert, AlertTitle, AlertDescription } from "@/components/ui/alert";
|
|
20
|
+
import type {
|
|
21
|
+
CreateAppUpdaterReturn,
|
|
22
|
+
UpdateManifestInfo,
|
|
23
|
+
UpdateProgressInfo,
|
|
24
|
+
} from "@/hooks/create-app-updater";
|
|
25
|
+
import {
|
|
26
|
+
Download,
|
|
27
|
+
RotateCcw,
|
|
28
|
+
CheckCircle2,
|
|
29
|
+
AlertTriangle,
|
|
30
|
+
ArrowRight,
|
|
31
|
+
Package,
|
|
32
|
+
} from "lucide-solid";
|
|
33
|
+
import { cn } from "@/lib/cn";
|
|
34
|
+
|
|
35
|
+
function formatBytes(bytes: number): string {
|
|
36
|
+
if (!bytes || bytes === 0) return "0 MB";
|
|
37
|
+
const mb = bytes / (1024 * 1024);
|
|
38
|
+
return `${mb.toFixed(1)} MB`;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/* --- 1. Sub-components for Clean Modularity & Zero Repetition --- */
|
|
42
|
+
|
|
43
|
+
export interface UpdaterHeaderProps {
|
|
44
|
+
appName: string;
|
|
45
|
+
status: string;
|
|
46
|
+
info?: UpdateManifestInfo | null;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export const UpdaterHeader: Component<UpdaterHeaderProps> = (props) => (
|
|
50
|
+
<DialogHeader class="space-y-1.5 text-left">
|
|
51
|
+
<div class="flex items-center justify-between">
|
|
52
|
+
<div class="size-8 rounded-lg bg-primary/10 text-primary flex items-center justify-center">
|
|
53
|
+
<Package class="size-4" />
|
|
54
|
+
</div>
|
|
55
|
+
<Show when={props.info?.version}>
|
|
56
|
+
<div class="flex items-center gap-1.5 text-xs font-mono">
|
|
57
|
+
<span class="text-muted-foreground">{props.info?.currentVersion || "v1.0.0"}</span>
|
|
58
|
+
<ArrowRight class="size-3 text-muted-foreground" />
|
|
59
|
+
<Badge variant="default" class="text-xs px-1.5 py-0 bg-primary text-primary-foreground font-semibold">
|
|
60
|
+
{props.info?.version}
|
|
61
|
+
</Badge>
|
|
62
|
+
</div>
|
|
63
|
+
</Show>
|
|
64
|
+
</div>
|
|
65
|
+
|
|
66
|
+
<DialogTitle class="text-base font-bold tracking-tight text-foreground">
|
|
67
|
+
{props.status === "downloaded"
|
|
68
|
+
? "Update Ready to Install"
|
|
69
|
+
: props.status === "downloading"
|
|
70
|
+
? "Downloading Update..."
|
|
71
|
+
: props.status === "up-to-date"
|
|
72
|
+
? "Up to Date"
|
|
73
|
+
: `New Update Available for ${props.appName}`}
|
|
74
|
+
</DialogTitle>
|
|
75
|
+
|
|
76
|
+
<DialogDescription class="text-xs text-muted-foreground leading-relaxed">
|
|
77
|
+
{props.status === "downloaded"
|
|
78
|
+
? "The update has been downloaded and verified. Restart to apply changes."
|
|
79
|
+
: props.status === "downloading"
|
|
80
|
+
? "Please wait while update packages are being downloaded."
|
|
81
|
+
: props.status === "up-to-date"
|
|
82
|
+
? `${props.appName} is running on the latest version.`
|
|
83
|
+
: "A new version with features and bug fixes is ready to install."}
|
|
84
|
+
</DialogDescription>
|
|
85
|
+
</DialogHeader>
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
export interface UpdaterReleaseNotesProps {
|
|
89
|
+
body?: string;
|
|
90
|
+
date?: string;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export const UpdaterReleaseNotes: Component<UpdaterReleaseNotesProps> = (props) => (
|
|
94
|
+
<div class="space-y-1">
|
|
95
|
+
<div class="flex items-center justify-between text-xs text-muted-foreground font-medium">
|
|
96
|
+
<span>Release Notes</span>
|
|
97
|
+
<Show when={props.date}>
|
|
98
|
+
<span class="text-[11px] font-mono">{props.date}</span>
|
|
99
|
+
</Show>
|
|
100
|
+
</div>
|
|
101
|
+
<pre class="max-h-28 overflow-y-auto rounded-md border border-border bg-black/5 dark:bg-black/50 p-2.5 text-xs text-foreground font-mono whitespace-pre-wrap leading-relaxed select-text shadow-inner">
|
|
102
|
+
{props.body}
|
|
103
|
+
</pre>
|
|
104
|
+
</div>
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
export interface UpdaterProgressBarProps {
|
|
108
|
+
progress: UpdateProgressInfo;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export const UpdaterProgressBar: Component<UpdaterProgressBarProps> = (props) => (
|
|
112
|
+
<div class="space-y-1.5 py-1">
|
|
113
|
+
<div class="flex items-center justify-between text-xs font-mono">
|
|
114
|
+
<span class="text-muted-foreground font-sans">Progress</span>
|
|
115
|
+
<span class="font-semibold text-primary">{props.progress.percentage}%</span>
|
|
116
|
+
</div>
|
|
117
|
+
<Progress value={props.progress.percentage} class="h-1.5" />
|
|
118
|
+
<div class="flex items-center justify-between text-[11px] font-mono text-muted-foreground">
|
|
119
|
+
<span>{formatBytes(props.progress.downloaded)}</span>
|
|
120
|
+
<span>{formatBytes(props.progress.total)}</span>
|
|
121
|
+
</div>
|
|
122
|
+
</div>
|
|
123
|
+
);
|
|
124
|
+
|
|
125
|
+
/* --- 2. Main UpdaterModal Compound Component --- */
|
|
126
|
+
|
|
127
|
+
export interface UpdaterModalProps {
|
|
128
|
+
open: boolean;
|
|
129
|
+
onOpenChange: (open: boolean) => void;
|
|
130
|
+
updater: CreateAppUpdaterReturn;
|
|
131
|
+
appName?: string;
|
|
132
|
+
class?: string;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export const UpdaterModal: Component<UpdaterModalProps> = (props) => {
|
|
136
|
+
const [local, rest] = splitProps(props, [
|
|
137
|
+
"open",
|
|
138
|
+
"onOpenChange",
|
|
139
|
+
"updater",
|
|
140
|
+
"appName",
|
|
141
|
+
"class",
|
|
142
|
+
]);
|
|
143
|
+
|
|
144
|
+
const appName = () => local.appName || "Nikala Desktop";
|
|
145
|
+
const status = () => local.updater.status();
|
|
146
|
+
const info = () => local.updater.updateInfo();
|
|
147
|
+
const progress = () => local.updater.progress();
|
|
148
|
+
const error = () => local.updater.error();
|
|
149
|
+
|
|
150
|
+
return (
|
|
151
|
+
<Dialog open={local.open} onOpenChange={local.onOpenChange}>
|
|
152
|
+
<DialogContent class={cn("sm:max-w-sm", local.class)}>
|
|
153
|
+
{/* Header */}
|
|
154
|
+
<UpdaterHeader
|
|
155
|
+
appName={appName()}
|
|
156
|
+
status={status()}
|
|
157
|
+
info={info()}
|
|
158
|
+
/>
|
|
159
|
+
|
|
160
|
+
{/* Error Alert */}
|
|
161
|
+
<Show when={error()}>
|
|
162
|
+
<Alert variant="destructive" class="py-2 text-xs">
|
|
163
|
+
<AlertTriangle class="size-3.5" />
|
|
164
|
+
<AlertTitle class="font-semibold text-xs">Update Failed</AlertTitle>
|
|
165
|
+
<AlertDescription class="text-[11px]">{error()}</AlertDescription>
|
|
166
|
+
</Alert>
|
|
167
|
+
</Show>
|
|
168
|
+
|
|
169
|
+
{/* Release Notes */}
|
|
170
|
+
<Show when={info()?.body && (status() === "available" || status() === "downloading")}>
|
|
171
|
+
<UpdaterReleaseNotes body={info()?.body} date={info()?.date} />
|
|
172
|
+
</Show>
|
|
173
|
+
|
|
174
|
+
{/* Progress Bar */}
|
|
175
|
+
<Show when={status() === "downloading"}>
|
|
176
|
+
<UpdaterProgressBar progress={progress()} />
|
|
177
|
+
</Show>
|
|
178
|
+
|
|
179
|
+
{/* Success Callout */}
|
|
180
|
+
<Show when={status() === "downloaded"}>
|
|
181
|
+
<div class="flex items-center gap-2.5 p-2.5 rounded-md border border-primary/30 bg-primary/5 text-xs text-foreground">
|
|
182
|
+
<CheckCircle2 class="size-4 text-primary shrink-0" />
|
|
183
|
+
<p class="font-medium text-foreground text-xs">Package downloaded & verified.</p>
|
|
184
|
+
</div>
|
|
185
|
+
</Show>
|
|
186
|
+
|
|
187
|
+
{/* Actions Footer */}
|
|
188
|
+
<DialogFooter class="flex-row items-center justify-end gap-1.5 pt-1">
|
|
189
|
+
<Show when={status() === "available" || status() === "error"}>
|
|
190
|
+
<Button
|
|
191
|
+
variant="outline"
|
|
192
|
+
size="sm"
|
|
193
|
+
onClick={() => local.onOpenChange(false)}
|
|
194
|
+
class="text-xs h-7.5 px-3 cursor-pointer"
|
|
195
|
+
>
|
|
196
|
+
Later
|
|
197
|
+
</Button>
|
|
198
|
+
<Button
|
|
199
|
+
variant="default"
|
|
200
|
+
size="sm"
|
|
201
|
+
onClick={() => local.updater.downloadAndInstall()}
|
|
202
|
+
class="text-xs h-7.5 px-3 gap-1.5 cursor-pointer font-medium"
|
|
203
|
+
>
|
|
204
|
+
<Download class="size-3.5" />
|
|
205
|
+
<span>Update Now</span>
|
|
206
|
+
</Button>
|
|
207
|
+
</Show>
|
|
208
|
+
|
|
209
|
+
<Show when={status() === "downloading"}>
|
|
210
|
+
<Button
|
|
211
|
+
variant="outline"
|
|
212
|
+
size="sm"
|
|
213
|
+
disabled
|
|
214
|
+
class="text-xs h-7.5 w-full opacity-70 justify-center"
|
|
215
|
+
>
|
|
216
|
+
Downloading ({progress().percentage}%)
|
|
217
|
+
</Button>
|
|
218
|
+
</Show>
|
|
219
|
+
|
|
220
|
+
<Show when={status() === "downloaded"}>
|
|
221
|
+
<Button
|
|
222
|
+
variant="outline"
|
|
223
|
+
size="sm"
|
|
224
|
+
onClick={() => local.onOpenChange(false)}
|
|
225
|
+
class="text-xs h-7.5 px-3 cursor-pointer"
|
|
226
|
+
>
|
|
227
|
+
Later
|
|
228
|
+
</Button>
|
|
229
|
+
<Button
|
|
230
|
+
variant="default"
|
|
231
|
+
size="sm"
|
|
232
|
+
onClick={() => local.updater.relaunch()}
|
|
233
|
+
class="text-xs h-7.5 px-3 gap-1.5 cursor-pointer font-semibold shadow-xs"
|
|
234
|
+
>
|
|
235
|
+
<RotateCcw class="size-3.5" />
|
|
236
|
+
<span>Relaunch</span>
|
|
237
|
+
</Button>
|
|
238
|
+
</Show>
|
|
239
|
+
|
|
240
|
+
<Show when={status() === "up-to-date" || status() === "idle"}>
|
|
241
|
+
<Button
|
|
242
|
+
variant="outline"
|
|
243
|
+
size="sm"
|
|
244
|
+
onClick={() => local.onOpenChange(false)}
|
|
245
|
+
class="text-xs h-7.5 px-3 cursor-pointer"
|
|
246
|
+
>
|
|
247
|
+
Close
|
|
248
|
+
</Button>
|
|
249
|
+
</Show>
|
|
250
|
+
</DialogFooter>
|
|
251
|
+
</DialogContent>
|
|
252
|
+
</Dialog>
|
|
253
|
+
);
|
|
254
|
+
};
|
package/src/registry/metadata.ts
CHANGED
|
@@ -56,7 +56,7 @@ export const COMPONENT_METADATA: Record<string, ComponentMeta> = {
|
|
|
56
56
|
"form-message": {
|
|
57
57
|
title: "Form Message",
|
|
58
58
|
description: "Validation message helper connected to createForm errors and touched state.",
|
|
59
|
-
registryDependencies: ["field"],
|
|
59
|
+
registryDependencies: ["field", "create-form"],
|
|
60
60
|
},
|
|
61
61
|
field: {
|
|
62
62
|
title: "Field",
|
|
@@ -69,6 +69,11 @@ export const COMPONENT_METADATA: Record<string, ComponentMeta> = {
|
|
|
69
69
|
description: "A versatile container component with header, content, and footer sections.",
|
|
70
70
|
dependencies: ["clsx", "tailwind-merge"],
|
|
71
71
|
},
|
|
72
|
+
container: {
|
|
73
|
+
title: "Container",
|
|
74
|
+
description: "A responsive layout container constraining maximum width with semantic padding tokens.",
|
|
75
|
+
dependencies: ["clsx", "tailwind-merge", "class-variance-authority"],
|
|
76
|
+
},
|
|
72
77
|
badge: {
|
|
73
78
|
title: "Badge",
|
|
74
79
|
description: "A small badge component for status indicators and tags.",
|
|
@@ -103,11 +108,13 @@ export const COMPONENT_METADATA: Record<string, ComponentMeta> = {
|
|
|
103
108
|
title: "Switch",
|
|
104
109
|
description: "A control that allows the user to toggle between checked and unchecked states.",
|
|
105
110
|
dependencies: ["clsx", "tailwind-merge"],
|
|
111
|
+
registryDependencies: ["create-controllable-signal"],
|
|
106
112
|
},
|
|
107
113
|
checkbox: {
|
|
108
114
|
title: "Checkbox",
|
|
109
115
|
description: "A control that allows the user to toggle between checked and unchecked options.",
|
|
110
116
|
dependencies: ["clsx", "tailwind-merge"],
|
|
117
|
+
registryDependencies: ["create-controllable-signal"],
|
|
111
118
|
},
|
|
112
119
|
"radio-group": {
|
|
113
120
|
title: "Radio Group",
|
|
@@ -118,7 +125,7 @@ export const COMPONENT_METADATA: Record<string, ComponentMeta> = {
|
|
|
118
125
|
title: "Select",
|
|
119
126
|
description: "Displays a list of options for the user to pick from, built on Kobalte primitives.",
|
|
120
127
|
dependencies: ["clsx", "tailwind-merge", "@kobalte/core"],
|
|
121
|
-
registryDependencies: ["scroll-area"],
|
|
128
|
+
registryDependencies: ["scroll-area", "create-click-outside"],
|
|
122
129
|
},
|
|
123
130
|
combobox: {
|
|
124
131
|
title: "Combobox",
|
|
@@ -130,6 +137,7 @@ export const COMPONENT_METADATA: Record<string, ComponentMeta> = {
|
|
|
130
137
|
title: "Tabs",
|
|
131
138
|
description: "A set of layered sections of content displayed one at a time.",
|
|
132
139
|
dependencies: ["clsx", "tailwind-merge"],
|
|
140
|
+
registryDependencies: ["create-controllable-signal"],
|
|
133
141
|
},
|
|
134
142
|
accordion: {
|
|
135
143
|
title: "Accordion",
|
|
@@ -162,13 +170,13 @@ export const COMPONENT_METADATA: Record<string, ComponentMeta> = {
|
|
|
162
170
|
title: "Dropdown Menu",
|
|
163
171
|
description: "Displays a menu to the user—such as a set of actions or functions—triggered by a button or avatar.",
|
|
164
172
|
dependencies: ["clsx", "tailwind-merge", "@kobalte/core"],
|
|
165
|
-
registryDependencies: ["scroll-area"],
|
|
173
|
+
registryDependencies: ["scroll-area", "create-click-outside"],
|
|
166
174
|
},
|
|
167
175
|
"theme-manager": {
|
|
168
176
|
title: "Theme Manager",
|
|
169
177
|
description: "Zero-dependency ThemeProvider and ThemeToggle component for switching light, dark, and system themes.",
|
|
170
178
|
dependencies: ["clsx", "tailwind-merge", "@kobalte/core", "lucide-solid"],
|
|
171
|
-
registryDependencies: ["button", "dropdown-menu"],
|
|
179
|
+
registryDependencies: ["button", "dropdown-menu", "create-color-mode"],
|
|
172
180
|
},
|
|
173
181
|
banner: {
|
|
174
182
|
title: "Banner",
|
|
@@ -201,7 +209,7 @@ export const COMPONENT_METADATA: Record<string, ComponentMeta> = {
|
|
|
201
209
|
"lucide-solid",
|
|
202
210
|
"@kobalte/core",
|
|
203
211
|
],
|
|
204
|
-
registryDependencies: ["kbd", "input-group", "list", "scroll-area"],
|
|
212
|
+
registryDependencies: ["kbd", "input-group", "list", "scroll-area", "create-keybindings"],
|
|
205
213
|
},
|
|
206
214
|
toast: {
|
|
207
215
|
title: "Toast / Sonner",
|
|
@@ -217,6 +225,7 @@ export const COMPONENT_METADATA: Record<string, ComponentMeta> = {
|
|
|
217
225
|
title: "Popover",
|
|
218
226
|
description: "Displays rich content in a portal layer triggered by a button, built on Kobalte primitives.",
|
|
219
227
|
dependencies: ["clsx", "tailwind-merge", "@kobalte/core", "lucide-solid"],
|
|
228
|
+
registryDependencies: ["create-click-outside"],
|
|
220
229
|
},
|
|
221
230
|
progress: {
|
|
222
231
|
title: "Progress",
|
|
@@ -342,6 +351,12 @@ export const COMPONENT_METADATA: Record<string, ComponentMeta> = {
|
|
|
342
351
|
dependencies: ["clsx", "tailwind-merge", "class-variance-authority", "lucide-solid"],
|
|
343
352
|
registryDependencies: ["create-pagination"],
|
|
344
353
|
},
|
|
354
|
+
pager: {
|
|
355
|
+
title: "Pager",
|
|
356
|
+
description: "Previous and next article navigation links with card previews for documentation and blog layouts.",
|
|
357
|
+
dependencies: ["clsx", "tailwind-merge", "lucide-solid"],
|
|
358
|
+
registryDependencies: ["card"],
|
|
359
|
+
},
|
|
345
360
|
message: {
|
|
346
361
|
title: "Message",
|
|
347
362
|
description: "A structured chat and conversation message layout with avatars, alignment, headers, footers, and actions.",
|
|
@@ -363,6 +378,112 @@ export const COMPONENT_METADATA: Record<string, ComponentMeta> = {
|
|
|
363
378
|
dependencies: ["clsx", "tailwind-merge", "class-variance-authority", "lucide-solid"],
|
|
364
379
|
registryDependencies: ["tooltip", "skeleton", "separator"],
|
|
365
380
|
},
|
|
381
|
+
titlebar: {
|
|
382
|
+
title: "Titlebar",
|
|
383
|
+
description: "A native-feeling custom titlebar for frameless desktop windows supporting macOS Traffic Lights and Windows 11 controls.",
|
|
384
|
+
dependencies: ["clsx", "tailwind-merge", "class-variance-authority", "lucide-solid"],
|
|
385
|
+
registryDependencies: ["titlebar-tabs", "button", "tooltip", "create-tauri-window", "create-document-tabs"],
|
|
386
|
+
},
|
|
387
|
+
"titlebar-tabs": {
|
|
388
|
+
title: "Titlebar Tabs",
|
|
389
|
+
description: "Native draggable tab bar integrated directly inside desktop titlebars for multi-document applications.",
|
|
390
|
+
dependencies: ["clsx", "tailwind-merge", "class-variance-authority", "lucide-solid"],
|
|
391
|
+
registryDependencies: ["button", "tooltip", "create-document-tabs"],
|
|
392
|
+
},
|
|
393
|
+
"updater-modal": {
|
|
394
|
+
title: "Updater Modal",
|
|
395
|
+
description: "An automated application auto-updater dialog for Tauri v2 with release notes preview, download progress bar, and relaunch actions.",
|
|
396
|
+
dependencies: ["clsx", "tailwind-merge", "lucide-solid"],
|
|
397
|
+
registryDependencies: ["dialog", "button", "badge", "progress", "alert", "create-app-updater"],
|
|
398
|
+
},
|
|
399
|
+
"rich-text-editor": {
|
|
400
|
+
title: "Rich Text Editor",
|
|
401
|
+
description: "A full-featured WYSIWYG rich text editor with toolbar, bubble formatting, tables, task lists, and image uploads built on Tiptap.",
|
|
402
|
+
dependencies: [
|
|
403
|
+
"@tiptap/core",
|
|
404
|
+
"@tiptap/starter-kit",
|
|
405
|
+
"@tiptap/extension-link",
|
|
406
|
+
"@tiptap/extension-image",
|
|
407
|
+
"@tiptap/extension-placeholder",
|
|
408
|
+
"@tiptap/extension-task-list",
|
|
409
|
+
"@tiptap/extension-task-item",
|
|
410
|
+
"@tiptap/extension-table",
|
|
411
|
+
"@tiptap/extension-table-row",
|
|
412
|
+
"@tiptap/extension-table-cell",
|
|
413
|
+
"@tiptap/extension-table-header",
|
|
414
|
+
"@tiptap/extension-underline",
|
|
415
|
+
"@tiptap/extension-text-align",
|
|
416
|
+
"@tiptap/extension-highlight",
|
|
417
|
+
"@tiptap/extension-character-count",
|
|
418
|
+
"@tiptap/extension-subscript",
|
|
419
|
+
"@tiptap/extension-superscript",
|
|
420
|
+
"@tiptap/extension-typography",
|
|
421
|
+
"tiptap-markdown",
|
|
422
|
+
"clsx",
|
|
423
|
+
"tailwind-merge",
|
|
424
|
+
"lucide-solid",
|
|
425
|
+
],
|
|
426
|
+
registryDependencies: ["create-tiptap-editor"],
|
|
427
|
+
},
|
|
428
|
+
callout: {
|
|
429
|
+
title: "Callout",
|
|
430
|
+
description: "A semantic callout and alert block with status variants, icons, and titles for documentation and notices.",
|
|
431
|
+
dependencies: ["clsx", "tailwind-merge", "class-variance-authority", "lucide-solid"],
|
|
432
|
+
},
|
|
433
|
+
"code-block": {
|
|
434
|
+
title: "Code Block",
|
|
435
|
+
description: "A code block container with filename header, language indicator, and interactive copy to clipboard button.",
|
|
436
|
+
dependencies: ["clsx", "tailwind-merge", "lucide-solid", "shiki"],
|
|
437
|
+
registryDependencies: ["button", "badge", "tooltip", "tabs", "create-clipboard"],
|
|
438
|
+
},
|
|
439
|
+
"package-manager-tabs": {
|
|
440
|
+
title: "Package Manager Tabs",
|
|
441
|
+
description: "An interactive command tab bar supporting customizable package managers (bun, pnpm, npm, yarn, deno, bunx, npx) with copy functionality.",
|
|
442
|
+
dependencies: ["clsx", "tailwind-merge", "lucide-solid"],
|
|
443
|
+
registryDependencies: ["button", "tooltip", "tabs", "create-clipboard"],
|
|
444
|
+
},
|
|
445
|
+
"code-group": {
|
|
446
|
+
title: "Code Group",
|
|
447
|
+
description: "A compound tabbed code container for organizing multiple files, languages, and snippets built on Tabs.",
|
|
448
|
+
dependencies: ["clsx", "tailwind-merge"],
|
|
449
|
+
registryDependencies: ["tabs"],
|
|
450
|
+
},
|
|
451
|
+
steps: {
|
|
452
|
+
title: "Steps",
|
|
453
|
+
description: "A vertical multi-step instruction container with connecting progress line and numbered step indicators.",
|
|
454
|
+
dependencies: ["clsx", "tailwind-merge"],
|
|
455
|
+
registryDependencies: ["badge"],
|
|
456
|
+
},
|
|
457
|
+
"file-tree": {
|
|
458
|
+
title: "File Tree",
|
|
459
|
+
description: "An interactive hierarchical directory file tree component built on Collapsible.",
|
|
460
|
+
dependencies: ["clsx", "tailwind-merge", "lucide-solid"],
|
|
461
|
+
registryDependencies: ["collapsible"],
|
|
462
|
+
},
|
|
463
|
+
"section-heading": {
|
|
464
|
+
title: "Section Heading",
|
|
465
|
+
description: "A reusable heading block with title, optional badge, and description. Supports page and section variants.",
|
|
466
|
+
dependencies: ["clsx", "tailwind-merge", "class-variance-authority"],
|
|
467
|
+
registryDependencies: ["badge"],
|
|
468
|
+
},
|
|
469
|
+
"api-table": {
|
|
470
|
+
title: "API Table",
|
|
471
|
+
description: "A structured, clean API reference table component for documenting props, options, and events.",
|
|
472
|
+
dependencies: ["clsx", "tailwind-merge"],
|
|
473
|
+
registryDependencies: ["table", "section-heading"],
|
|
474
|
+
},
|
|
475
|
+
"component-viewer": {
|
|
476
|
+
title: "Component Viewer",
|
|
477
|
+
description: "An interactive preview canvas and code viewer container with responsive viewports, canvas grid, and AI prompts.",
|
|
478
|
+
dependencies: ["clsx", "tailwind-merge", "lucide-solid"],
|
|
479
|
+
registryDependencies: ["tabs", "button", "tooltip", "code-block", "create-clipboard"],
|
|
480
|
+
},
|
|
481
|
+
"table-of-contents": {
|
|
482
|
+
title: "Table of Contents",
|
|
483
|
+
description: "An accessible heading navigation tree with ScrollSpy tracking and smooth scrolling, composed of ScrollArea and List.",
|
|
484
|
+
dependencies: ["clsx", "tailwind-merge", "class-variance-authority"],
|
|
485
|
+
registryDependencies: ["scroll-area", "list", "create-scroll-position"],
|
|
486
|
+
},
|
|
366
487
|
};
|
|
367
488
|
|
|
368
489
|
/**
|
|
@@ -541,6 +662,47 @@ export const HOOK_METADATA: Record<string, ComponentMeta> = {
|
|
|
541
662
|
title: "createChatScroll",
|
|
542
663
|
description: "SolidJS reactive primitive for automated chat container scrolling with manual scroll-up detection",
|
|
543
664
|
},
|
|
665
|
+
"create-tauri-window": {
|
|
666
|
+
title: "createTauriWindow",
|
|
667
|
+
description: "SolidJS reactive primitive for interacting with and controlling Tauri v2 application window states",
|
|
668
|
+
},
|
|
669
|
+
"create-global-shortcut": {
|
|
670
|
+
title: "createGlobalShortcut",
|
|
671
|
+
description: "SolidJS reactive primitive for registering OS-level global keyboard shortcuts via Tauri v2 plugin",
|
|
672
|
+
},
|
|
673
|
+
"create-app-updater": {
|
|
674
|
+
title: "createAppUpdater",
|
|
675
|
+
description: "SolidJS reactive primitive for controlling and observing Tauri v2 application updates",
|
|
676
|
+
},
|
|
677
|
+
"create-document-tabs": {
|
|
678
|
+
title: "createDocumentTabs",
|
|
679
|
+
description: "SolidJS reactive primitive for managing multi-document tabs, editor buffers, and browser tab stacks with adjacent activation and pinned state",
|
|
680
|
+
},
|
|
681
|
+
"create-tiptap-editor": {
|
|
682
|
+
title: "createTiptapEditor",
|
|
683
|
+
description: "Fine-grained reactive SolidJS primitive for managing Tiptap rich text editor instances, signals, and formatting commands.",
|
|
684
|
+
dependencies: [
|
|
685
|
+
"@tiptap/core",
|
|
686
|
+
"@tiptap/starter-kit",
|
|
687
|
+
"@tiptap/extension-link",
|
|
688
|
+
"@tiptap/extension-image",
|
|
689
|
+
"@tiptap/extension-placeholder",
|
|
690
|
+
"@tiptap/extension-task-list",
|
|
691
|
+
"@tiptap/extension-task-item",
|
|
692
|
+
"@tiptap/extension-table",
|
|
693
|
+
"@tiptap/extension-table-row",
|
|
694
|
+
"@tiptap/extension-table-cell",
|
|
695
|
+
"@tiptap/extension-table-header",
|
|
696
|
+
"@tiptap/extension-underline",
|
|
697
|
+
"@tiptap/extension-text-align",
|
|
698
|
+
"@tiptap/extension-highlight",
|
|
699
|
+
"@tiptap/extension-character-count",
|
|
700
|
+
"@tiptap/extension-subscript",
|
|
701
|
+
"@tiptap/extension-superscript",
|
|
702
|
+
"@tiptap/extension-typography",
|
|
703
|
+
"tiptap-markdown",
|
|
704
|
+
],
|
|
705
|
+
},
|
|
544
706
|
};
|
|
545
707
|
|
|
546
708
|
/**
|
|
@@ -578,4 +740,3 @@ export const BLOCK_METADATA: Record<string, ComponentMeta> = {
|
|
|
578
740
|
registryDependencies: ["card", "input", "label", "button", "alert", "form", "field", "form-message"],
|
|
579
741
|
},
|
|
580
742
|
};
|
|
581
|
-
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
} from "solid-js";
|
|
11
11
|
|
|
12
12
|
export type Theme = "light" | "dark" | "system";
|
|
13
|
-
export type AccentColor = "
|
|
13
|
+
export type AccentColor = "yellow" | "red" | "violet" | "sky" | "emerald" | "zinc";
|
|
14
14
|
export type Radius = "0" | "0.3" | "0.5" | "0.75" | "1.0";
|
|
15
15
|
|
|
16
16
|
export interface ThemeProviderProps {
|
|
@@ -28,13 +28,12 @@ const ACCENT_COLORS: Record<
|
|
|
28
28
|
AccentColor,
|
|
29
29
|
{ light: string; dark: string; lightFg: string; darkFg: string }
|
|
30
30
|
> = {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
zinc: { light: "#18181b", dark: "#fafafa", lightFg: "#fafafa", darkFg: "#18181b" },
|
|
31
|
+
yellow: { light: "oklch(0.795 0.184 86.047)", dark: "oklch(0.852 0.199 91.936)", lightFg: "oklch(0.145 0 0)", darkFg: "oklch(0.145 0 0)" },
|
|
32
|
+
red: { light: "oklch(0.577 0.245 27.325)", dark: "oklch(0.637 0.237 25.331)", lightFg: "oklch(0.985 0 0)", darkFg: "oklch(0.985 0 0)" },
|
|
33
|
+
violet: { light: "oklch(0.541 0.281 293.009)", dark: "oklch(0.606 0.25 292.717)", lightFg: "oklch(0.985 0 0)", darkFg: "oklch(0.985 0 0)" },
|
|
34
|
+
sky: { light: "oklch(0.588 0.158 241.966)", dark: "oklch(0.672 0.154 238.29)", lightFg: "oklch(0.985 0 0)", darkFg: "oklch(0.145 0 0)" },
|
|
35
|
+
emerald: { light: "oklch(0.596 0.145 163.225)", dark: "oklch(0.696 0.17 162.48)", lightFg: "oklch(0.985 0 0)", darkFg: "oklch(0.145 0 0)" },
|
|
36
|
+
zinc: { light: "oklch(0.205 0 0)", dark: "oklch(0.985 0 0)", lightFg: "oklch(0.985 0 0)", darkFg: "oklch(0.205 0 0)" },
|
|
38
37
|
};
|
|
39
38
|
|
|
40
39
|
interface ThemeProviderContextValue {
|
|
@@ -106,6 +105,7 @@ export const ThemeProvider: ParentComponent<ThemeProviderProps> = (props) => {
|
|
|
106
105
|
resolvedDark = targetTheme === "dark";
|
|
107
106
|
root.classList.add(targetTheme);
|
|
108
107
|
}
|
|
108
|
+
root.style.colorScheme = resolvedDark ? "dark" : "light";
|
|
109
109
|
|
|
110
110
|
// Override --primary CSS variables ONLY if explicitly chosen
|
|
111
111
|
if (currentAccent && ACCENT_COLORS[currentAccent]) {
|
|
@@ -115,11 +115,16 @@ export const ThemeProvider: ParentComponent<ThemeProviderProps> = (props) => {
|
|
|
115
115
|
|
|
116
116
|
root.style.setProperty("--primary", primaryHex);
|
|
117
117
|
root.style.setProperty("--primary-foreground", primaryFgHex);
|
|
118
|
+
} else {
|
|
119
|
+
root.style.removeProperty("--primary");
|
|
120
|
+
root.style.removeProperty("--primary-foreground");
|
|
118
121
|
}
|
|
119
122
|
|
|
120
123
|
// Override --radius CSS variable ONLY if explicitly chosen
|
|
121
124
|
if (currentRadius) {
|
|
122
125
|
root.style.setProperty("--radius", `${currentRadius}rem`);
|
|
126
|
+
} else {
|
|
127
|
+
root.style.removeProperty("--radius");
|
|
123
128
|
}
|
|
124
129
|
};
|
|
125
130
|
|
|
@@ -135,7 +140,9 @@ export const ThemeProvider: ParentComponent<ThemeProviderProps> = (props) => {
|
|
|
135
140
|
try {
|
|
136
141
|
localStorage.setItem(`${storageKey}-mode`, t);
|
|
137
142
|
if (a) localStorage.setItem(`${storageKey}-accent`, a);
|
|
143
|
+
else localStorage.removeItem(`${storageKey}-accent`);
|
|
138
144
|
if (r) localStorage.setItem(`${storageKey}-radius`, r);
|
|
145
|
+
else localStorage.removeItem(`${storageKey}-radius`);
|
|
139
146
|
} catch { }
|
|
140
147
|
}
|
|
141
148
|
});
|
|
@@ -150,6 +157,7 @@ export const ThemeProvider: ParentComponent<ThemeProviderProps> = (props) => {
|
|
|
150
157
|
const root = document.documentElement;
|
|
151
158
|
root.classList.remove("light", "dark");
|
|
152
159
|
root.classList.add(e.matches ? "dark" : "light");
|
|
160
|
+
root.style.colorScheme = e.matches ? "dark" : "light";
|
|
153
161
|
|
|
154
162
|
const currentAccent = accent();
|
|
155
163
|
if (currentAccent && ACCENT_COLORS[currentAccent]) {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { isServer } from "solid-js/web";
|
|
2
|
+
import type { Component } from "solid-js";
|
|
2
3
|
|
|
3
4
|
export interface ThemeScriptProps {
|
|
4
5
|
/** Storage key namespace used in localStorage (default: "nikala-theme") */
|
|
@@ -15,6 +16,7 @@ export interface ThemeScriptProps {
|
|
|
15
16
|
* Pre-hydration inline script executed synchronously before DOM paint to prevent theme flickering (anti-FOUC).
|
|
16
17
|
*/
|
|
17
18
|
export const ThemeScript: Component<ThemeScriptProps> = (props) => {
|
|
19
|
+
if (!isServer) return null;
|
|
18
20
|
const key = props.storageKey || "nikala-theme";
|
|
19
21
|
const defTheme = props.defaultTheme || "system";
|
|
20
22
|
const defAccent = props.defaultAccent || "";
|
|
@@ -35,17 +37,35 @@ export const ThemeScript: Component<ThemeScriptProps> = (props) => {
|
|
|
35
37
|
root.style.colorScheme = resolvedDark ? 'dark' : 'light';
|
|
36
38
|
|
|
37
39
|
var colorMap = {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
40
|
+
yellow: {
|
|
41
|
+
primary: resolvedDark ? 'oklch(0.852 0.199 91.936)' : 'oklch(0.795 0.184 86.047)',
|
|
42
|
+
foreground: 'oklch(0.145 0 0)'
|
|
43
|
+
},
|
|
44
|
+
red: {
|
|
45
|
+
primary: resolvedDark ? 'oklch(0.637 0.237 25.331)' : 'oklch(0.577 0.245 27.325)',
|
|
46
|
+
foreground: 'oklch(0.985 0 0)'
|
|
47
|
+
},
|
|
48
|
+
violet: {
|
|
49
|
+
primary: resolvedDark ? 'oklch(0.606 0.25 292.717)' : 'oklch(0.541 0.281 293.009)',
|
|
50
|
+
foreground: 'oklch(0.985 0 0)'
|
|
51
|
+
},
|
|
52
|
+
sky: {
|
|
53
|
+
primary: resolvedDark ? 'oklch(0.672 0.154 238.29)' : 'oklch(0.588 0.158 241.966)',
|
|
54
|
+
foreground: resolvedDark ? 'oklch(0.145 0 0)' : 'oklch(0.985 0 0)'
|
|
55
|
+
},
|
|
56
|
+
emerald: {
|
|
57
|
+
primary: resolvedDark ? 'oklch(0.696 0.17 162.48)' : 'oklch(0.596 0.145 163.225)',
|
|
58
|
+
foreground: resolvedDark ? 'oklch(0.145 0 0)' : 'oklch(0.985 0 0)'
|
|
59
|
+
},
|
|
60
|
+
zinc: {
|
|
61
|
+
primary: resolvedDark ? 'oklch(0.985 0 0)' : 'oklch(0.205 0 0)',
|
|
62
|
+
foreground: resolvedDark ? 'oklch(0.205 0 0)' : 'oklch(0.985 0 0)'
|
|
63
|
+
}
|
|
45
64
|
};
|
|
46
65
|
|
|
47
66
|
if (accent && colorMap[accent]) {
|
|
48
|
-
root.style.setProperty('--primary', colorMap[accent]);
|
|
67
|
+
root.style.setProperty('--primary', colorMap[accent].primary);
|
|
68
|
+
root.style.setProperty('--primary-foreground', colorMap[accent].foreground);
|
|
49
69
|
}
|
|
50
70
|
|
|
51
71
|
if (radius) {
|