@tollerud/ui 1.1.5 → 3.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/AGENTS.md +36 -13
- package/CHANGELOG.md +411 -0
- package/COMPONENTS.md +951 -0
- package/GETTING_STARTED.md +159 -0
- package/README.md +51 -43
- package/SKILL.md +59 -24
- package/components.json +18 -0
- package/dist/accordion.d.ts +20 -0
- package/dist/accordion.js +5 -0
- package/dist/accordion.js.map +1 -0
- package/dist/action-diff.d.ts +26 -0
- package/dist/action-diff.js +5 -0
- package/dist/action-diff.js.map +1 -0
- package/dist/action-row.d.ts +36 -0
- package/dist/action-row.js +6 -0
- package/dist/action-row.js.map +1 -0
- package/dist/alert-inbox.d.ts +23 -0
- package/dist/alert-inbox.js +6 -0
- package/dist/alert-inbox.js.map +1 -0
- package/dist/alert.d.ts +33 -0
- package/dist/alert.js +5 -0
- package/dist/alert.js.map +1 -0
- package/dist/approval-card.d.ts +27 -0
- package/dist/approval-card.js +5 -0
- package/dist/approval-card.js.map +1 -0
- package/dist/area-chart.d.ts +10 -0
- package/dist/area-chart.js +5 -0
- package/dist/area-chart.js.map +1 -0
- package/dist/avatar.d.ts +28 -0
- package/dist/avatar.js +5 -0
- package/dist/avatar.js.map +1 -0
- package/dist/backup-status-panel.d.ts +25 -0
- package/dist/backup-status-panel.js +6 -0
- package/dist/backup-status-panel.js.map +1 -0
- package/dist/badge.d.ts +17 -0
- package/dist/badge.js +5 -0
- package/dist/badge.js.map +1 -0
- package/dist/bar-chart.d.ts +15 -0
- package/dist/bar-chart.js +5 -0
- package/dist/bar-chart.js.map +1 -0
- package/dist/bento-dashboard.d.ts +30 -0
- package/dist/bento-dashboard.js +10 -0
- package/dist/bento-dashboard.js.map +1 -0
- package/dist/breadcrumb.d.ts +16 -0
- package/dist/breadcrumb.js +5 -0
- package/dist/breadcrumb.js.map +1 -0
- package/dist/button.d.ts +29 -0
- package/dist/button.js +5 -0
- package/dist/button.js.map +1 -0
- package/dist/card.d.ts +10 -0
- package/dist/card.js +5 -0
- package/dist/card.js.map +1 -0
- package/dist/checkbox.d.ts +9 -0
- package/dist/checkbox.js +5 -0
- package/dist/checkbox.js.map +1 -0
- package/dist/chunk-2QWKOCWF.js +79 -0
- package/dist/chunk-2QWKOCWF.js.map +1 -0
- package/dist/chunk-3LTW224O.js +53 -0
- package/dist/chunk-3LTW224O.js.map +1 -0
- package/dist/chunk-3XTZPDNV.js +94 -0
- package/dist/chunk-3XTZPDNV.js.map +1 -0
- package/dist/chunk-435JHF7G.js +65 -0
- package/dist/chunk-435JHF7G.js.map +1 -0
- package/dist/chunk-4PA2ACNF.js +52 -0
- package/dist/chunk-4PA2ACNF.js.map +1 -0
- package/dist/chunk-5GWHUJ5D.js +29 -0
- package/dist/chunk-5GWHUJ5D.js.map +1 -0
- package/dist/chunk-6FUKJD3W.js +123 -0
- package/dist/chunk-6FUKJD3W.js.map +1 -0
- package/dist/chunk-6IS2AYYG.js +106 -0
- package/dist/chunk-6IS2AYYG.js.map +1 -0
- package/dist/chunk-6PZKU6ZL.js +78 -0
- package/dist/chunk-6PZKU6ZL.js.map +1 -0
- package/dist/chunk-6SKTH45H.js +75 -0
- package/dist/chunk-6SKTH45H.js.map +1 -0
- package/dist/chunk-6UXW5YUC.js +77 -0
- package/dist/chunk-6UXW5YUC.js.map +1 -0
- package/dist/chunk-7EP2T3OW.js +52 -0
- package/dist/chunk-7EP2T3OW.js.map +1 -0
- package/dist/chunk-7J5QXUQN.js +38 -0
- package/dist/chunk-7J5QXUQN.js.map +1 -0
- package/dist/chunk-A6L5C3IJ.js +47 -0
- package/dist/chunk-A6L5C3IJ.js.map +1 -0
- package/dist/chunk-ADE22JSR.js +54 -0
- package/dist/chunk-ADE22JSR.js.map +1 -0
- package/dist/chunk-ANW6J6PV.js +42 -0
- package/dist/chunk-ANW6J6PV.js.map +1 -0
- package/dist/chunk-APFFKNPS.js +80 -0
- package/dist/chunk-APFFKNPS.js.map +1 -0
- package/dist/chunk-AQT3FZRQ.js +23 -0
- package/dist/chunk-AQT3FZRQ.js.map +1 -0
- package/dist/chunk-AZADSX4Z.js +85 -0
- package/dist/chunk-AZADSX4Z.js.map +1 -0
- package/dist/chunk-BPCH5LJ3.js +36 -0
- package/dist/chunk-BPCH5LJ3.js.map +1 -0
- package/dist/chunk-CDI7353B.js +40 -0
- package/dist/chunk-CDI7353B.js.map +1 -0
- package/dist/chunk-CKNWXYMA.js +53 -0
- package/dist/chunk-CKNWXYMA.js.map +1 -0
- package/dist/chunk-DNJI65VQ.js +22 -0
- package/dist/chunk-DNJI65VQ.js.map +1 -0
- package/dist/chunk-DOUDJU4P.js +63 -0
- package/dist/chunk-DOUDJU4P.js.map +1 -0
- package/dist/chunk-DRCMGIQ6.js +64 -0
- package/dist/chunk-DRCMGIQ6.js.map +1 -0
- package/dist/chunk-DZOBXK2S.js +28 -0
- package/dist/chunk-DZOBXK2S.js.map +1 -0
- package/dist/chunk-EN4OJCEF.js +54 -0
- package/dist/chunk-EN4OJCEF.js.map +1 -0
- package/dist/chunk-EVHZFYWX.js +33 -0
- package/dist/chunk-EVHZFYWX.js.map +1 -0
- package/dist/chunk-G2VKWNZA.js +53 -0
- package/dist/chunk-G2VKWNZA.js.map +1 -0
- package/dist/chunk-GTM2DE4C.js +156 -0
- package/dist/chunk-GTM2DE4C.js.map +1 -0
- package/dist/chunk-H3ZVGTJM.js +165 -0
- package/dist/chunk-H3ZVGTJM.js.map +1 -0
- package/dist/chunk-HWAWUEHC.js +28 -0
- package/dist/chunk-HWAWUEHC.js.map +1 -0
- package/dist/chunk-HWJVRTWO.js +36 -0
- package/dist/chunk-HWJVRTWO.js.map +1 -0
- package/dist/chunk-ILADNTUB.js +77 -0
- package/dist/chunk-ILADNTUB.js.map +1 -0
- package/dist/chunk-IUPVQWO5.js +31 -0
- package/dist/chunk-IUPVQWO5.js.map +1 -0
- package/dist/chunk-JFOW2DI5.js +43 -0
- package/dist/chunk-JFOW2DI5.js.map +1 -0
- package/dist/chunk-JRFSUVSO.js +66 -0
- package/dist/chunk-JRFSUVSO.js.map +1 -0
- package/dist/chunk-KI6OTVID.js +91 -0
- package/dist/chunk-KI6OTVID.js.map +1 -0
- package/dist/chunk-LUM2YJBH.js +73 -0
- package/dist/chunk-LUM2YJBH.js.map +1 -0
- package/dist/chunk-NHPISZWS.js +71 -0
- package/dist/chunk-NHPISZWS.js.map +1 -0
- package/dist/chunk-NOLWJJHT.js +52 -0
- package/dist/chunk-NOLWJJHT.js.map +1 -0
- package/dist/chunk-NPVINX3Q.js +20 -0
- package/dist/chunk-NPVINX3Q.js.map +1 -0
- package/dist/chunk-NSMU66ZX.js +47 -0
- package/dist/chunk-NSMU66ZX.js.map +1 -0
- package/dist/chunk-O5SWPHUQ.js +79 -0
- package/dist/chunk-O5SWPHUQ.js.map +1 -0
- package/dist/chunk-OGVSZ7NV.js +53 -0
- package/dist/chunk-OGVSZ7NV.js.map +1 -0
- package/dist/chunk-OLHMMFQ7.js +43 -0
- package/dist/chunk-OLHMMFQ7.js.map +1 -0
- package/dist/chunk-ONMTHBZ4.js +54 -0
- package/dist/chunk-ONMTHBZ4.js.map +1 -0
- package/dist/chunk-OVSIOZHJ.js +56 -0
- package/dist/chunk-OVSIOZHJ.js.map +1 -0
- package/dist/chunk-Q54CVE3W.js +154 -0
- package/dist/chunk-Q54CVE3W.js.map +1 -0
- package/dist/chunk-QEHTPQHL.js +35 -0
- package/dist/chunk-QEHTPQHL.js.map +1 -0
- package/dist/chunk-QEIEWGHA.js +62 -0
- package/dist/chunk-QEIEWGHA.js.map +1 -0
- package/dist/chunk-QQHBEACI.js +88 -0
- package/dist/chunk-QQHBEACI.js.map +1 -0
- package/dist/chunk-RJTDQOT2.js +73 -0
- package/dist/chunk-RJTDQOT2.js.map +1 -0
- package/dist/chunk-RQ3RXKAZ.js +203 -0
- package/dist/chunk-RQ3RXKAZ.js.map +1 -0
- package/dist/chunk-RZK2S2OO.js +126 -0
- package/dist/chunk-RZK2S2OO.js.map +1 -0
- package/dist/chunk-SAP7JSSO.js +106 -0
- package/dist/chunk-SAP7JSSO.js.map +1 -0
- package/dist/chunk-T3TQPOVM.js +79 -0
- package/dist/chunk-T3TQPOVM.js.map +1 -0
- package/dist/chunk-T3UQ7G4T.js +58 -0
- package/dist/chunk-T3UQ7G4T.js.map +1 -0
- package/dist/chunk-T56TTOI6.js +53 -0
- package/dist/chunk-T56TTOI6.js.map +1 -0
- package/dist/chunk-T7EFDE2L.js +36 -0
- package/dist/chunk-T7EFDE2L.js.map +1 -0
- package/dist/chunk-VFS3V3VY.js +91 -0
- package/dist/chunk-VFS3V3VY.js.map +1 -0
- package/dist/chunk-VOARBYVQ.js +44 -0
- package/dist/chunk-VOARBYVQ.js.map +1 -0
- package/dist/chunk-WDANALHD.js +95 -0
- package/dist/chunk-WDANALHD.js.map +1 -0
- package/dist/chunk-WSQNPRGN.js +12 -0
- package/dist/chunk-WSQNPRGN.js.map +1 -0
- package/dist/chunk-YPP7QHYT.js +393 -0
- package/dist/chunk-YPP7QHYT.js.map +1 -0
- package/dist/chunk-YTU7BRDW.js +72 -0
- package/dist/chunk-YTU7BRDW.js.map +1 -0
- package/dist/chunk-YYWODLER.js +111 -0
- package/dist/chunk-YYWODLER.js.map +1 -0
- package/dist/chunk-ZOXO3G3I.js +50 -0
- package/dist/chunk-ZOXO3G3I.js.map +1 -0
- package/dist/chunk-ZTFOR3AN.js +79 -0
- package/dist/chunk-ZTFOR3AN.js.map +1 -0
- package/dist/code-block.d.ts +14 -0
- package/dist/code-block.js +5 -0
- package/dist/code-block.js.map +1 -0
- package/dist/combobox.d.ts +26 -0
- package/dist/combobox.js +5 -0
- package/dist/combobox.js.map +1 -0
- package/dist/command-menu.d.ts +52 -0
- package/dist/command-menu.js +7 -0
- package/dist/command-menu.js.map +1 -0
- package/dist/container.d.ts +9 -0
- package/dist/container.js +5 -0
- package/dist/container.js.map +1 -0
- package/dist/cta-band.d.ts +12 -0
- package/dist/cta-band.js +5 -0
- package/dist/cta-band.js.map +1 -0
- package/dist/data-table.d.ts +58 -0
- package/dist/data-table.js +12 -0
- package/dist/data-table.js.map +1 -0
- package/dist/date-picker.d.ts +20 -0
- package/dist/date-picker.js +5 -0
- package/dist/date-picker.js.map +1 -0
- package/dist/dialog.d.ts +21 -0
- package/dist/dialog.js +5 -0
- package/dist/dialog.js.map +1 -0
- package/dist/divider.d.ts +12 -0
- package/dist/divider.js +5 -0
- package/dist/divider.js.map +1 -0
- package/dist/docker-stack-card.d.ts +21 -0
- package/dist/docker-stack-card.js +6 -0
- package/dist/docker-stack-card.js.map +1 -0
- package/dist/donut.d.ts +15 -0
- package/dist/donut.js +5 -0
- package/dist/donut.js.map +1 -0
- package/dist/dropdown-menu.d.ts +15 -0
- package/dist/dropdown-menu.js +5 -0
- package/dist/dropdown-menu.js.map +1 -0
- package/dist/empty.d.ts +12 -0
- package/dist/empty.js +5 -0
- package/dist/empty.js.map +1 -0
- package/dist/feature-card.d.ts +11 -0
- package/dist/feature-card.js +6 -0
- package/dist/feature-card.js.map +1 -0
- package/dist/file-upload.d.ts +20 -0
- package/dist/file-upload.js +5 -0
- package/dist/file-upload.js.map +1 -0
- package/dist/footer.d.ts +35 -0
- package/dist/footer.js +6 -0
- package/dist/footer.js.map +1 -0
- package/dist/form-row.d.ts +19 -0
- package/dist/form-row.js +5 -0
- package/dist/form-row.js.map +1 -0
- package/dist/glow-card.d.ts +14 -0
- package/dist/glow-card.js +5 -0
- package/dist/glow-card.js.map +1 -0
- package/dist/hero-block.d.ts +16 -0
- package/dist/hero-block.js +7 -0
- package/dist/hero-block.js.map +1 -0
- package/dist/host-card.d.ts +27 -0
- package/dist/host-card.js +6 -0
- package/dist/host-card.js.map +1 -0
- package/dist/incident-card.d.ts +23 -0
- package/dist/incident-card.js +5 -0
- package/dist/incident-card.js.map +1 -0
- package/dist/index.d.ts +77 -960
- package/dist/index.js +69 -3812
- package/dist/index.js.map +1 -1
- package/dist/input.d.ts +10 -0
- package/dist/input.js +5 -0
- package/dist/input.js.map +1 -0
- package/dist/kbd.d.ts +24 -0
- package/dist/kbd.js +5 -0
- package/dist/kbd.js.map +1 -0
- package/dist/log-viewer.d.ts +35 -0
- package/dist/log-viewer.js +5 -0
- package/dist/log-viewer.js.map +1 -0
- package/dist/meter.d.ts +23 -0
- package/dist/meter.js +5 -0
- package/dist/meter.js.map +1 -0
- package/dist/monogram.d.ts +20 -0
- package/dist/monogram.js +5 -0
- package/dist/monogram.js.map +1 -0
- package/dist/noir-glow-background.d.ts +56 -0
- package/dist/noir-glow-background.js +4 -0
- package/dist/noir-glow-background.js.map +1 -0
- package/dist/pagination.d.ts +16 -0
- package/dist/pagination.js +5 -0
- package/dist/pagination.js.map +1 -0
- package/dist/panel.d.ts +12 -0
- package/dist/panel.js +5 -0
- package/dist/panel.js.map +1 -0
- package/dist/password-input.d.ts +10 -0
- package/dist/password-input.js +5 -0
- package/dist/password-input.js.map +1 -0
- package/dist/pill.d.ts +17 -0
- package/dist/pill.js +5 -0
- package/dist/pill.js.map +1 -0
- package/dist/pricing-card.d.ts +20 -0
- package/dist/pricing-card.js +6 -0
- package/dist/pricing-card.js.map +1 -0
- package/dist/progress.d.ts +6 -0
- package/dist/progress.js +5 -0
- package/dist/progress.js.map +1 -0
- package/dist/radio-group.d.ts +18 -0
- package/dist/radio-group.js +5 -0
- package/dist/radio-group.js.map +1 -0
- package/dist/rollback-plan.d.ts +23 -0
- package/dist/rollback-plan.js +5 -0
- package/dist/rollback-plan.js.map +1 -0
- package/dist/segmented.d.ts +17 -0
- package/dist/segmented.js +5 -0
- package/dist/segmented.js.map +1 -0
- package/dist/select.d.ts +18 -0
- package/dist/select.js +5 -0
- package/dist/select.js.map +1 -0
- package/dist/service-health-card.d.ts +21 -0
- package/dist/service-health-card.js +6 -0
- package/dist/service-health-card.js.map +1 -0
- package/dist/sheet.d.ts +25 -0
- package/dist/sheet.js +5 -0
- package/dist/sheet.js.map +1 -0
- package/dist/skeleton.d.ts +13 -0
- package/dist/skeleton.js +5 -0
- package/dist/skeleton.js.map +1 -0
- package/dist/slider.d.ts +12 -0
- package/dist/slider.js +5 -0
- package/dist/slider.js.map +1 -0
- package/dist/sparkline.d.ts +16 -0
- package/dist/sparkline.js +5 -0
- package/dist/sparkline.js.map +1 -0
- package/dist/stat-card.d.ts +15 -0
- package/dist/stat-card.js +5 -0
- package/dist/stat-card.js.map +1 -0
- package/dist/status-dot.d.ts +13 -0
- package/dist/status-dot.js +5 -0
- package/dist/status-dot.js.map +1 -0
- package/dist/stepper.d.ts +16 -0
- package/dist/stepper.js +5 -0
- package/dist/stepper.js.map +1 -0
- package/dist/switch.d.ts +9 -0
- package/dist/switch.js +5 -0
- package/dist/switch.js.map +1 -0
- package/dist/tabs.d.ts +9 -0
- package/dist/tabs.js +5 -0
- package/dist/tabs.js.map +1 -0
- package/dist/tag-input.d.ts +20 -0
- package/dist/tag-input.js +5 -0
- package/dist/tag-input.js.map +1 -0
- package/dist/textarea.d.ts +10 -0
- package/dist/textarea.js +5 -0
- package/dist/textarea.js.map +1 -0
- package/dist/timeline.d.ts +30 -0
- package/dist/timeline.js +5 -0
- package/dist/timeline.js.map +1 -0
- package/dist/toaster.d.ts +10 -0
- package/dist/toaster.js +4 -0
- package/dist/toaster.js.map +1 -0
- package/dist/tooltip.d.ts +12 -0
- package/dist/tooltip.js +5 -0
- package/dist/tooltip.js.map +1 -0
- package/dist/utils.d.ts +5 -0
- package/dist/utils.js +4 -0
- package/dist/utils.js.map +1 -0
- package/globals-layers.css +1019 -0
- package/globals-v3.css +17 -0
- package/globals-v4.css +2 -0
- package/globals.css +12 -939
- package/package.json +85 -17
- package/registry.json +936 -0
- package/tailwind.css +9 -0
- package/tokens.css +20 -0
- package/tollerud-avatar-full.png +0 -0
- package/dist/index.cjs +0 -3938
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.cts +0 -960
- /package/{tia-full-figure.svg → tollerud-avatar-full.svg} +0 -0
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { cn } from './chunk-WSQNPRGN.js';
|
|
3
|
+
import { forwardRef, useState, useMemo } from 'react';
|
|
4
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
5
|
+
|
|
6
|
+
var diffStyles = {
|
|
7
|
+
add: "bg-tollerud-success/[0.06] text-tollerud-success hover:bg-tollerud-success/[0.10]",
|
|
8
|
+
remove: "bg-tollerud-error/[0.06] text-tollerud-error hover:bg-tollerud-error/[0.10]",
|
|
9
|
+
context: "text-tollerud-noir-300"
|
|
10
|
+
};
|
|
11
|
+
var diffPrefix = {
|
|
12
|
+
add: "+",
|
|
13
|
+
remove: "-",
|
|
14
|
+
context: " "
|
|
15
|
+
};
|
|
16
|
+
var ActionDiff = forwardRef(
|
|
17
|
+
({ className, lines, label, view: _view = "unified", loading, ...props }, ref) => {
|
|
18
|
+
const [showContext, setShowContext] = useState(true);
|
|
19
|
+
const stats = useMemo(() => {
|
|
20
|
+
const adds = lines.filter((l) => l.type === "add").length;
|
|
21
|
+
const rems = lines.filter((l) => l.type === "remove").length;
|
|
22
|
+
return { adds, rems };
|
|
23
|
+
}, [lines]);
|
|
24
|
+
const displayLines = showContext ? lines : lines.filter((l) => l.type !== "context");
|
|
25
|
+
const hasContext = lines.some((l) => l.type === "context");
|
|
26
|
+
return /* @__PURE__ */ jsxs(
|
|
27
|
+
"div",
|
|
28
|
+
{
|
|
29
|
+
ref,
|
|
30
|
+
className: cn(
|
|
31
|
+
"rounded-lg border border-tollerud-border bg-[var(--color-tollerud-surface-raised)] overflow-hidden",
|
|
32
|
+
loading && "animate-pulse",
|
|
33
|
+
className
|
|
34
|
+
),
|
|
35
|
+
...props,
|
|
36
|
+
children: [
|
|
37
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-4 py-2.5 border-b border-tollerud-border bg-tollerud-noir-900", children: [
|
|
38
|
+
/* @__PURE__ */ jsx("div", { className: "flex items-center gap-2 min-w-0", children: label && /* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-tollerud-foreground font-mono truncate", children: label }) }),
|
|
39
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 text-[11px]", children: [
|
|
40
|
+
/* @__PURE__ */ jsxs("span", { className: "text-tollerud-success", children: [
|
|
41
|
+
"+",
|
|
42
|
+
stats.adds
|
|
43
|
+
] }),
|
|
44
|
+
/* @__PURE__ */ jsxs("span", { className: "text-tollerud-error", children: [
|
|
45
|
+
"-",
|
|
46
|
+
stats.rems
|
|
47
|
+
] }),
|
|
48
|
+
hasContext && /* @__PURE__ */ jsx(
|
|
49
|
+
"button",
|
|
50
|
+
{
|
|
51
|
+
type: "button",
|
|
52
|
+
onClick: () => setShowContext(!showContext),
|
|
53
|
+
className: "text-tollerud-text-muted hover:text-tollerud-foreground transition-colors",
|
|
54
|
+
children: showContext ? "Hide context" : "Show context"
|
|
55
|
+
}
|
|
56
|
+
)
|
|
57
|
+
] })
|
|
58
|
+
] }),
|
|
59
|
+
/* @__PURE__ */ jsx("div", { className: "overflow-x-auto font-mono text-xs leading-relaxed", children: /* @__PURE__ */ jsx("table", { className: "w-full border-collapse", children: /* @__PURE__ */ jsx("tbody", { children: displayLines.map((line, i) => /* @__PURE__ */ jsxs(
|
|
60
|
+
"tr",
|
|
61
|
+
{
|
|
62
|
+
className: cn(
|
|
63
|
+
"transition-colors duration-[100ms]",
|
|
64
|
+
diffStyles[line.type]
|
|
65
|
+
),
|
|
66
|
+
children: [
|
|
67
|
+
/* @__PURE__ */ jsx("td", { className: cn(
|
|
68
|
+
"w-10 text-right px-2 py-px select-none",
|
|
69
|
+
"text-tollerud-noir-500 border-r border-tollerud-border/30",
|
|
70
|
+
"text-[10px] align-top"
|
|
71
|
+
), children: line.oldLine ?? "" }),
|
|
72
|
+
/* @__PURE__ */ jsx("td", { className: cn(
|
|
73
|
+
"w-10 text-right px-2 py-px select-none",
|
|
74
|
+
"text-tollerud-noir-500 border-r border-tollerud-border/30",
|
|
75
|
+
"text-[10px] align-top"
|
|
76
|
+
), children: line.newLine ?? "" }),
|
|
77
|
+
/* @__PURE__ */ jsxs("td", { className: "px-2 py-px whitespace-pre-wrap", children: [
|
|
78
|
+
/* @__PURE__ */ jsx("span", { className: "select-none opacity-50 mr-2", children: diffPrefix[line.type] }),
|
|
79
|
+
line.text
|
|
80
|
+
] })
|
|
81
|
+
]
|
|
82
|
+
},
|
|
83
|
+
i
|
|
84
|
+
)) }) }) })
|
|
85
|
+
]
|
|
86
|
+
}
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
);
|
|
90
|
+
ActionDiff.displayName = "ActionDiff";
|
|
91
|
+
|
|
92
|
+
export { ActionDiff };
|
|
93
|
+
//# sourceMappingURL=chunk-3XTZPDNV.js.map
|
|
94
|
+
//# sourceMappingURL=chunk-3XTZPDNV.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../components/ActionDiff.tsx"],"names":[],"mappings":"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","file":"chunk-3XTZPDNV.js","sourcesContent":["'use client'\n\nimport { type HTMLAttributes, forwardRef, useMemo, useState } from 'react'\nimport { cn } from '@/lib/utils'\n\nexport interface DiffLine {\n /** Diff content */\n text: string\n /** Change type */\n type: 'add' | 'remove' | 'context'\n /** Line number in original */\n oldLine?: number\n /** Line number in new */\n newLine?: number\n}\n\nexport interface ActionDiffProps extends HTMLAttributes<HTMLDivElement> {\n /** Diff lines */\n lines: DiffLine[]\n /** File/label name */\n label?: string\n /** View mode */\n view?: 'unified' | 'side-by-side'\n /** Whether the diff is loading */\n loading?: boolean\n}\n\nconst diffStyles = {\n add: 'bg-tollerud-success/[0.06] text-tollerud-success hover:bg-tollerud-success/[0.10]',\n remove: 'bg-tollerud-error/[0.06] text-tollerud-error hover:bg-tollerud-error/[0.10]',\n context: 'text-tollerud-noir-300',\n}\n\nconst diffPrefix = {\n add: '+',\n remove: '-',\n context: ' ',\n}\n\nconst ActionDiff = forwardRef<HTMLDivElement, ActionDiffProps>(\n ({ className, lines, label, view: _view = 'unified', loading, ...props }, ref) => {\n const [showContext, setShowContext] = useState(true)\n\n const stats = useMemo(() => {\n const adds = lines.filter((l) => l.type === 'add').length\n const rems = lines.filter((l) => l.type === 'remove').length\n return { adds, rems }\n }, [lines])\n\n // Filter context lines if collapsed\n const displayLines = showContext ? lines : lines.filter((l) => l.type !== 'context')\n const hasContext = lines.some((l) => l.type === 'context')\n\n return (\n <div\n ref={ref}\n className={cn(\n 'rounded-lg border border-tollerud-border bg-[var(--color-tollerud-surface-raised)] overflow-hidden',\n loading && 'animate-pulse',\n className\n )}\n {...props}\n >\n {/* Header */}\n <div className=\"flex items-center justify-between px-4 py-2.5 border-b border-tollerud-border bg-tollerud-noir-900\">\n <div className=\"flex items-center gap-2 min-w-0\">\n {label && (\n <span className=\"text-xs font-medium text-tollerud-foreground font-mono truncate\">{label}</span>\n )}\n </div>\n <div className=\"flex items-center gap-3 text-[11px]\">\n <span className=\"text-tollerud-success\">+{stats.adds}</span>\n <span className=\"text-tollerud-error\">-{stats.rems}</span>\n {hasContext && (\n <button\n type=\"button\"\n onClick={() => setShowContext(!showContext)}\n className=\"text-tollerud-text-muted hover:text-tollerud-foreground transition-colors\"\n >\n {showContext ? 'Hide context' : 'Show context'}\n </button>\n )}\n </div>\n </div>\n\n {/* Diff content */}\n <div className=\"overflow-x-auto font-mono text-xs leading-relaxed\">\n <table className=\"w-full border-collapse\">\n <tbody>\n {displayLines.map((line, i) => (\n <tr\n key={i}\n className={cn(\n 'transition-colors duration-[100ms]',\n diffStyles[line.type]\n )}\n >\n {/* Old line number */}\n <td className={cn(\n 'w-10 text-right px-2 py-px select-none',\n 'text-tollerud-noir-500 border-r border-tollerud-border/30',\n 'text-[10px] align-top'\n )}>\n {line.oldLine ?? ''}\n </td>\n {/* New line number */}\n <td className={cn(\n 'w-10 text-right px-2 py-px select-none',\n 'text-tollerud-noir-500 border-r border-tollerud-border/30',\n 'text-[10px] align-top'\n )}>\n {line.newLine ?? ''}\n </td>\n {/* Prefix + content */}\n <td className=\"px-2 py-px whitespace-pre-wrap\">\n <span className=\"select-none opacity-50 mr-2\">{diffPrefix[line.type]}</span>\n {line.text}\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n </div>\n )\n }\n)\nActionDiff.displayName = 'ActionDiff'\n\nexport { ActionDiff }"]}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { cn } from './chunk-WSQNPRGN.js';
|
|
3
|
+
import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';
|
|
4
|
+
import { forwardRef } from 'react';
|
|
5
|
+
import { jsx } from 'react/jsx-runtime';
|
|
6
|
+
|
|
7
|
+
var DropdownMenu = DropdownMenuPrimitive.Root;
|
|
8
|
+
var DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;
|
|
9
|
+
var DropdownMenuContent = forwardRef(({ className, sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx(DropdownMenuPrimitive.Portal, { children: /* @__PURE__ */ jsx(
|
|
10
|
+
DropdownMenuPrimitive.Content,
|
|
11
|
+
{
|
|
12
|
+
ref,
|
|
13
|
+
sideOffset,
|
|
14
|
+
className: cn(
|
|
15
|
+
"z-50 min-w-[9rem] overflow-hidden rounded-lg border p-1 shadow-md",
|
|
16
|
+
"bg-tollerud-noir-850 border-tollerud-border/30 text-tollerud-text-primary",
|
|
17
|
+
"data-[state=open]:animate-in data-[state=closed]:animate-out",
|
|
18
|
+
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
19
|
+
"data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95",
|
|
20
|
+
"data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2",
|
|
21
|
+
"data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
|
22
|
+
className
|
|
23
|
+
),
|
|
24
|
+
...props
|
|
25
|
+
}
|
|
26
|
+
) }));
|
|
27
|
+
DropdownMenuContent.displayName = "DropdownMenuContent";
|
|
28
|
+
var DropdownMenuItem = forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
29
|
+
DropdownMenuPrimitive.Item,
|
|
30
|
+
{
|
|
31
|
+
ref,
|
|
32
|
+
className: cn(
|
|
33
|
+
"relative flex cursor-default select-none items-center rounded-md px-2 py-1.5 text-sm outline-none",
|
|
34
|
+
"text-tollerud-text-secondary data-[highlighted]:text-tollerud-text-primary",
|
|
35
|
+
"data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
|
36
|
+
"data-[highlighted]:bg-tollerud-surface-raised",
|
|
37
|
+
inset && "pl-8",
|
|
38
|
+
className
|
|
39
|
+
),
|
|
40
|
+
...props
|
|
41
|
+
}
|
|
42
|
+
));
|
|
43
|
+
DropdownMenuItem.displayName = "DropdownMenuItem";
|
|
44
|
+
var DropdownMenuSeparator = forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
45
|
+
DropdownMenuPrimitive.Separator,
|
|
46
|
+
{
|
|
47
|
+
ref,
|
|
48
|
+
className: cn("-mx-1 my-1 h-px bg-tollerud-border/30", className),
|
|
49
|
+
...props
|
|
50
|
+
}
|
|
51
|
+
));
|
|
52
|
+
DropdownMenuSeparator.displayName = "DropdownMenuSeparator";
|
|
53
|
+
var DropdownMenuLabel = forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
54
|
+
DropdownMenuPrimitive.Label,
|
|
55
|
+
{
|
|
56
|
+
ref,
|
|
57
|
+
className: cn("px-2 py-1.5 text-xs font-semibold text-tollerud-text-muted", inset && "pl-8", className),
|
|
58
|
+
...props
|
|
59
|
+
}
|
|
60
|
+
));
|
|
61
|
+
DropdownMenuLabel.displayName = "DropdownMenuLabel";
|
|
62
|
+
|
|
63
|
+
export { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger };
|
|
64
|
+
//# sourceMappingURL=chunk-435JHF7G.js.map
|
|
65
|
+
//# sourceMappingURL=chunk-435JHF7G.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../components/DropdownMenu.tsx"],"names":[],"mappings":";;;;;AAQA,IAAM,YAAA,GAAqC,qBAAA,CAAA;AAC3C,IAAM,mBAAA,GAA4C,qBAAA,CAAA;AAElD,IAAM,mBAAA,GAAsB,UAAA,CAG1B,CAAC,EAAE,SAAA,EAAW,UAAA,GAAa,CAAA,EAAG,GAAG,KAAA,EAAM,EAAG,GAAA,qBAC1C,GAAA,CAAuB,8BAAtB,EACC,QAAA,kBAAA,GAAA;AAAA,EAAuB,qBAAA,CAAA,OAAA;AAAA,EAAtB;AAAA,IACC,GAAA;AAAA,IACA,UAAA;AAAA,IACA,SAAA,EAAW,EAAA;AAAA,MACT,mEAAA;AAAA,MACA,2EAAA;AAAA,MACA,8DAAA;AAAA,MACA,4DAAA;AAAA,MACA,8DAAA;AAAA,MACA,+EAAA;AAAA,MACA,+EAAA;AAAA,MACA;AAAA,KACF;AAAA,IACC,GAAG;AAAA;AACN,CAAA,EACF,CACD;AACD,mBAAA,CAAoB,WAAA,GAAc,qBAAA;AAElC,IAAM,gBAAA,GAAmB,WAKvB,CAAC,EAAE,WAAW,KAAA,EAAO,GAAG,KAAA,EAAM,EAAG,GAAA,qBACjC,GAAA;AAAA,EAAuB,qBAAA,CAAA,IAAA;AAAA,EAAtB;AAAA,IACC,GAAA;AAAA,IACA,SAAA,EAAW,EAAA;AAAA,MACT,mGAAA;AAAA,MACA,4EAAA;AAAA,MACA,gEAAA;AAAA,MACA,+CAAA;AAAA,MACA,KAAA,IAAS,MAAA;AAAA,MACT;AAAA,KACF;AAAA,IACC,GAAG;AAAA;AACN,CACD;AACD,gBAAA,CAAiB,WAAA,GAAc,kBAAA;AAE/B,IAAM,qBAAA,GAAwB,WAG5B,CAAC,EAAE,WAAW,GAAG,KAAA,IAAS,GAAA,qBAC1B,GAAA;AAAA,EAAuB,qBAAA,CAAA,SAAA;AAAA,EAAtB;AAAA,IACC,GAAA;AAAA,IACA,SAAA,EAAW,EAAA,CAAG,uCAAA,EAAyC,SAAS,CAAA;AAAA,IAC/D,GAAG;AAAA;AACN,CACD;AACD,qBAAA,CAAsB,WAAA,GAAc,uBAAA;AAEpC,IAAM,iBAAA,GAAoB,WAKxB,CAAC,EAAE,WAAW,KAAA,EAAO,GAAG,KAAA,EAAM,EAAG,GAAA,qBACjC,GAAA;AAAA,EAAuB,qBAAA,CAAA,KAAA;AAAA,EAAtB;AAAA,IACC,GAAA;AAAA,IACA,SAAA,EAAW,EAAA,CAAG,4DAAA,EAA8D,KAAA,IAAS,QAAQ,SAAS,CAAA;AAAA,IACrG,GAAG;AAAA;AACN,CACD;AACD,iBAAA,CAAkB,WAAA,GAAc,mBAAA","file":"chunk-435JHF7G.js","sourcesContent":["'use client'\n\nimport * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu'\nimport { forwardRef } from 'react'\nimport { cn } from '@/lib/utils'\n\n/* ──────────────────── DropdownMenu ──────────────────── */\n\nconst DropdownMenu = DropdownMenuPrimitive.Root\nconst DropdownMenuTrigger = DropdownMenuPrimitive.Trigger\n\nconst DropdownMenuContent = forwardRef<\n React.ComponentRef<typeof DropdownMenuPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content>\n>(({ className, sideOffset = 4, ...props }, ref) => (\n <DropdownMenuPrimitive.Portal>\n <DropdownMenuPrimitive.Content\n ref={ref}\n sideOffset={sideOffset}\n className={cn(\n 'z-50 min-w-[9rem] overflow-hidden rounded-lg border p-1 shadow-md',\n 'bg-tollerud-noir-850 border-tollerud-border/30 text-tollerud-text-primary',\n 'data-[state=open]:animate-in data-[state=closed]:animate-out',\n 'data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0',\n 'data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95',\n 'data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2',\n 'data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',\n className\n )}\n {...props}\n />\n </DropdownMenuPrimitive.Portal>\n))\nDropdownMenuContent.displayName = 'DropdownMenuContent'\n\nconst DropdownMenuItem = forwardRef<\n React.ComponentRef<typeof DropdownMenuPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item> & {\n inset?: boolean\n }\n>(({ className, inset, ...props }, ref) => (\n <DropdownMenuPrimitive.Item\n ref={ref}\n className={cn(\n 'relative flex cursor-default select-none items-center rounded-md px-2 py-1.5 text-sm outline-none',\n 'text-tollerud-text-secondary data-[highlighted]:text-tollerud-text-primary',\n 'data-[disabled]:pointer-events-none data-[disabled]:opacity-50',\n 'data-[highlighted]:bg-tollerud-surface-raised',\n inset && 'pl-8',\n className\n )}\n {...props}\n />\n))\nDropdownMenuItem.displayName = 'DropdownMenuItem'\n\nconst DropdownMenuSeparator = forwardRef<\n React.ComponentRef<typeof DropdownMenuPrimitive.Separator>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Separator>\n>(({ className, ...props }, ref) => (\n <DropdownMenuPrimitive.Separator\n ref={ref}\n className={cn('-mx-1 my-1 h-px bg-tollerud-border/30', className)}\n {...props}\n />\n))\nDropdownMenuSeparator.displayName = 'DropdownMenuSeparator'\n\nconst DropdownMenuLabel = forwardRef<\n React.ComponentRef<typeof DropdownMenuPrimitive.Label>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Label> & {\n inset?: boolean\n }\n>(({ className, inset, ...props }, ref) => (\n <DropdownMenuPrimitive.Label\n ref={ref}\n className={cn('px-2 py-1.5 text-xs font-semibold text-tollerud-text-muted', inset && 'pl-8', className)}\n {...props}\n />\n))\nDropdownMenuLabel.displayName = 'DropdownMenuLabel'\n\nexport {\n DropdownMenu,\n DropdownMenuTrigger,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuSeparator,\n DropdownMenuLabel,\n}"]}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { cn } from './chunk-WSQNPRGN.js';
|
|
3
|
+
import { forwardRef } from 'react';
|
|
4
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
5
|
+
|
|
6
|
+
var BarChart = forwardRef(
|
|
7
|
+
({ className, data, height = 180, ...props }, ref) => {
|
|
8
|
+
const max = Math.max(...data.map((d) => d.value), 1);
|
|
9
|
+
return /* @__PURE__ */ jsxs("div", { ref, className: cn("w-full", className), ...props, children: [
|
|
10
|
+
/* @__PURE__ */ jsx(
|
|
11
|
+
"div",
|
|
12
|
+
{
|
|
13
|
+
className: "flex items-end gap-2.5 px-1",
|
|
14
|
+
style: { height, borderBottom: "1px solid var(--chart-grid)" },
|
|
15
|
+
children: data.map((d, i) => /* @__PURE__ */ jsxs(
|
|
16
|
+
"div",
|
|
17
|
+
{
|
|
18
|
+
className: "flex flex-1 flex-col items-center justify-end h-full",
|
|
19
|
+
children: [
|
|
20
|
+
/* @__PURE__ */ jsx("span", { className: "mb-1.5 font-mono text-[11px] text-tollerud-text-secondary", children: d.value }),
|
|
21
|
+
/* @__PURE__ */ jsx(
|
|
22
|
+
"div",
|
|
23
|
+
{
|
|
24
|
+
className: cn(
|
|
25
|
+
"w-full max-w-[38px] rounded-t-[3px] transition-[height] duration-500 ease-out",
|
|
26
|
+
d.accent ? "bg-tollerud-yellow" : "bg-tollerud-noir-600"
|
|
27
|
+
),
|
|
28
|
+
style: { height: `${d.value / max * 100}%` }
|
|
29
|
+
}
|
|
30
|
+
)
|
|
31
|
+
]
|
|
32
|
+
},
|
|
33
|
+
i
|
|
34
|
+
))
|
|
35
|
+
}
|
|
36
|
+
),
|
|
37
|
+
/* @__PURE__ */ jsx("div", { className: "flex gap-2.5 px-1 pt-2", children: data.map((d, i) => /* @__PURE__ */ jsx(
|
|
38
|
+
"div",
|
|
39
|
+
{
|
|
40
|
+
className: "flex-1 text-center text-[11px] text-tollerud-text-muted",
|
|
41
|
+
children: d.label
|
|
42
|
+
},
|
|
43
|
+
i
|
|
44
|
+
)) })
|
|
45
|
+
] });
|
|
46
|
+
}
|
|
47
|
+
);
|
|
48
|
+
BarChart.displayName = "BarChart";
|
|
49
|
+
|
|
50
|
+
export { BarChart };
|
|
51
|
+
//# sourceMappingURL=chunk-4PA2ACNF.js.map
|
|
52
|
+
//# sourceMappingURL=chunk-4PA2ACNF.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../components/BarChart.tsx"],"names":[],"mappings":";;;;AAcA,IAAM,QAAA,GAAW,UAAA;AAAA,EACf,CAAC,EAAE,SAAA,EAAW,IAAA,EAAM,SAAS,GAAA,EAAK,GAAG,KAAA,EAAM,EAAG,GAAA,KAAQ;AACpD,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,GAAA,CAAI,GAAG,IAAA,CAAK,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAE,KAAK,CAAA,EAAG,CAAC,CAAA;AAEnD,IAAA,uBACE,IAAA,CAAC,SAAI,GAAA,EAAU,SAAA,EAAW,GAAG,QAAA,EAAU,SAAS,CAAA,EAAI,GAAG,KAAA,EACrD,QAAA,EAAA;AAAA,sBAAA,GAAA;AAAA,QAAC,KAAA;AAAA,QAAA;AAAA,UACC,SAAA,EAAU,6BAAA;AAAA,UACV,KAAA,EAAO,EAAE,MAAA,EAAQ,YAAA,EAAc,6BAAA,EAA8B;AAAA,UAE5D,QAAA,EAAA,IAAA,CAAK,GAAA,CAAI,CAAC,CAAA,EAAG,CAAA,qBACZ,IAAA;AAAA,YAAC,KAAA;AAAA,YAAA;AAAA,cAEC,SAAA,EAAU,sDAAA;AAAA,cAEV,QAAA,EAAA;AAAA,gCAAA,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,2DAAA,EACb,QAAA,EAAA,CAAA,CAAE,KAAA,EACL,CAAA;AAAA,gCACA,GAAA;AAAA,kBAAC,KAAA;AAAA,kBAAA;AAAA,oBACC,SAAA,EAAW,EAAA;AAAA,sBACT,+EAAA;AAAA,sBACA,CAAA,CAAE,SAAS,oBAAA,GAAuB;AAAA,qBACpC;AAAA,oBACA,KAAA,EAAO,EAAE,MAAA,EAAQ,CAAA,EAAI,EAAE,KAAA,GAAQ,GAAA,GAAO,GAAG,CAAA,CAAA,CAAA;AAAI;AAAA;AAC/C;AAAA,aAAA;AAAA,YAZK;AAAA,WAcR;AAAA;AAAA,OACH;AAAA,sBACA,GAAA,CAAC,SAAI,SAAA,EAAU,wBAAA,EACZ,eAAK,GAAA,CAAI,CAAC,GAAG,CAAA,qBACZ,GAAA;AAAA,QAAC,KAAA;AAAA,QAAA;AAAA,UAEC,SAAA,EAAU,yDAAA;AAAA,UAET,QAAA,EAAA,CAAA,CAAE;AAAA,SAAA;AAAA,QAHE;AAAA,OAKR,CAAA,EACH;AAAA,KAAA,EACF,CAAA;AAAA,EAEJ;AACF;AACA,QAAA,CAAS,WAAA,GAAc,UAAA","file":"chunk-4PA2ACNF.js","sourcesContent":["import { type HTMLAttributes, forwardRef } from 'react'\nimport { cn } from '@/lib/utils'\n\nexport interface BarChartDatum {\n label: string\n value: number\n accent?: boolean\n}\n\nexport interface BarChartProps extends HTMLAttributes<HTMLDivElement> {\n data: BarChartDatum[]\n height?: number\n}\n\nconst BarChart = forwardRef<HTMLDivElement, BarChartProps>(\n ({ className, data, height = 180, ...props }, ref) => {\n const max = Math.max(...data.map((d) => d.value), 1)\n\n return (\n <div ref={ref} className={cn('w-full', className)} {...props}>\n <div\n className=\"flex items-end gap-2.5 px-1\"\n style={{ height, borderBottom: '1px solid var(--chart-grid)' }}\n >\n {data.map((d, i) => (\n <div\n key={i}\n className=\"flex flex-1 flex-col items-center justify-end h-full\"\n >\n <span className=\"mb-1.5 font-mono text-[11px] text-tollerud-text-secondary\">\n {d.value}\n </span>\n <div\n className={cn(\n 'w-full max-w-[38px] rounded-t-[3px] transition-[height] duration-500 ease-out',\n d.accent ? 'bg-tollerud-yellow' : 'bg-tollerud-noir-600'\n )}\n style={{ height: `${(d.value / max) * 100}%` }}\n />\n </div>\n ))}\n </div>\n <div className=\"flex gap-2.5 px-1 pt-2\">\n {data.map((d, i) => (\n <div\n key={i}\n className=\"flex-1 text-center text-[11px] text-tollerud-text-muted\"\n >\n {d.label}\n </div>\n ))}\n </div>\n </div>\n )\n }\n)\nBarChart.displayName = 'BarChart'\n\nexport { BarChart }\n"]}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { cn } from './chunk-WSQNPRGN.js';
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
import * as ProgressPrimitive from '@radix-ui/react-progress';
|
|
5
|
+
import { jsx } from 'react/jsx-runtime';
|
|
6
|
+
|
|
7
|
+
var Progress = React.forwardRef(({ className, value, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
8
|
+
ProgressPrimitive.Root,
|
|
9
|
+
{
|
|
10
|
+
ref,
|
|
11
|
+
className: cn(
|
|
12
|
+
"relative h-2 w-full overflow-hidden rounded-full bg-tollerud-noir-800",
|
|
13
|
+
className
|
|
14
|
+
),
|
|
15
|
+
...props,
|
|
16
|
+
children: /* @__PURE__ */ jsx(
|
|
17
|
+
ProgressPrimitive.Indicator,
|
|
18
|
+
{
|
|
19
|
+
className: "h-full w-full flex-1 rounded-full bg-tollerud-yellow transition-all duration-300 ease-in-out",
|
|
20
|
+
style: { transform: `translateX(-${100 - (value || 0)}%)` }
|
|
21
|
+
}
|
|
22
|
+
)
|
|
23
|
+
}
|
|
24
|
+
));
|
|
25
|
+
Progress.displayName = "Progress";
|
|
26
|
+
|
|
27
|
+
export { Progress };
|
|
28
|
+
//# sourceMappingURL=chunk-5GWHUJ5D.js.map
|
|
29
|
+
//# sourceMappingURL=chunk-5GWHUJ5D.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../components/Progress.tsx"],"names":[],"mappings":";;;;;AAMA,IAAM,QAAA,GAAiB,iBAGrB,CAAC,EAAE,WAAW,KAAA,EAAO,GAAG,KAAA,EAAM,EAAG,GAAA,qBACjC,GAAA;AAAA,EAAmB,iBAAA,CAAA,IAAA;AAAA,EAAlB;AAAA,IACC,GAAA;AAAA,IACA,SAAA,EAAW,EAAA;AAAA,MACT,uEAAA;AAAA,MACA;AAAA,KACF;AAAA,IACC,GAAG,KAAA;AAAA,IAEJ,QAAA,kBAAA,GAAA;AAAA,MAAmB,iBAAA,CAAA,SAAA;AAAA,MAAlB;AAAA,QACC,SAAA,EAAU,8FAAA;AAAA,QACV,OAAO,EAAE,SAAA,EAAW,eAAe,GAAA,IAAO,KAAA,IAAS,EAAE,CAAA,EAAA,CAAA;AAAK;AAAA;AAC5D;AACF,CACD;AACD,QAAA,CAAS,WAAA,GAAc,UAAA","file":"chunk-5GWHUJ5D.js","sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport * as ProgressPrimitive from '@radix-ui/react-progress'\nimport { cn } from '@/lib/utils'\n\nconst Progress = React.forwardRef<\n React.ComponentRef<typeof ProgressPrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof ProgressPrimitive.Root>\n>(({ className, value, ...props }, ref) => (\n <ProgressPrimitive.Root\n ref={ref}\n className={cn(\n 'relative h-2 w-full overflow-hidden rounded-full bg-tollerud-noir-800',\n className\n )}\n {...props}\n >\n <ProgressPrimitive.Indicator\n className=\"h-full w-full flex-1 rounded-full bg-tollerud-yellow transition-all duration-300 ease-in-out\"\n style={{ transform: `translateX(-${100 - (value || 0)}%)` }}\n />\n </ProgressPrimitive.Root>\n))\nProgress.displayName = 'Progress'\n\nexport { Progress }"]}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { cn } from './chunk-WSQNPRGN.js';
|
|
3
|
+
import { useId, useRef, useState } from 'react';
|
|
4
|
+
import { Upload, File, X } from 'lucide-react';
|
|
5
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
6
|
+
|
|
7
|
+
function formatBytes(bytes) {
|
|
8
|
+
if (bytes < 1024) return `${bytes} B`;
|
|
9
|
+
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
10
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
11
|
+
}
|
|
12
|
+
function FileUpload({
|
|
13
|
+
label,
|
|
14
|
+
description,
|
|
15
|
+
error,
|
|
16
|
+
accept,
|
|
17
|
+
multiple,
|
|
18
|
+
onFilesChange,
|
|
19
|
+
className,
|
|
20
|
+
disabled
|
|
21
|
+
}) {
|
|
22
|
+
const id = useId();
|
|
23
|
+
const inputRef = useRef(null);
|
|
24
|
+
const [files, setFiles] = useState([]);
|
|
25
|
+
const [dragging, setDragging] = useState(false);
|
|
26
|
+
const setAndNotify = (next) => {
|
|
27
|
+
setFiles(next);
|
|
28
|
+
onFilesChange?.(next);
|
|
29
|
+
};
|
|
30
|
+
const addFiles = (incoming) => {
|
|
31
|
+
if (!incoming || incoming.length === 0) return;
|
|
32
|
+
const incomingArr = Array.from(incoming);
|
|
33
|
+
setAndNotify(multiple ? [...files, ...incomingArr] : [incomingArr[0]]);
|
|
34
|
+
};
|
|
35
|
+
const removeAt = (index) => {
|
|
36
|
+
setAndNotify(files.filter((_, i) => i !== index));
|
|
37
|
+
};
|
|
38
|
+
const onDrop = (e) => {
|
|
39
|
+
e.preventDefault();
|
|
40
|
+
setDragging(false);
|
|
41
|
+
if (disabled) return;
|
|
42
|
+
addFiles(e.dataTransfer.files);
|
|
43
|
+
};
|
|
44
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-1.5", className), children: [
|
|
45
|
+
label && /* @__PURE__ */ jsx("label", { htmlFor: id, className: "text-xs font-medium text-tollerud-text-muted", children: label }),
|
|
46
|
+
/* @__PURE__ */ jsxs(
|
|
47
|
+
"div",
|
|
48
|
+
{
|
|
49
|
+
role: "button",
|
|
50
|
+
tabIndex: disabled ? -1 : 0,
|
|
51
|
+
"aria-disabled": disabled,
|
|
52
|
+
onClick: () => !disabled && inputRef.current?.click(),
|
|
53
|
+
onKeyDown: (e) => {
|
|
54
|
+
if (!disabled && (e.key === "Enter" || e.key === " ")) {
|
|
55
|
+
e.preventDefault();
|
|
56
|
+
inputRef.current?.click();
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
onDragOver: (e) => {
|
|
60
|
+
e.preventDefault();
|
|
61
|
+
if (!disabled) setDragging(true);
|
|
62
|
+
},
|
|
63
|
+
onDragLeave: () => setDragging(false),
|
|
64
|
+
onDrop,
|
|
65
|
+
className: cn(
|
|
66
|
+
"flex flex-col items-center justify-center gap-2 rounded-lg border border-dashed px-6 py-8 text-center cursor-pointer transition-colors duration-[150ms]",
|
|
67
|
+
dragging ? "border-tollerud-yellow bg-tollerud-yellow/[0.06]" : "border-tollerud-border bg-tollerud-surface-raised hover:border-tollerud-text-secondary",
|
|
68
|
+
error && "border-tollerud-error",
|
|
69
|
+
disabled && "opacity-50 pointer-events-none"
|
|
70
|
+
),
|
|
71
|
+
children: [
|
|
72
|
+
/* @__PURE__ */ jsx(Upload, { size: 20, className: "text-tollerud-text-muted" }),
|
|
73
|
+
/* @__PURE__ */ jsxs("div", { className: "text-sm text-tollerud-text-secondary", children: [
|
|
74
|
+
/* @__PURE__ */ jsx("span", { className: "font-medium text-tollerud-yellow", children: "Click to upload" }),
|
|
75
|
+
" or drag and drop"
|
|
76
|
+
] }),
|
|
77
|
+
description && /* @__PURE__ */ jsx("p", { className: "text-xs text-tollerud-text-muted", children: description }),
|
|
78
|
+
/* @__PURE__ */ jsx(
|
|
79
|
+
"input",
|
|
80
|
+
{
|
|
81
|
+
ref: inputRef,
|
|
82
|
+
id,
|
|
83
|
+
type: "file",
|
|
84
|
+
accept,
|
|
85
|
+
multiple,
|
|
86
|
+
disabled,
|
|
87
|
+
onChange: (e) => addFiles(e.target.files),
|
|
88
|
+
className: "sr-only"
|
|
89
|
+
}
|
|
90
|
+
)
|
|
91
|
+
]
|
|
92
|
+
}
|
|
93
|
+
),
|
|
94
|
+
files.length > 0 && /* @__PURE__ */ jsx("ul", { className: "flex flex-col gap-1.5", children: files.map((file, i) => /* @__PURE__ */ jsxs(
|
|
95
|
+
"li",
|
|
96
|
+
{
|
|
97
|
+
className: "flex items-center gap-2.5 rounded-md border border-tollerud-border bg-tollerud-surface-raised px-3 py-2 text-sm",
|
|
98
|
+
children: [
|
|
99
|
+
/* @__PURE__ */ jsx(File, { size: 15, className: "shrink-0 text-tollerud-text-muted" }),
|
|
100
|
+
/* @__PURE__ */ jsx("span", { className: "flex-1 truncate text-tollerud-text-primary", children: file.name }),
|
|
101
|
+
/* @__PURE__ */ jsx("span", { className: "shrink-0 text-xs text-tollerud-text-muted", children: formatBytes(file.size) }),
|
|
102
|
+
/* @__PURE__ */ jsx(
|
|
103
|
+
"button",
|
|
104
|
+
{
|
|
105
|
+
type: "button",
|
|
106
|
+
"aria-label": `Remove ${file.name}`,
|
|
107
|
+
onClick: () => removeAt(i),
|
|
108
|
+
className: "shrink-0 text-tollerud-text-muted hover:text-tollerud-text-primary transition-colors duration-[150ms]",
|
|
109
|
+
children: /* @__PURE__ */ jsx(X, { size: 14 })
|
|
110
|
+
}
|
|
111
|
+
)
|
|
112
|
+
]
|
|
113
|
+
},
|
|
114
|
+
`${file.name}-${i}`
|
|
115
|
+
)) }),
|
|
116
|
+
error && /* @__PURE__ */ jsx("p", { className: "text-xs text-tollerud-error", children: error })
|
|
117
|
+
] });
|
|
118
|
+
}
|
|
119
|
+
FileUpload.displayName = "FileUpload";
|
|
120
|
+
|
|
121
|
+
export { FileUpload };
|
|
122
|
+
//# sourceMappingURL=chunk-6FUKJD3W.js.map
|
|
123
|
+
//# sourceMappingURL=chunk-6FUKJD3W.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../components/FileUpload.tsx"],"names":["FileIcon"],"mappings":"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","file":"chunk-6FUKJD3W.js","sourcesContent":["'use client'\n\nimport { type DragEvent, useId, useRef, useState } from 'react'\nimport { Upload, X, File as FileIcon } from 'lucide-react'\nimport { cn } from '@/lib/utils'\n\nexport interface FileUploadProps {\n label?: string\n description?: React.ReactNode\n error?: string\n /** Forwarded to the underlying `<input accept>` */\n accept?: string\n multiple?: boolean\n /** Called whenever the selected file list changes */\n onFilesChange?: (files: File[]) => void\n className?: string\n disabled?: boolean\n}\n\nfunction formatBytes(bytes: number) {\n if (bytes < 1024) return `${bytes} B`\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`\n}\n\nfunction FileUpload({\n label,\n description,\n error,\n accept,\n multiple,\n onFilesChange,\n className,\n disabled,\n}: FileUploadProps) {\n const id = useId()\n const inputRef = useRef<HTMLInputElement>(null)\n const [files, setFiles] = useState<File[]>([])\n const [dragging, setDragging] = useState(false)\n\n const setAndNotify = (next: File[]) => {\n setFiles(next)\n onFilesChange?.(next)\n }\n\n const addFiles = (incoming: FileList | null) => {\n if (!incoming || incoming.length === 0) return\n const incomingArr = Array.from(incoming)\n setAndNotify(multiple ? [...files, ...incomingArr] : [incomingArr[0]!])\n }\n\n const removeAt = (index: number) => {\n setAndNotify(files.filter((_, i) => i !== index))\n }\n\n const onDrop = (e: DragEvent<HTMLDivElement>) => {\n e.preventDefault()\n setDragging(false)\n if (disabled) return\n addFiles(e.dataTransfer.files)\n }\n\n return (\n <div className={cn('flex flex-col gap-1.5', className)}>\n {label && (\n <label htmlFor={id} className=\"text-xs font-medium text-tollerud-text-muted\">\n {label}\n </label>\n )}\n\n <div\n role=\"button\"\n tabIndex={disabled ? -1 : 0}\n aria-disabled={disabled}\n onClick={() => !disabled && inputRef.current?.click()}\n onKeyDown={(e) => {\n if (!disabled && (e.key === 'Enter' || e.key === ' ')) {\n e.preventDefault()\n inputRef.current?.click()\n }\n }}\n onDragOver={(e) => {\n e.preventDefault()\n if (!disabled) setDragging(true)\n }}\n onDragLeave={() => setDragging(false)}\n onDrop={onDrop}\n className={cn(\n 'flex flex-col items-center justify-center gap-2 rounded-lg border border-dashed px-6 py-8 text-center cursor-pointer transition-colors duration-[150ms]',\n dragging\n ? 'border-tollerud-yellow bg-tollerud-yellow/[0.06]'\n : 'border-tollerud-border bg-tollerud-surface-raised hover:border-tollerud-text-secondary',\n error && 'border-tollerud-error',\n disabled && 'opacity-50 pointer-events-none'\n )}\n >\n <Upload size={20} className=\"text-tollerud-text-muted\" />\n <div className=\"text-sm text-tollerud-text-secondary\">\n <span className=\"font-medium text-tollerud-yellow\">Click to upload</span> or drag and drop\n </div>\n {description && <p className=\"text-xs text-tollerud-text-muted\">{description}</p>}\n <input\n ref={inputRef}\n id={id}\n type=\"file\"\n accept={accept}\n multiple={multiple}\n disabled={disabled}\n onChange={(e) => addFiles(e.target.files)}\n className=\"sr-only\"\n />\n </div>\n\n {files.length > 0 && (\n <ul className=\"flex flex-col gap-1.5\">\n {files.map((file, i) => (\n <li\n key={`${file.name}-${i}`}\n className=\"flex items-center gap-2.5 rounded-md border border-tollerud-border bg-tollerud-surface-raised px-3 py-2 text-sm\"\n >\n <FileIcon size={15} className=\"shrink-0 text-tollerud-text-muted\" />\n <span className=\"flex-1 truncate text-tollerud-text-primary\">{file.name}</span>\n <span className=\"shrink-0 text-xs text-tollerud-text-muted\">{formatBytes(file.size)}</span>\n <button\n type=\"button\"\n aria-label={`Remove ${file.name}`}\n onClick={() => removeAt(i)}\n className=\"shrink-0 text-tollerud-text-muted hover:text-tollerud-text-primary transition-colors duration-[150ms]\"\n >\n <X size={14} />\n </button>\n </li>\n ))}\n </ul>\n )}\n\n {error && <p className=\"text-xs text-tollerud-error\">{error}</p>}\n </div>\n )\n}\nFileUpload.displayName = 'FileUpload'\n\nexport { FileUpload }\n"]}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { cn } from './chunk-WSQNPRGN.js';
|
|
3
|
+
import { useId, useState } from 'react';
|
|
4
|
+
import { X } from 'lucide-react';
|
|
5
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
6
|
+
|
|
7
|
+
function TagInput({
|
|
8
|
+
value: valueProp,
|
|
9
|
+
defaultValue = [],
|
|
10
|
+
onChange,
|
|
11
|
+
label,
|
|
12
|
+
error,
|
|
13
|
+
placeholder = "Add a tag\u2026",
|
|
14
|
+
max,
|
|
15
|
+
className,
|
|
16
|
+
disabled
|
|
17
|
+
}) {
|
|
18
|
+
const id = useId();
|
|
19
|
+
const isControlled = valueProp !== void 0;
|
|
20
|
+
const [internalTags, setInternalTags] = useState(defaultValue);
|
|
21
|
+
const tags = isControlled ? valueProp : internalTags;
|
|
22
|
+
const [draft, setDraft] = useState("");
|
|
23
|
+
const setAndNotify = (next) => {
|
|
24
|
+
if (!isControlled) setInternalTags(next);
|
|
25
|
+
onChange?.(next);
|
|
26
|
+
};
|
|
27
|
+
const addTag = (raw) => {
|
|
28
|
+
const tag = raw.trim();
|
|
29
|
+
if (!tag || tags.includes(tag)) return;
|
|
30
|
+
if (max && tags.length >= max) return;
|
|
31
|
+
setAndNotify([...tags, tag]);
|
|
32
|
+
setDraft("");
|
|
33
|
+
};
|
|
34
|
+
const removeTag = (index) => {
|
|
35
|
+
setAndNotify(tags.filter((_, i) => i !== index));
|
|
36
|
+
};
|
|
37
|
+
const onKeyDown = (e) => {
|
|
38
|
+
if (e.key === "Enter" || e.key === ",") {
|
|
39
|
+
e.preventDefault();
|
|
40
|
+
addTag(draft);
|
|
41
|
+
} else if (e.key === "Backspace" && draft === "" && tags.length > 0) {
|
|
42
|
+
removeTag(tags.length - 1);
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
const atMax = max ? tags.length >= max : false;
|
|
46
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-1", className), children: [
|
|
47
|
+
label && /* @__PURE__ */ jsx("label", { htmlFor: id, className: "text-xs font-medium text-tollerud-text-muted", children: label }),
|
|
48
|
+
/* @__PURE__ */ jsxs(
|
|
49
|
+
"div",
|
|
50
|
+
{
|
|
51
|
+
className: cn(
|
|
52
|
+
"flex flex-wrap items-center gap-1.5 rounded px-2.5 py-1.5",
|
|
53
|
+
"bg-tollerud-surface-raised border",
|
|
54
|
+
"transition-[border-color] duration-[150ms]",
|
|
55
|
+
"focus-within:border-tollerud-yellow focus-within:shadow-[0_0_0_1px_#E8D500]",
|
|
56
|
+
error ? "border-tollerud-error" : "border-tollerud-border",
|
|
57
|
+
disabled && "opacity-50 pointer-events-none"
|
|
58
|
+
),
|
|
59
|
+
children: [
|
|
60
|
+
tags.map((tag, i) => /* @__PURE__ */ jsxs(
|
|
61
|
+
"span",
|
|
62
|
+
{
|
|
63
|
+
className: "inline-flex items-center gap-1 rounded-full bg-tollerud-surface-hover px-2.5 py-0.5 text-xs font-medium text-tollerud-text-primary",
|
|
64
|
+
children: [
|
|
65
|
+
tag,
|
|
66
|
+
/* @__PURE__ */ jsx(
|
|
67
|
+
"button",
|
|
68
|
+
{
|
|
69
|
+
type: "button",
|
|
70
|
+
"aria-label": `Remove ${tag}`,
|
|
71
|
+
onClick: () => removeTag(i),
|
|
72
|
+
className: "text-tollerud-text-muted hover:text-tollerud-text-primary transition-colors duration-[150ms]",
|
|
73
|
+
children: /* @__PURE__ */ jsx(X, { size: 12 })
|
|
74
|
+
}
|
|
75
|
+
)
|
|
76
|
+
]
|
|
77
|
+
},
|
|
78
|
+
`${tag}-${i}`
|
|
79
|
+
)),
|
|
80
|
+
/* @__PURE__ */ jsx(
|
|
81
|
+
"input",
|
|
82
|
+
{
|
|
83
|
+
id,
|
|
84
|
+
value: draft,
|
|
85
|
+
disabled: disabled || atMax,
|
|
86
|
+
onChange: (e) => setDraft(e.target.value),
|
|
87
|
+
onKeyDown,
|
|
88
|
+
onBlur: () => addTag(draft),
|
|
89
|
+
placeholder: atMax ? "" : placeholder,
|
|
90
|
+
className: cn(
|
|
91
|
+
"min-w-[6rem] flex-1 bg-transparent py-0.5 text-sm text-tollerud-text-primary",
|
|
92
|
+
"placeholder:text-tollerud-text-muted focus:outline-none"
|
|
93
|
+
)
|
|
94
|
+
}
|
|
95
|
+
)
|
|
96
|
+
]
|
|
97
|
+
}
|
|
98
|
+
),
|
|
99
|
+
error && /* @__PURE__ */ jsx("p", { className: "text-xs text-tollerud-error mt-0.5", children: error })
|
|
100
|
+
] });
|
|
101
|
+
}
|
|
102
|
+
TagInput.displayName = "TagInput";
|
|
103
|
+
|
|
104
|
+
export { TagInput };
|
|
105
|
+
//# sourceMappingURL=chunk-6IS2AYYG.js.map
|
|
106
|
+
//# sourceMappingURL=chunk-6IS2AYYG.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../components/TagInput.tsx"],"names":[],"mappings":"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","file":"chunk-6IS2AYYG.js","sourcesContent":["'use client'\n\nimport { type KeyboardEvent, useId, useState } from 'react'\nimport { X } from 'lucide-react'\nimport { cn } from '@/lib/utils'\n\nexport interface TagInputProps {\n value?: string[]\n defaultValue?: string[]\n onChange?: (tags: string[]) => void\n label?: string\n error?: string\n placeholder?: string\n /** Maximum number of tags allowed */\n max?: number\n className?: string\n disabled?: boolean\n}\n\nfunction TagInput({\n value: valueProp,\n defaultValue = [],\n onChange,\n label,\n error,\n placeholder = 'Add a tag…',\n max,\n className,\n disabled,\n}: TagInputProps) {\n const id = useId()\n const isControlled = valueProp !== undefined\n const [internalTags, setInternalTags] = useState<string[]>(defaultValue)\n const tags = isControlled ? valueProp : internalTags\n const [draft, setDraft] = useState('')\n\n const setAndNotify = (next: string[]) => {\n if (!isControlled) setInternalTags(next)\n onChange?.(next)\n }\n\n const addTag = (raw: string) => {\n const tag = raw.trim()\n if (!tag || tags.includes(tag)) return\n if (max && tags.length >= max) return\n setAndNotify([...tags, tag])\n setDraft('')\n }\n\n const removeTag = (index: number) => {\n setAndNotify(tags.filter((_, i) => i !== index))\n }\n\n const onKeyDown = (e: KeyboardEvent<HTMLInputElement>) => {\n if (e.key === 'Enter' || e.key === ',') {\n e.preventDefault()\n addTag(draft)\n } else if (e.key === 'Backspace' && draft === '' && tags.length > 0) {\n removeTag(tags.length - 1)\n }\n }\n\n const atMax = max ? tags.length >= max : false\n\n return (\n <div className={cn('flex flex-col gap-1', className)}>\n {label && (\n <label htmlFor={id} className=\"text-xs font-medium text-tollerud-text-muted\">\n {label}\n </label>\n )}\n <div\n className={cn(\n 'flex flex-wrap items-center gap-1.5 rounded px-2.5 py-1.5',\n 'bg-tollerud-surface-raised border',\n 'transition-[border-color] duration-[150ms]',\n 'focus-within:border-tollerud-yellow focus-within:shadow-[0_0_0_1px_#E8D500]',\n error ? 'border-tollerud-error' : 'border-tollerud-border',\n disabled && 'opacity-50 pointer-events-none'\n )}\n >\n {tags.map((tag, i) => (\n <span\n key={`${tag}-${i}`}\n className=\"inline-flex items-center gap-1 rounded-full bg-tollerud-surface-hover px-2.5 py-0.5 text-xs font-medium text-tollerud-text-primary\"\n >\n {tag}\n <button\n type=\"button\"\n aria-label={`Remove ${tag}`}\n onClick={() => removeTag(i)}\n className=\"text-tollerud-text-muted hover:text-tollerud-text-primary transition-colors duration-[150ms]\"\n >\n <X size={12} />\n </button>\n </span>\n ))}\n <input\n id={id}\n value={draft}\n disabled={disabled || atMax}\n onChange={(e) => setDraft(e.target.value)}\n onKeyDown={onKeyDown}\n onBlur={() => addTag(draft)}\n placeholder={atMax ? '' : placeholder}\n className={cn(\n 'min-w-[6rem] flex-1 bg-transparent py-0.5 text-sm text-tollerud-text-primary',\n 'placeholder:text-tollerud-text-muted focus:outline-none'\n )}\n />\n </div>\n {error && <p className=\"text-xs text-tollerud-error mt-0.5\">{error}</p>}\n </div>\n )\n}\nTagInput.displayName = 'TagInput'\n\nexport { TagInput }\n"]}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { cn } from './chunk-WSQNPRGN.js';
|
|
3
|
+
import { forwardRef, useId } from 'react';
|
|
4
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
5
|
+
|
|
6
|
+
var AreaChart = forwardRef(
|
|
7
|
+
({ className, data, height = 180, ...props }, ref) => {
|
|
8
|
+
const gradientId = useId().replace(/:/g, "");
|
|
9
|
+
const w = 520;
|
|
10
|
+
const h = height;
|
|
11
|
+
const pad = 8;
|
|
12
|
+
const max = Math.max(...data) * 1.1;
|
|
13
|
+
const min = Math.min(...data, 0);
|
|
14
|
+
const span = Math.max(data.length - 1, 1);
|
|
15
|
+
const x = (i) => pad + i / span * (w - pad * 2);
|
|
16
|
+
const y = (v) => h - pad - (v - min) / (max - min || 1) * (h - pad * 2);
|
|
17
|
+
const line = data.map((v, i) => `${x(i)},${y(v)}`).join(" ");
|
|
18
|
+
const area = `${pad},${h - pad} ${line} ${w - pad},${h - pad}`;
|
|
19
|
+
return /* @__PURE__ */ jsx("div", { ref, className: cn("w-full", className), ...props, children: /* @__PURE__ */ jsxs(
|
|
20
|
+
"svg",
|
|
21
|
+
{
|
|
22
|
+
viewBox: `0 0 ${w} ${h}`,
|
|
23
|
+
className: "w-full",
|
|
24
|
+
style: { height },
|
|
25
|
+
preserveAspectRatio: "none",
|
|
26
|
+
role: "img",
|
|
27
|
+
"aria-hidden": "true",
|
|
28
|
+
children: [
|
|
29
|
+
/* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsxs("linearGradient", { id: gradientId, x1: "0", y1: "0", x2: "0", y2: "1", children: [
|
|
30
|
+
/* @__PURE__ */ jsx("stop", { offset: "0%", stopColor: "#E8D500", stopOpacity: "0.30" }),
|
|
31
|
+
/* @__PURE__ */ jsx("stop", { offset: "100%", stopColor: "#E8D500", stopOpacity: "0" })
|
|
32
|
+
] }) }),
|
|
33
|
+
[0.25, 0.5, 0.75].map((g, i) => /* @__PURE__ */ jsx(
|
|
34
|
+
"line",
|
|
35
|
+
{
|
|
36
|
+
x1: pad,
|
|
37
|
+
x2: w - pad,
|
|
38
|
+
y1: h * g,
|
|
39
|
+
y2: h * g,
|
|
40
|
+
stroke: "var(--chart-grid)",
|
|
41
|
+
strokeWidth: "1"
|
|
42
|
+
},
|
|
43
|
+
i
|
|
44
|
+
)),
|
|
45
|
+
/* @__PURE__ */ jsx("polygon", { points: area, fill: `url(#${gradientId})` }),
|
|
46
|
+
/* @__PURE__ */ jsx(
|
|
47
|
+
"polyline",
|
|
48
|
+
{
|
|
49
|
+
points: line,
|
|
50
|
+
fill: "none",
|
|
51
|
+
stroke: "#E8D500",
|
|
52
|
+
strokeWidth: "2",
|
|
53
|
+
strokeLinecap: "round",
|
|
54
|
+
strokeLinejoin: "round"
|
|
55
|
+
}
|
|
56
|
+
),
|
|
57
|
+
data.map((v, i) => /* @__PURE__ */ jsx(
|
|
58
|
+
"circle",
|
|
59
|
+
{
|
|
60
|
+
cx: x(i),
|
|
61
|
+
cy: y(v),
|
|
62
|
+
r: "2.5",
|
|
63
|
+
fill: "var(--card)",
|
|
64
|
+
stroke: "#E8D500",
|
|
65
|
+
strokeWidth: "1.5"
|
|
66
|
+
},
|
|
67
|
+
i
|
|
68
|
+
))
|
|
69
|
+
]
|
|
70
|
+
}
|
|
71
|
+
) });
|
|
72
|
+
}
|
|
73
|
+
);
|
|
74
|
+
AreaChart.displayName = "AreaChart";
|
|
75
|
+
|
|
76
|
+
export { AreaChart };
|
|
77
|
+
//# sourceMappingURL=chunk-6PZKU6ZL.js.map
|
|
78
|
+
//# sourceMappingURL=chunk-6PZKU6ZL.js.map
|