@gmickel/gno 0.7.0 → 0.8.1
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/LICENSE +21 -0
- package/README.md +90 -50
- package/THIRD_PARTY_NOTICES.md +22 -0
- package/assets/screenshots/webui-ask-answer.png +0 -0
- package/assets/screenshots/webui-collections.png +0 -0
- package/assets/screenshots/webui-editor.png +0 -0
- package/assets/screenshots/webui-home.png +0 -0
- package/assets/skill/SKILL.md +12 -12
- package/assets/skill/cli-reference.md +59 -57
- package/assets/skill/examples.md +8 -7
- package/assets/skill/mcp-reference.md +8 -4
- package/package.json +31 -24
- package/src/app/constants.ts +43 -42
- package/src/cli/colors.ts +1 -1
- package/src/cli/commands/ask.ts +44 -43
- package/src/cli/commands/cleanup.ts +9 -8
- package/src/cli/commands/collection/add.ts +12 -12
- package/src/cli/commands/collection/index.ts +4 -4
- package/src/cli/commands/collection/list.ts +26 -25
- package/src/cli/commands/collection/remove.ts +10 -10
- package/src/cli/commands/collection/rename.ts +10 -10
- package/src/cli/commands/context/add.ts +1 -1
- package/src/cli/commands/context/check.ts +17 -17
- package/src/cli/commands/context/index.ts +4 -4
- package/src/cli/commands/context/list.ts +11 -11
- package/src/cli/commands/context/rm.ts +1 -1
- package/src/cli/commands/doctor.ts +86 -84
- package/src/cli/commands/embed.ts +30 -28
- package/src/cli/commands/get.ts +27 -26
- package/src/cli/commands/index-cmd.ts +9 -9
- package/src/cli/commands/index.ts +16 -16
- package/src/cli/commands/init.ts +13 -12
- package/src/cli/commands/ls.ts +20 -19
- package/src/cli/commands/mcp/config.ts +30 -28
- package/src/cli/commands/mcp/index.ts +4 -4
- package/src/cli/commands/mcp/install.ts +17 -17
- package/src/cli/commands/mcp/paths.ts +133 -133
- package/src/cli/commands/mcp/status.ts +21 -21
- package/src/cli/commands/mcp/uninstall.ts +13 -13
- package/src/cli/commands/mcp.ts +2 -2
- package/src/cli/commands/models/clear.ts +12 -11
- package/src/cli/commands/models/index.ts +5 -5
- package/src/cli/commands/models/list.ts +31 -30
- package/src/cli/commands/models/path.ts +1 -1
- package/src/cli/commands/models/pull.ts +19 -18
- package/src/cli/commands/models/use.ts +4 -4
- package/src/cli/commands/multi-get.ts +38 -36
- package/src/cli/commands/query.ts +21 -20
- package/src/cli/commands/ref-parser.ts +10 -10
- package/src/cli/commands/reset.ts +40 -39
- package/src/cli/commands/search.ts +14 -13
- package/src/cli/commands/serve.ts +4 -4
- package/src/cli/commands/shared.ts +11 -10
- package/src/cli/commands/skill/index.ts +5 -5
- package/src/cli/commands/skill/install.ts +18 -17
- package/src/cli/commands/skill/paths-cmd.ts +11 -10
- package/src/cli/commands/skill/paths.ts +23 -23
- package/src/cli/commands/skill/show.ts +13 -12
- package/src/cli/commands/skill/uninstall.ts +16 -15
- package/src/cli/commands/status.ts +25 -24
- package/src/cli/commands/update.ts +3 -3
- package/src/cli/commands/vsearch.ts +17 -16
- package/src/cli/context.ts +5 -5
- package/src/cli/errors.ts +3 -3
- package/src/cli/format/search-results.ts +37 -37
- package/src/cli/options.ts +43 -43
- package/src/cli/program.ts +455 -459
- package/src/cli/progress.ts +1 -1
- package/src/cli/run.ts +24 -23
- package/src/collection/add.ts +9 -8
- package/src/collection/index.ts +3 -3
- package/src/collection/remove.ts +7 -6
- package/src/collection/types.ts +6 -6
- package/src/config/defaults.ts +1 -1
- package/src/config/index.ts +5 -5
- package/src/config/loader.ts +19 -18
- package/src/config/paths.ts +9 -8
- package/src/config/saver.ts +14 -13
- package/src/config/types.ts +53 -52
- package/src/converters/adapters/markitdownTs/adapter.ts +21 -19
- package/src/converters/adapters/officeparser/adapter.ts +18 -16
- package/src/converters/canonicalize.ts +12 -12
- package/src/converters/errors.ts +26 -22
- package/src/converters/index.ts +8 -8
- package/src/converters/mime.ts +25 -25
- package/src/converters/native/markdown.ts +10 -9
- package/src/converters/native/plaintext.ts +8 -7
- package/src/converters/path.ts +2 -2
- package/src/converters/pipeline.ts +11 -10
- package/src/converters/registry.ts +8 -8
- package/src/converters/types.ts +14 -14
- package/src/converters/versions.ts +4 -4
- package/src/index.ts +4 -4
- package/src/ingestion/chunker.ts +10 -9
- package/src/ingestion/index.ts +6 -6
- package/src/ingestion/language.ts +62 -62
- package/src/ingestion/sync.ts +50 -49
- package/src/ingestion/types.ts +10 -10
- package/src/ingestion/walker.ts +14 -13
- package/src/llm/cache.ts +51 -49
- package/src/llm/errors.ts +40 -36
- package/src/llm/index.ts +9 -9
- package/src/llm/lockfile.ts +6 -6
- package/src/llm/nodeLlamaCpp/adapter.ts +13 -12
- package/src/llm/nodeLlamaCpp/embedding.ts +9 -8
- package/src/llm/nodeLlamaCpp/generation.ts +7 -6
- package/src/llm/nodeLlamaCpp/lifecycle.ts +11 -10
- package/src/llm/nodeLlamaCpp/rerank.ts +6 -5
- package/src/llm/policy.ts +5 -5
- package/src/llm/registry.ts +6 -5
- package/src/llm/types.ts +2 -2
- package/src/mcp/resources/index.ts +15 -13
- package/src/mcp/server.ts +25 -23
- package/src/mcp/tools/get.ts +25 -23
- package/src/mcp/tools/index.ts +32 -29
- package/src/mcp/tools/multi-get.ts +34 -32
- package/src/mcp/tools/query.ts +29 -27
- package/src/mcp/tools/search.ts +14 -12
- package/src/mcp/tools/status.ts +12 -11
- package/src/mcp/tools/vsearch.ts +26 -24
- package/src/pipeline/answer.ts +9 -9
- package/src/pipeline/chunk-lookup.ts +1 -1
- package/src/pipeline/contextual.ts +4 -4
- package/src/pipeline/expansion.ts +23 -21
- package/src/pipeline/explain.ts +21 -21
- package/src/pipeline/fusion.ts +9 -9
- package/src/pipeline/hybrid.ts +41 -42
- package/src/pipeline/index.ts +10 -10
- package/src/pipeline/query-language.ts +39 -39
- package/src/pipeline/rerank.ts +8 -7
- package/src/pipeline/search.ts +22 -22
- package/src/pipeline/types.ts +8 -8
- package/src/pipeline/vsearch.ts +21 -24
- package/src/serve/CLAUDE.md +21 -15
- package/src/serve/config-sync.ts +9 -8
- package/src/serve/context.ts +19 -18
- package/src/serve/index.ts +1 -1
- package/src/serve/jobs.ts +7 -7
- package/src/serve/public/app.tsx +79 -25
- package/src/serve/public/components/AddCollectionDialog.tsx +382 -0
- package/src/serve/public/components/CaptureButton.tsx +60 -0
- package/src/serve/public/components/CaptureModal.tsx +365 -0
- package/src/serve/public/components/IndexingProgress.tsx +333 -0
- package/src/serve/public/components/ShortcutHelpModal.tsx +106 -0
- package/src/serve/public/components/ai-elements/code-block.tsx +42 -32
- package/src/serve/public/components/ai-elements/conversation.tsx +16 -14
- package/src/serve/public/components/ai-elements/inline-citation.tsx +33 -32
- package/src/serve/public/components/ai-elements/loader.tsx +5 -4
- package/src/serve/public/components/ai-elements/message.tsx +39 -37
- package/src/serve/public/components/ai-elements/prompt-input.tsx +97 -95
- package/src/serve/public/components/ai-elements/sources.tsx +12 -10
- package/src/serve/public/components/ai-elements/suggestion.tsx +10 -9
- package/src/serve/public/components/editor/CodeMirrorEditor.tsx +142 -0
- package/src/serve/public/components/editor/MarkdownPreview.tsx +311 -0
- package/src/serve/public/components/editor/index.ts +6 -0
- package/src/serve/public/components/preset-selector.tsx +29 -28
- package/src/serve/public/components/ui/badge.tsx +13 -12
- package/src/serve/public/components/ui/button-group.tsx +13 -12
- package/src/serve/public/components/ui/button.tsx +23 -22
- package/src/serve/public/components/ui/card.tsx +16 -16
- package/src/serve/public/components/ui/carousel.tsx +36 -35
- package/src/serve/public/components/ui/collapsible.tsx +1 -1
- package/src/serve/public/components/ui/command.tsx +17 -15
- package/src/serve/public/components/ui/dialog.tsx +13 -12
- package/src/serve/public/components/ui/dropdown-menu.tsx +13 -12
- package/src/serve/public/components/ui/hover-card.tsx +6 -5
- package/src/serve/public/components/ui/input-group.tsx +45 -43
- package/src/serve/public/components/ui/input.tsx +6 -6
- package/src/serve/public/components/ui/progress.tsx +5 -4
- package/src/serve/public/components/ui/scroll-area.tsx +11 -10
- package/src/serve/public/components/ui/select.tsx +19 -18
- package/src/serve/public/components/ui/separator.tsx +6 -5
- package/src/serve/public/components/ui/table.tsx +18 -18
- package/src/serve/public/components/ui/textarea.tsx +4 -4
- package/src/serve/public/components/ui/tooltip.tsx +5 -4
- package/src/serve/public/globals.css +27 -4
- package/src/serve/public/hooks/use-api.ts +8 -8
- package/src/serve/public/hooks/useCaptureModal.tsx +83 -0
- package/src/serve/public/hooks/useKeyboardShortcuts.ts +85 -0
- package/src/serve/public/index.html +4 -4
- package/src/serve/public/lib/utils.ts +6 -0
- package/src/serve/public/pages/Ask.tsx +27 -26
- package/src/serve/public/pages/Browse.tsx +28 -27
- package/src/serve/public/pages/Collections.tsx +439 -0
- package/src/serve/public/pages/Dashboard.tsx +166 -40
- package/src/serve/public/pages/DocView.tsx +258 -73
- package/src/serve/public/pages/DocumentEditor.tsx +510 -0
- package/src/serve/public/pages/Search.tsx +80 -58
- package/src/serve/routes/api.ts +272 -155
- package/src/serve/security.ts +4 -4
- package/src/serve/server.ts +66 -48
- package/src/store/index.ts +5 -5
- package/src/store/migrations/001-initial.ts +24 -23
- package/src/store/migrations/002-documents-fts.ts +7 -6
- package/src/store/migrations/index.ts +4 -4
- package/src/store/migrations/runner.ts +17 -15
- package/src/store/sqlite/adapter.ts +123 -121
- package/src/store/sqlite/fts5-snowball.ts +24 -23
- package/src/store/sqlite/index.ts +1 -1
- package/src/store/sqlite/setup.ts +12 -12
- package/src/store/sqlite/types.ts +4 -4
- package/src/store/types.ts +19 -19
- package/src/store/vector/index.ts +3 -3
- package/src/store/vector/sqlite-vec.ts +23 -20
- package/src/store/vector/stats.ts +10 -8
- package/src/store/vector/types.ts +2 -2
- package/vendor/fts5-snowball/README.md +6 -6
- package/assets/screenshots/webui-ask-answer.jpg +0 -0
- package/assets/screenshots/webui-home.jpg +0 -0
|
@@ -5,10 +5,11 @@ import {
|
|
|
5
5
|
Download,
|
|
6
6
|
Loader2,
|
|
7
7
|
SlidersHorizontal,
|
|
8
|
-
} from
|
|
9
|
-
import { useCallback, useEffect, useRef, useState } from
|
|
10
|
-
|
|
11
|
-
import {
|
|
8
|
+
} from "lucide-react";
|
|
9
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
10
|
+
|
|
11
|
+
import { apiFetch } from "../hooks/use-api";
|
|
12
|
+
import { Button } from "./ui/button";
|
|
12
13
|
import {
|
|
13
14
|
DropdownMenu,
|
|
14
15
|
DropdownMenuContent,
|
|
@@ -17,8 +18,8 @@ import {
|
|
|
17
18
|
DropdownMenuRadioItem,
|
|
18
19
|
DropdownMenuSeparator,
|
|
19
20
|
DropdownMenuTrigger,
|
|
20
|
-
} from
|
|
21
|
-
import { Progress } from
|
|
21
|
+
} from "./ui/dropdown-menu";
|
|
22
|
+
import { Progress } from "./ui/progress";
|
|
22
23
|
|
|
23
24
|
interface Preset {
|
|
24
25
|
id: string;
|
|
@@ -82,7 +83,7 @@ function extractDesc(name: string): string | null {
|
|
|
82
83
|
}
|
|
83
84
|
|
|
84
85
|
function extractBaseName(name: string): string {
|
|
85
|
-
return name.split(
|
|
86
|
+
return name.split("(")[0].trim();
|
|
86
87
|
}
|
|
87
88
|
|
|
88
89
|
function formatBytes(bytes: number): string {
|
|
@@ -123,17 +124,17 @@ function getButtonLabel(
|
|
|
123
124
|
activePreset: Preset | undefined
|
|
124
125
|
): string {
|
|
125
126
|
if (switching) {
|
|
126
|
-
return
|
|
127
|
+
return "Switching...";
|
|
127
128
|
}
|
|
128
129
|
if (downloading) {
|
|
129
|
-
return
|
|
130
|
+
return "Downloading...";
|
|
130
131
|
}
|
|
131
|
-
return activePreset ? extractBaseName(activePreset.name) :
|
|
132
|
+
return activePreset ? extractBaseName(activePreset.name) : "Preset";
|
|
132
133
|
}
|
|
133
134
|
|
|
134
135
|
export function PresetSelector() {
|
|
135
136
|
const [presets, setPresets] = useState<Preset[]>([]);
|
|
136
|
-
const [activeId, setActiveId] = useState<string>(
|
|
137
|
+
const [activeId, setActiveId] = useState<string>("");
|
|
137
138
|
const [loading, setLoading] = useState(true);
|
|
138
139
|
const [switching, setSwitching] = useState(false);
|
|
139
140
|
const [error, setError] = useState<string | null>(null);
|
|
@@ -150,14 +151,14 @@ export function PresetSelector() {
|
|
|
150
151
|
const checkCapabilities = useCallback((caps: Capabilities) => {
|
|
151
152
|
const missing: string[] = [];
|
|
152
153
|
if (!caps.vector) {
|
|
153
|
-
missing.push(
|
|
154
|
+
missing.push("vector search");
|
|
154
155
|
}
|
|
155
156
|
if (!caps.answer) {
|
|
156
|
-
missing.push(
|
|
157
|
+
missing.push("AI answers");
|
|
157
158
|
}
|
|
158
159
|
|
|
159
160
|
if (missing.length > 0) {
|
|
160
|
-
setError(`Missing: ${missing.join(
|
|
161
|
+
setError(`Missing: ${missing.join(", ")}`);
|
|
161
162
|
setModelsNeeded(true);
|
|
162
163
|
} else {
|
|
163
164
|
setError(null);
|
|
@@ -167,7 +168,7 @@ export function PresetSelector() {
|
|
|
167
168
|
|
|
168
169
|
// Poll download status
|
|
169
170
|
const pollStatus = useCallback(async () => {
|
|
170
|
-
const { data } = await apiFetch<DownloadStatus>(
|
|
171
|
+
const { data } = await apiFetch<DownloadStatus>("/api/models/status");
|
|
171
172
|
if (data) {
|
|
172
173
|
setDownloadStatus(data);
|
|
173
174
|
|
|
@@ -181,14 +182,14 @@ export function PresetSelector() {
|
|
|
181
182
|
|
|
182
183
|
// Refresh presets to get updated capabilities
|
|
183
184
|
const { data: presetsData } =
|
|
184
|
-
await apiFetch<PresetsResponse>(
|
|
185
|
+
await apiFetch<PresetsResponse>("/api/presets");
|
|
185
186
|
if (presetsData) {
|
|
186
187
|
checkCapabilities(presetsData.capabilities);
|
|
187
188
|
}
|
|
188
189
|
|
|
189
190
|
// Show any failures
|
|
190
191
|
if (data.failed.length > 0) {
|
|
191
|
-
setError(`Failed: ${data.failed.map((f) => f.type).join(
|
|
192
|
+
setError(`Failed: ${data.failed.map((f) => f.type).join(", ")}`);
|
|
192
193
|
}
|
|
193
194
|
}
|
|
194
195
|
}
|
|
@@ -196,7 +197,7 @@ export function PresetSelector() {
|
|
|
196
197
|
|
|
197
198
|
// Initial load
|
|
198
199
|
useEffect(() => {
|
|
199
|
-
apiFetch<PresetsResponse>(
|
|
200
|
+
void apiFetch<PresetsResponse>("/api/presets").then(({ data }) => {
|
|
200
201
|
if (data) {
|
|
201
202
|
setPresets(data.presets);
|
|
202
203
|
setActiveId(data.activePreset);
|
|
@@ -206,7 +207,7 @@ export function PresetSelector() {
|
|
|
206
207
|
});
|
|
207
208
|
|
|
208
209
|
// Check if download already in progress
|
|
209
|
-
apiFetch<DownloadStatus>(
|
|
210
|
+
void apiFetch<DownloadStatus>("/api/models/status").then(({ data }) => {
|
|
210
211
|
if (data?.active) {
|
|
211
212
|
setDownloading(true);
|
|
212
213
|
setDownloadStatus(data);
|
|
@@ -242,10 +243,10 @@ export function PresetSelector() {
|
|
|
242
243
|
setError(null);
|
|
243
244
|
|
|
244
245
|
const { data, error: fetchError } = await apiFetch<SetPresetResponse>(
|
|
245
|
-
|
|
246
|
+
"/api/presets",
|
|
246
247
|
{
|
|
247
|
-
method:
|
|
248
|
-
headers: {
|
|
248
|
+
method: "POST",
|
|
249
|
+
headers: { "Content-Type": "application/json" },
|
|
249
250
|
body: JSON.stringify({ presetId: id }),
|
|
250
251
|
}
|
|
251
252
|
);
|
|
@@ -271,8 +272,8 @@ export function PresetSelector() {
|
|
|
271
272
|
setDownloading(true);
|
|
272
273
|
setError(null);
|
|
273
274
|
|
|
274
|
-
const { error: fetchError } = await apiFetch(
|
|
275
|
-
method:
|
|
275
|
+
const { error: fetchError } = await apiFetch("/api/models/pull", {
|
|
276
|
+
method: "POST",
|
|
276
277
|
});
|
|
277
278
|
|
|
278
279
|
if (fetchError) {
|
|
@@ -282,7 +283,7 @@ export function PresetSelector() {
|
|
|
282
283
|
}
|
|
283
284
|
|
|
284
285
|
// Start polling
|
|
285
|
-
pollStatus();
|
|
286
|
+
void pollStatus();
|
|
286
287
|
};
|
|
287
288
|
|
|
288
289
|
return (
|
|
@@ -317,11 +318,11 @@ export function PresetSelector() {
|
|
|
317
318
|
<div className="space-y-2 px-2 py-2">
|
|
318
319
|
<div className="flex items-center justify-between text-xs">
|
|
319
320
|
<span className="text-muted-foreground">
|
|
320
|
-
{downloadStatus.currentType ||
|
|
321
|
+
{downloadStatus.currentType || "Starting..."}
|
|
321
322
|
</span>
|
|
322
323
|
{downloadStatus.progress && (
|
|
323
324
|
<span className="font-mono text-[10px] text-muted-foreground">
|
|
324
|
-
{formatBytes(downloadStatus.progress.downloadedBytes)} /{
|
|
325
|
+
{formatBytes(downloadStatus.progress.downloadedBytes)} /{" "}
|
|
325
326
|
{formatBytes(downloadStatus.progress.totalBytes)}
|
|
326
327
|
</span>
|
|
327
328
|
)}
|
|
@@ -329,7 +330,7 @@ export function PresetSelector() {
|
|
|
329
330
|
<Progress value={downloadStatus.progress?.percent ?? 0} />
|
|
330
331
|
{downloadStatus.completed.length > 0 && (
|
|
331
332
|
<div className="text-[10px] text-muted-foreground">
|
|
332
|
-
Done: {downloadStatus.completed.join(
|
|
333
|
+
Done: {downloadStatus.completed.join(", ")}
|
|
333
334
|
</div>
|
|
334
335
|
)}
|
|
335
336
|
</div>
|
|
@@ -1,26 +1,27 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { cva, type VariantProps } from 'class-variance-authority';
|
|
3
|
-
import type * as React from 'react';
|
|
1
|
+
import type * as React from "react";
|
|
4
2
|
|
|
5
|
-
import {
|
|
3
|
+
import { Slot } from "@radix-ui/react-slot";
|
|
4
|
+
import { cva, type VariantProps } from "class-variance-authority";
|
|
5
|
+
|
|
6
|
+
import { cn } from "../../lib/utils";
|
|
6
7
|
|
|
7
8
|
const badgeVariants = cva(
|
|
8
|
-
|
|
9
|
+
"inline-flex w-fit shrink-0 items-center justify-center gap-1 overflow-hidden whitespace-nowrap rounded-full border px-2 py-0.5 font-medium text-xs transition-[color,box-shadow] focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&>svg]:pointer-events-none [&>svg]:size-3",
|
|
9
10
|
{
|
|
10
11
|
variants: {
|
|
11
12
|
variant: {
|
|
12
13
|
default:
|
|
13
|
-
|
|
14
|
+
"border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90",
|
|
14
15
|
secondary:
|
|
15
|
-
|
|
16
|
+
"border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90",
|
|
16
17
|
destructive:
|
|
17
|
-
|
|
18
|
+
"border-transparent bg-destructive text-white focus-visible:ring-destructive/20 dark:bg-destructive/60 dark:focus-visible:ring-destructive/40 [a&]:hover:bg-destructive/90",
|
|
18
19
|
outline:
|
|
19
|
-
|
|
20
|
+
"text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground",
|
|
20
21
|
},
|
|
21
22
|
},
|
|
22
23
|
defaultVariants: {
|
|
23
|
-
variant:
|
|
24
|
+
variant: "default",
|
|
24
25
|
},
|
|
25
26
|
}
|
|
26
27
|
);
|
|
@@ -30,9 +31,9 @@ function Badge({
|
|
|
30
31
|
variant,
|
|
31
32
|
asChild = false,
|
|
32
33
|
...props
|
|
33
|
-
}: React.ComponentProps<
|
|
34
|
+
}: React.ComponentProps<"span"> &
|
|
34
35
|
VariantProps<typeof badgeVariants> & { asChild?: boolean }) {
|
|
35
|
-
const Comp = asChild ? Slot :
|
|
36
|
+
const Comp = asChild ? Slot : "span";
|
|
36
37
|
|
|
37
38
|
return (
|
|
38
39
|
<Comp
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { Slot } from
|
|
2
|
-
import { cva, type VariantProps } from
|
|
3
|
-
|
|
4
|
-
import {
|
|
1
|
+
import { Slot } from "@radix-ui/react-slot";
|
|
2
|
+
import { cva, type VariantProps } from "class-variance-authority";
|
|
3
|
+
|
|
4
|
+
import { cn } from "../../lib/utils";
|
|
5
|
+
import { Separator } from "./separator";
|
|
5
6
|
|
|
6
7
|
const buttonGroupVariants = cva(
|
|
7
8
|
"flex w-fit items-stretch has-[>[data-slot=button-group]]:gap-2 [&>*]:focus-visible:relative [&>*]:focus-visible:z-10 has-[select[aria-hidden=true]:last-child]:[&>[data-slot=select-trigger]:last-of-type]:rounded-r-md [&>[data-slot=select-trigger]:not([class*='w-'])]:w-fit [&>input]:flex-1",
|
|
@@ -9,13 +10,13 @@ const buttonGroupVariants = cva(
|
|
|
9
10
|
variants: {
|
|
10
11
|
orientation: {
|
|
11
12
|
horizontal:
|
|
12
|
-
|
|
13
|
+
"[&>*:not(:first-child)]:rounded-l-none [&>*:not(:first-child)]:border-l-0 [&>*:not(:last-child)]:rounded-r-none",
|
|
13
14
|
vertical:
|
|
14
|
-
|
|
15
|
+
"flex-col [&>*:not(:first-child)]:rounded-t-none [&>*:not(:first-child)]:border-t-0 [&>*:not(:last-child)]:rounded-b-none",
|
|
15
16
|
},
|
|
16
17
|
},
|
|
17
18
|
defaultVariants: {
|
|
18
|
-
orientation:
|
|
19
|
+
orientation: "horizontal",
|
|
19
20
|
},
|
|
20
21
|
}
|
|
21
22
|
);
|
|
@@ -24,7 +25,7 @@ function ButtonGroup({
|
|
|
24
25
|
className,
|
|
25
26
|
orientation,
|
|
26
27
|
...props
|
|
27
|
-
}: React.ComponentProps<
|
|
28
|
+
}: React.ComponentProps<"div"> & VariantProps<typeof buttonGroupVariants>) {
|
|
28
29
|
return (
|
|
29
30
|
<div
|
|
30
31
|
className={cn(buttonGroupVariants({ orientation }), className)}
|
|
@@ -40,10 +41,10 @@ function ButtonGroupText({
|
|
|
40
41
|
className,
|
|
41
42
|
asChild = false,
|
|
42
43
|
...props
|
|
43
|
-
}: React.ComponentProps<
|
|
44
|
+
}: React.ComponentProps<"div"> & {
|
|
44
45
|
asChild?: boolean;
|
|
45
46
|
}) {
|
|
46
|
-
const Comp = asChild ? Slot :
|
|
47
|
+
const Comp = asChild ? Slot : "div";
|
|
47
48
|
|
|
48
49
|
return (
|
|
49
50
|
<Comp
|
|
@@ -58,13 +59,13 @@ function ButtonGroupText({
|
|
|
58
59
|
|
|
59
60
|
function ButtonGroupSeparator({
|
|
60
61
|
className,
|
|
61
|
-
orientation =
|
|
62
|
+
orientation = "vertical",
|
|
62
63
|
...props
|
|
63
64
|
}: React.ComponentProps<typeof Separator>) {
|
|
64
65
|
return (
|
|
65
66
|
<Separator
|
|
66
67
|
className={cn(
|
|
67
|
-
|
|
68
|
+
"!m-0 relative self-stretch bg-input data-[orientation=vertical]:h-auto",
|
|
68
69
|
className
|
|
69
70
|
)}
|
|
70
71
|
data-slot="button-group-separator"
|
|
@@ -1,52 +1,53 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { cva, type VariantProps } from 'class-variance-authority';
|
|
3
|
-
import type * as React from 'react';
|
|
1
|
+
import type * as React from "react";
|
|
4
2
|
|
|
5
|
-
import {
|
|
3
|
+
import { Slot } from "@radix-ui/react-slot";
|
|
4
|
+
import { cva, type VariantProps } from "class-variance-authority";
|
|
5
|
+
|
|
6
|
+
import { cn } from "../../lib/utils";
|
|
6
7
|
|
|
7
8
|
const buttonVariants = cva(
|
|
8
9
|
"inline-flex shrink-0 items-center justify-center gap-2 whitespace-nowrap rounded-md font-medium text-sm outline-none transition-all focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0",
|
|
9
10
|
{
|
|
10
11
|
variants: {
|
|
11
12
|
variant: {
|
|
12
|
-
default:
|
|
13
|
+
default: "bg-primary text-primary-foreground hover:bg-primary/90",
|
|
13
14
|
destructive:
|
|
14
|
-
|
|
15
|
+
"bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:bg-destructive/60 dark:focus-visible:ring-destructive/40",
|
|
15
16
|
outline:
|
|
16
|
-
|
|
17
|
+
"border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50",
|
|
17
18
|
secondary:
|
|
18
|
-
|
|
19
|
+
"bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
|
19
20
|
ghost:
|
|
20
|
-
|
|
21
|
-
link:
|
|
21
|
+
"hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
|
|
22
|
+
link: "text-primary underline-offset-4 hover:underline",
|
|
22
23
|
},
|
|
23
24
|
size: {
|
|
24
|
-
default:
|
|
25
|
-
sm:
|
|
26
|
-
lg:
|
|
27
|
-
icon:
|
|
28
|
-
|
|
29
|
-
|
|
25
|
+
default: "h-9 px-4 py-2 has-[>svg]:px-3",
|
|
26
|
+
sm: "h-8 gap-1.5 rounded-md px-3 has-[>svg]:px-2.5",
|
|
27
|
+
lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
|
|
28
|
+
icon: "size-9",
|
|
29
|
+
"icon-sm": "size-8",
|
|
30
|
+
"icon-lg": "size-10",
|
|
30
31
|
},
|
|
31
32
|
},
|
|
32
33
|
defaultVariants: {
|
|
33
|
-
variant:
|
|
34
|
-
size:
|
|
34
|
+
variant: "default",
|
|
35
|
+
size: "default",
|
|
35
36
|
},
|
|
36
37
|
}
|
|
37
38
|
);
|
|
38
39
|
|
|
39
40
|
function Button({
|
|
40
41
|
className,
|
|
41
|
-
variant =
|
|
42
|
-
size =
|
|
42
|
+
variant = "default",
|
|
43
|
+
size = "default",
|
|
43
44
|
asChild = false,
|
|
44
45
|
...props
|
|
45
|
-
}: React.ComponentProps<
|
|
46
|
+
}: React.ComponentProps<"button"> &
|
|
46
47
|
VariantProps<typeof buttonVariants> & {
|
|
47
48
|
asChild?: boolean;
|
|
48
49
|
}) {
|
|
49
|
-
const Comp = asChild ? Slot :
|
|
50
|
+
const Comp = asChild ? Slot : "button";
|
|
50
51
|
|
|
51
52
|
return (
|
|
52
53
|
<Comp
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import type * as React from
|
|
1
|
+
import type * as React from "react";
|
|
2
2
|
|
|
3
|
-
import { cn } from
|
|
3
|
+
import { cn } from "../../lib/utils";
|
|
4
4
|
|
|
5
|
-
function Card({ className, ...props }: React.ComponentProps<
|
|
5
|
+
function Card({ className, ...props }: React.ComponentProps<"div">) {
|
|
6
6
|
return (
|
|
7
7
|
<div
|
|
8
8
|
className={cn(
|
|
9
|
-
|
|
9
|
+
"flex flex-col gap-6 rounded-xl border bg-card py-6 text-card-foreground shadow-sm",
|
|
10
10
|
className
|
|
11
11
|
)}
|
|
12
12
|
data-slot="card"
|
|
@@ -15,11 +15,11 @@ function Card({ className, ...props }: React.ComponentProps<'div'>) {
|
|
|
15
15
|
);
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
function CardHeader({ className, ...props }: React.ComponentProps<
|
|
18
|
+
function CardHeader({ className, ...props }: React.ComponentProps<"div">) {
|
|
19
19
|
return (
|
|
20
20
|
<div
|
|
21
21
|
className={cn(
|
|
22
|
-
|
|
22
|
+
"@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-2 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6",
|
|
23
23
|
className
|
|
24
24
|
)}
|
|
25
25
|
data-slot="card-header"
|
|
@@ -28,31 +28,31 @@ function CardHeader({ className, ...props }: React.ComponentProps<'div'>) {
|
|
|
28
28
|
);
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
function CardTitle({ className, ...props }: React.ComponentProps<
|
|
31
|
+
function CardTitle({ className, ...props }: React.ComponentProps<"div">) {
|
|
32
32
|
return (
|
|
33
33
|
<div
|
|
34
|
-
className={cn(
|
|
34
|
+
className={cn("font-semibold leading-none", className)}
|
|
35
35
|
data-slot="card-title"
|
|
36
36
|
{...props}
|
|
37
37
|
/>
|
|
38
38
|
);
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
function CardDescription({ className, ...props }: React.ComponentProps<
|
|
41
|
+
function CardDescription({ className, ...props }: React.ComponentProps<"div">) {
|
|
42
42
|
return (
|
|
43
43
|
<div
|
|
44
|
-
className={cn(
|
|
44
|
+
className={cn("text-muted-foreground text-sm", className)}
|
|
45
45
|
data-slot="card-description"
|
|
46
46
|
{...props}
|
|
47
47
|
/>
|
|
48
48
|
);
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
-
function CardAction({ className, ...props }: React.ComponentProps<
|
|
51
|
+
function CardAction({ className, ...props }: React.ComponentProps<"div">) {
|
|
52
52
|
return (
|
|
53
53
|
<div
|
|
54
54
|
className={cn(
|
|
55
|
-
|
|
55
|
+
"col-start-2 row-span-2 row-start-1 self-start justify-self-end",
|
|
56
56
|
className
|
|
57
57
|
)}
|
|
58
58
|
data-slot="card-action"
|
|
@@ -61,20 +61,20 @@ function CardAction({ className, ...props }: React.ComponentProps<'div'>) {
|
|
|
61
61
|
);
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
-
function CardContent({ className, ...props }: React.ComponentProps<
|
|
64
|
+
function CardContent({ className, ...props }: React.ComponentProps<"div">) {
|
|
65
65
|
return (
|
|
66
66
|
<div
|
|
67
|
-
className={cn(
|
|
67
|
+
className={cn("px-6", className)}
|
|
68
68
|
data-slot="card-content"
|
|
69
69
|
{...props}
|
|
70
70
|
/>
|
|
71
71
|
);
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
-
function CardFooter({ className, ...props }: React.ComponentProps<
|
|
74
|
+
function CardFooter({ className, ...props }: React.ComponentProps<"div">) {
|
|
75
75
|
return (
|
|
76
76
|
<div
|
|
77
|
-
className={cn(
|
|
77
|
+
className={cn("flex items-center px-6 [.border-t]:pt-6", className)}
|
|
78
78
|
data-slot="card-footer"
|
|
79
79
|
{...props}
|
|
80
80
|
/>
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import useEmblaCarousel, {
|
|
2
2
|
type UseEmblaCarouselType,
|
|
3
|
-
} from
|
|
4
|
-
import { ArrowLeft, ArrowRight } from
|
|
5
|
-
import * as React from
|
|
6
|
-
|
|
7
|
-
import {
|
|
3
|
+
} from "embla-carousel-react";
|
|
4
|
+
import { ArrowLeft, ArrowRight } from "lucide-react";
|
|
5
|
+
import * as React from "react";
|
|
6
|
+
|
|
7
|
+
import { cn } from "../../lib/utils";
|
|
8
|
+
import { Button } from "./button";
|
|
8
9
|
|
|
9
10
|
type CarouselApi = UseEmblaCarouselType[1];
|
|
10
11
|
type UseCarouselParameters = Parameters<typeof useEmblaCarousel>;
|
|
@@ -14,7 +15,7 @@ type CarouselPlugin = UseCarouselParameters[1];
|
|
|
14
15
|
interface CarouselProps {
|
|
15
16
|
opts?: CarouselOptions;
|
|
16
17
|
plugins?: CarouselPlugin;
|
|
17
|
-
orientation?:
|
|
18
|
+
orientation?: "horizontal" | "vertical";
|
|
18
19
|
setApi?: (api: CarouselApi) => void;
|
|
19
20
|
}
|
|
20
21
|
|
|
@@ -33,25 +34,25 @@ function useCarousel() {
|
|
|
33
34
|
const context = React.useContext(CarouselContext);
|
|
34
35
|
|
|
35
36
|
if (!context) {
|
|
36
|
-
throw new Error(
|
|
37
|
+
throw new Error("useCarousel must be used within a <Carousel />");
|
|
37
38
|
}
|
|
38
39
|
|
|
39
40
|
return context;
|
|
40
41
|
}
|
|
41
42
|
|
|
42
43
|
function Carousel({
|
|
43
|
-
orientation =
|
|
44
|
+
orientation = "horizontal",
|
|
44
45
|
opts,
|
|
45
46
|
setApi,
|
|
46
47
|
plugins,
|
|
47
48
|
className,
|
|
48
49
|
children,
|
|
49
50
|
...props
|
|
50
|
-
}: React.ComponentProps<
|
|
51
|
+
}: React.ComponentProps<"div"> & CarouselProps) {
|
|
51
52
|
const [carouselRef, api] = useEmblaCarousel(
|
|
52
53
|
{
|
|
53
54
|
...opts,
|
|
54
|
-
axis: orientation ===
|
|
55
|
+
axis: orientation === "horizontal" ? "x" : "y",
|
|
55
56
|
},
|
|
56
57
|
plugins
|
|
57
58
|
);
|
|
@@ -76,10 +77,10 @@ function Carousel({
|
|
|
76
77
|
|
|
77
78
|
const handleKeyDown = React.useCallback(
|
|
78
79
|
(event: React.KeyboardEvent<HTMLDivElement>) => {
|
|
79
|
-
if (event.key ===
|
|
80
|
+
if (event.key === "ArrowLeft") {
|
|
80
81
|
event.preventDefault();
|
|
81
82
|
scrollPrev();
|
|
82
|
-
} else if (event.key ===
|
|
83
|
+
} else if (event.key === "ArrowRight") {
|
|
83
84
|
event.preventDefault();
|
|
84
85
|
scrollNext();
|
|
85
86
|
}
|
|
@@ -99,11 +100,11 @@ function Carousel({
|
|
|
99
100
|
return;
|
|
100
101
|
}
|
|
101
102
|
onSelect(api);
|
|
102
|
-
api.on(
|
|
103
|
-
api.on(
|
|
103
|
+
api.on("reInit", onSelect);
|
|
104
|
+
api.on("select", onSelect);
|
|
104
105
|
|
|
105
106
|
return () => {
|
|
106
|
-
api?.off(
|
|
107
|
+
api?.off("select", onSelect);
|
|
107
108
|
};
|
|
108
109
|
}, [api, onSelect]);
|
|
109
110
|
|
|
@@ -114,7 +115,7 @@ function Carousel({
|
|
|
114
115
|
api,
|
|
115
116
|
opts,
|
|
116
117
|
orientation:
|
|
117
|
-
orientation || (opts?.axis ===
|
|
118
|
+
orientation || (opts?.axis === "y" ? "vertical" : "horizontal"),
|
|
118
119
|
scrollPrev,
|
|
119
120
|
scrollNext,
|
|
120
121
|
canScrollPrev,
|
|
@@ -123,7 +124,7 @@ function Carousel({
|
|
|
123
124
|
>
|
|
124
125
|
<div
|
|
125
126
|
aria-roledescription="carousel"
|
|
126
|
-
className={cn(
|
|
127
|
+
className={cn("relative", className)}
|
|
127
128
|
data-slot="carousel"
|
|
128
129
|
onKeyDownCapture={handleKeyDown}
|
|
129
130
|
role="region"
|
|
@@ -135,7 +136,7 @@ function Carousel({
|
|
|
135
136
|
);
|
|
136
137
|
}
|
|
137
138
|
|
|
138
|
-
function CarouselContent({ className, ...props }: React.ComponentProps<
|
|
139
|
+
function CarouselContent({ className, ...props }: React.ComponentProps<"div">) {
|
|
139
140
|
const { carouselRef, orientation } = useCarousel();
|
|
140
141
|
|
|
141
142
|
return (
|
|
@@ -146,8 +147,8 @@ function CarouselContent({ className, ...props }: React.ComponentProps<'div'>) {
|
|
|
146
147
|
>
|
|
147
148
|
<div
|
|
148
149
|
className={cn(
|
|
149
|
-
|
|
150
|
-
orientation ===
|
|
150
|
+
"flex",
|
|
151
|
+
orientation === "horizontal" ? "-ml-4" : "-mt-4 flex-col",
|
|
151
152
|
className
|
|
152
153
|
)}
|
|
153
154
|
{...props}
|
|
@@ -156,15 +157,15 @@ function CarouselContent({ className, ...props }: React.ComponentProps<'div'>) {
|
|
|
156
157
|
);
|
|
157
158
|
}
|
|
158
159
|
|
|
159
|
-
function CarouselItem({ className, ...props }: React.ComponentProps<
|
|
160
|
+
function CarouselItem({ className, ...props }: React.ComponentProps<"div">) {
|
|
160
161
|
const { orientation } = useCarousel();
|
|
161
162
|
|
|
162
163
|
return (
|
|
163
164
|
<div
|
|
164
165
|
aria-roledescription="slide"
|
|
165
166
|
className={cn(
|
|
166
|
-
|
|
167
|
-
orientation ===
|
|
167
|
+
"min-w-0 shrink-0 grow-0 basis-full",
|
|
168
|
+
orientation === "horizontal" ? "pl-4" : "pt-4",
|
|
168
169
|
className
|
|
169
170
|
)}
|
|
170
171
|
data-slot="carousel-item"
|
|
@@ -176,8 +177,8 @@ function CarouselItem({ className, ...props }: React.ComponentProps<'div'>) {
|
|
|
176
177
|
|
|
177
178
|
function CarouselPrevious({
|
|
178
179
|
className,
|
|
179
|
-
variant =
|
|
180
|
-
size =
|
|
180
|
+
variant = "outline",
|
|
181
|
+
size = "icon",
|
|
181
182
|
...props
|
|
182
183
|
}: React.ComponentProps<typeof Button>) {
|
|
183
184
|
const { orientation, scrollPrev, canScrollPrev } = useCarousel();
|
|
@@ -185,10 +186,10 @@ function CarouselPrevious({
|
|
|
185
186
|
return (
|
|
186
187
|
<Button
|
|
187
188
|
className={cn(
|
|
188
|
-
|
|
189
|
-
orientation ===
|
|
190
|
-
?
|
|
191
|
-
:
|
|
189
|
+
"absolute size-8 rounded-full",
|
|
190
|
+
orientation === "horizontal"
|
|
191
|
+
? "top-1/2 -left-12 -translate-y-1/2"
|
|
192
|
+
: "-top-12 left-1/2 -translate-x-1/2 rotate-90",
|
|
192
193
|
className
|
|
193
194
|
)}
|
|
194
195
|
data-slot="carousel-previous"
|
|
@@ -206,8 +207,8 @@ function CarouselPrevious({
|
|
|
206
207
|
|
|
207
208
|
function CarouselNext({
|
|
208
209
|
className,
|
|
209
|
-
variant =
|
|
210
|
-
size =
|
|
210
|
+
variant = "outline",
|
|
211
|
+
size = "icon",
|
|
211
212
|
...props
|
|
212
213
|
}: React.ComponentProps<typeof Button>) {
|
|
213
214
|
const { orientation, scrollNext, canScrollNext } = useCarousel();
|
|
@@ -215,10 +216,10 @@ function CarouselNext({
|
|
|
215
216
|
return (
|
|
216
217
|
<Button
|
|
217
218
|
className={cn(
|
|
218
|
-
|
|
219
|
-
orientation ===
|
|
220
|
-
?
|
|
221
|
-
:
|
|
219
|
+
"absolute size-8 rounded-full",
|
|
220
|
+
orientation === "horizontal"
|
|
221
|
+
? "top-1/2 -right-12 -translate-y-1/2"
|
|
222
|
+
: "-bottom-12 left-1/2 -translate-x-1/2 rotate-90",
|
|
222
223
|
className
|
|
223
224
|
)}
|
|
224
225
|
data-slot="carousel-next"
|