@blurrow/ui 0.2.0 → 0.2.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/README.md +48 -36
- package/dist/Accordion.d.ts +17 -0
- package/dist/Accordion.js +138 -0
- package/dist/Accordion.js.map +1 -0
- package/dist/Alert.d.ts +13 -0
- package/dist/Alert.js +69 -0
- package/dist/Alert.js.map +1 -0
- package/dist/AuthorCard.d.ts +12 -0
- package/dist/AuthorCard.js +57 -0
- package/dist/AuthorCard.js.map +1 -0
- package/dist/Avatar.d.ts +21 -0
- package/dist/Avatar.js +96 -0
- package/dist/Avatar.js.map +1 -0
- package/dist/Badge.d.ts +12 -0
- package/dist/Badge.js +46 -0
- package/dist/Badge.js.map +1 -0
- package/dist/Banner.d.ts +15 -0
- package/dist/Banner.js +68 -0
- package/dist/Banner.js.map +1 -0
- package/dist/Breadcrumb.d.ts +13 -0
- package/dist/Breadcrumb.js +45 -0
- package/dist/Breadcrumb.js.map +1 -0
- package/dist/Button.d.ts +19 -0
- package/dist/Button.js +282 -0
- package/dist/Button.js.map +1 -0
- package/dist/ButtonGroup.d.ts +19 -0
- package/dist/ButtonGroup.js +62 -0
- package/dist/ButtonGroup.js.map +1 -0
- package/dist/Card.d.ts +40 -0
- package/dist/Card.js +175 -0
- package/dist/Card.js.map +1 -0
- package/dist/CardShell.d.ts +18 -0
- package/dist/CardShell.js +58 -0
- package/dist/CardShell.js.map +1 -0
- package/dist/Carousel.d.ts +22 -0
- package/dist/Carousel.js +247 -0
- package/dist/Carousel.js.map +1 -0
- package/dist/Checkbox.d.ts +15 -0
- package/dist/Checkbox.js +84 -0
- package/dist/Checkbox.js.map +1 -0
- package/dist/CloseButton.d.ts +12 -0
- package/dist/CloseButton.js +63 -0
- package/dist/CloseButton.js.map +1 -0
- package/dist/CodeBlock.d.ts +12 -0
- package/dist/CodeBlock.js +221 -0
- package/dist/CodeBlock.js.map +1 -0
- package/dist/ColorPicker.d.ts +24 -0
- package/dist/ColorPicker.js +366 -0
- package/dist/ColorPicker.js.map +1 -0
- package/dist/Combobox.d.ts +34 -0
- package/dist/Combobox.js +255 -0
- package/dist/Combobox.js.map +1 -0
- package/dist/CommandPalette.d.ts +25 -0
- package/dist/CommandPalette.js +304 -0
- package/dist/CommandPalette.js.map +1 -0
- package/dist/ContextMenu.d.ts +16 -0
- package/dist/ContextMenu.js +209 -0
- package/dist/ContextMenu.js.map +1 -0
- package/dist/DataList.d.ts +15 -0
- package/dist/DataList.js +42 -0
- package/dist/DataList.js.map +1 -0
- package/dist/DatePicker.d.ts +65 -0
- package/dist/DatePicker.js +391 -0
- package/dist/DatePicker.js.map +1 -0
- package/dist/DateRangePicker.d.ts +34 -0
- package/dist/DateRangePicker.js +180 -0
- package/dist/DateRangePicker.js.map +1 -0
- package/dist/Drawer.d.ts +17 -0
- package/dist/Drawer.js +132 -0
- package/dist/Drawer.js.map +1 -0
- package/dist/DropdownMenu.d.ts +23 -0
- package/dist/DropdownMenu.js +185 -0
- package/dist/DropdownMenu.js.map +1 -0
- package/dist/EmptyState.d.ts +13 -0
- package/dist/EmptyState.js +55 -0
- package/dist/EmptyState.js.map +1 -0
- package/dist/FieldMessage.d.ts +26 -0
- package/dist/FieldMessage.js +95 -0
- package/dist/FieldMessage.js.map +1 -0
- package/dist/FileUpload.d.ts +32 -0
- package/dist/FileUpload.js +253 -0
- package/dist/FileUpload.js.map +1 -0
- package/dist/Floating.d.ts +32 -0
- package/dist/Floating.js +95 -0
- package/dist/Floating.js.map +1 -0
- package/dist/HoverCard.d.ts +18 -0
- package/dist/HoverCard.js +90 -0
- package/dist/HoverCard.js.map +1 -0
- package/dist/Input.d.ts +17 -0
- package/dist/Input.js +96 -0
- package/dist/Input.js.map +1 -0
- package/dist/Kbd.d.ts +9 -0
- package/dist/Kbd.js +24 -0
- package/dist/Kbd.js.map +1 -0
- package/dist/Modal.d.ts +15 -0
- package/dist/Modal.js +109 -0
- package/dist/Modal.js.map +1 -0
- package/dist/NumberInput.d.ts +23 -0
- package/dist/NumberInput.js +162 -0
- package/dist/NumberInput.js.map +1 -0
- package/dist/OtpInput.d.ts +26 -0
- package/dist/OtpInput.js +173 -0
- package/dist/OtpInput.js.map +1 -0
- package/dist/Pagination.d.ts +11 -0
- package/dist/Pagination.js +148 -0
- package/dist/Pagination.js.map +1 -0
- package/dist/Popover.d.ts +13 -0
- package/dist/Popover.js +98 -0
- package/dist/Popover.js.map +1 -0
- package/dist/Progress.d.ts +12 -0
- package/dist/Progress.js +61 -0
- package/dist/Progress.js.map +1 -0
- package/dist/QuoteCard.d.ts +13 -0
- package/dist/QuoteCard.js +92 -0
- package/dist/QuoteCard.js.map +1 -0
- package/dist/Radio.d.ts +19 -0
- package/dist/Radio.js +161 -0
- package/dist/Radio.js.map +1 -0
- package/dist/RadioCards.d.ts +27 -0
- package/dist/RadioCards.js +205 -0
- package/dist/RadioCards.js.map +1 -0
- package/dist/ReactionBar.d.ts +15 -0
- package/dist/ReactionBar.js +92 -0
- package/dist/ReactionBar.js.map +1 -0
- package/dist/ReadingProgress.d.ts +8 -0
- package/dist/ReadingProgress.js +51 -0
- package/dist/ReadingProgress.js.map +1 -0
- package/dist/ReadingTime.d.ts +9 -0
- package/dist/ReadingTime.js +39 -0
- package/dist/ReadingTime.js.map +1 -0
- package/dist/Select.d.ts +20 -0
- package/dist/Select.js +244 -0
- package/dist/Select.js.map +1 -0
- package/dist/Separator.d.ts +14 -0
- package/dist/Separator.js +33 -0
- package/dist/Separator.js.map +1 -0
- package/dist/ShareButtons.d.ts +10 -0
- package/dist/ShareButtons.js +107 -0
- package/dist/ShareButtons.js.map +1 -0
- package/dist/Sidebar.d.ts +30 -0
- package/dist/Sidebar.js +140 -0
- package/dist/Sidebar.js.map +1 -0
- package/dist/Skeleton.d.ts +15 -0
- package/dist/Skeleton.js +67 -0
- package/dist/Skeleton.js.map +1 -0
- package/dist/Slider.d.ts +27 -0
- package/dist/Slider.js +182 -0
- package/dist/Slider.js.map +1 -0
- package/dist/Spinner.d.ts +12 -0
- package/dist/Spinner.js +24 -0
- package/dist/Spinner.js.map +1 -0
- package/dist/SpotlightCard.d.ts +17 -0
- package/dist/SpotlightCard.js +87 -0
- package/dist/SpotlightCard.js.map +1 -0
- package/dist/Stat.d.ts +19 -0
- package/dist/Stat.js +71 -0
- package/dist/Stat.js.map +1 -0
- package/dist/StatCard.d.ts +24 -0
- package/dist/StatCard.js +212 -0
- package/dist/StatCard.js.map +1 -0
- package/dist/Steps.d.ts +14 -0
- package/dist/Steps.js +94 -0
- package/dist/Steps.js.map +1 -0
- package/dist/Table.d.ts +21 -0
- package/dist/Table.js +93 -0
- package/dist/Table.js.map +1 -0
- package/dist/TableOfContents.d.ts +17 -0
- package/dist/TableOfContents.js +92 -0
- package/dist/TableOfContents.js.map +1 -0
- package/dist/Tabs.d.ts +17 -0
- package/dist/Tabs.js +123 -0
- package/dist/Tabs.js.map +1 -0
- package/dist/TagInput.d.ts +16 -0
- package/dist/TagInput.js +169 -0
- package/dist/TagInput.js.map +1 -0
- package/dist/Textarea.d.ts +13 -0
- package/dist/Textarea.js +74 -0
- package/dist/Textarea.js.map +1 -0
- package/dist/TimePicker.d.ts +28 -0
- package/dist/TimePicker.js +264 -0
- package/dist/TimePicker.js.map +1 -0
- package/dist/Timeline.d.ts +19 -0
- package/dist/Timeline.js +76 -0
- package/dist/Timeline.js.map +1 -0
- package/dist/Toast.d.ts +18 -0
- package/dist/Toast.js +318 -0
- package/dist/Toast.js.map +1 -0
- package/dist/Toggle.d.ts +13 -0
- package/dist/Toggle.js +84 -0
- package/dist/Toggle.js.map +1 -0
- package/dist/Tooltip.d.ts +13 -0
- package/dist/Tooltip.js +138 -0
- package/dist/Tooltip.js.map +1 -0
- package/dist/cli.js +172 -5
- package/dist/index.d.ts +68 -631
- package/dist/index.js +67 -5558
- package/dist/index.js.map +1 -1
- package/dist/registry/Accordion.tsx +6 -6
- package/dist/registry/Alert.tsx +13 -10
- package/dist/registry/AuthorCard.tsx +7 -7
- package/dist/registry/Avatar.tsx +5 -5
- package/dist/registry/Badge.tsx +12 -15
- package/dist/registry/Banner.tsx +15 -18
- package/dist/registry/Breadcrumb.tsx +3 -3
- package/dist/registry/Button.tsx +58 -69
- package/dist/registry/ButtonGroup.tsx +9 -9
- package/dist/registry/Card.tsx +15 -15
- package/dist/registry/CardShell.tsx +6 -6
- package/dist/registry/Carousel.tsx +19 -15
- package/dist/registry/Checkbox.tsx +14 -9
- package/dist/registry/CloseButton.tsx +2 -2
- package/dist/registry/CodeBlock.tsx +15 -15
- package/dist/registry/ColorPicker.tsx +404 -0
- package/dist/registry/Combobox.tsx +318 -0
- package/dist/registry/CommandPalette.tsx +31 -24
- package/dist/registry/ContextMenu.tsx +241 -0
- package/dist/registry/DataList.tsx +4 -4
- package/dist/registry/DatePicker.tsx +494 -0
- package/dist/registry/DateRangePicker.tsx +232 -0
- package/dist/registry/Drawer.tsx +17 -15
- package/dist/registry/DropdownMenu.tsx +39 -77
- package/dist/registry/EmptyState.tsx +8 -8
- package/dist/registry/FieldMessage.tsx +123 -0
- package/dist/registry/FileUpload.tsx +318 -0
- package/dist/registry/Floating.tsx +134 -0
- package/dist/registry/HoverCard.tsx +113 -0
- package/dist/registry/Input.tsx +54 -43
- package/dist/registry/Kbd.tsx +4 -5
- package/dist/registry/Modal.tsx +17 -15
- package/dist/registry/NumberInput.tsx +183 -0
- package/dist/registry/OtpInput.tsx +219 -0
- package/dist/registry/Pagination.tsx +15 -18
- package/dist/registry/Popover.tsx +40 -45
- package/dist/registry/Progress.tsx +4 -4
- package/dist/registry/QuoteCard.tsx +7 -7
- package/dist/registry/Radio.tsx +24 -21
- package/dist/registry/RadioCards.tsx +247 -0
- package/dist/registry/ReactionBar.tsx +5 -5
- package/dist/registry/ReadingProgress.tsx +2 -2
- package/dist/registry/ReadingTime.tsx +2 -2
- package/dist/registry/Select.tsx +28 -53
- package/dist/registry/Separator.tsx +52 -0
- package/dist/registry/ShareButtons.tsx +2 -2
- package/dist/registry/Sidebar.tsx +18 -18
- package/dist/registry/Skeleton.tsx +1 -1
- package/dist/registry/Slider.tsx +229 -0
- package/dist/registry/Spinner.tsx +32 -0
- package/dist/registry/SpotlightCard.tsx +6 -6
- package/dist/registry/Stat.tsx +4 -4
- package/dist/registry/StatCard.tsx +19 -19
- package/dist/registry/Steps.tsx +7 -7
- package/dist/registry/Table.tsx +12 -10
- package/dist/registry/TableOfContents.tsx +8 -8
- package/dist/registry/Tabs.tsx +6 -6
- package/dist/registry/TagInput.tsx +9 -9
- package/dist/registry/Textarea.tsx +5 -5
- package/dist/registry/TimePicker.tsx +315 -0
- package/dist/registry/Timeline.tsx +14 -14
- package/dist/registry/Toast.tsx +15 -12
- package/dist/registry/Toggle.tsx +7 -10
- package/dist/registry/Tooltip.tsx +21 -73
- package/dist/registry/styles.css +868 -62
- package/dist/registry/useFloatingPanel.ts +112 -0
- package/dist/styles.css +868 -62
- package/dist/useFloatingPanel.d.ts +24 -0
- package/dist/useFloatingPanel.js +89 -0
- package/dist/useFloatingPanel.js.map +1 -0
- package/dist/useModalBehavior.d.ts +15 -0
- package/dist/useModalBehavior.js +57 -0
- package/dist/useModalBehavior.js.map +1 -0
- package/package.json +1 -1
package/dist/Steps.js
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
// ../../components/ui/Steps.tsx
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
function CheckIcon() {
|
|
4
|
+
return /* @__PURE__ */ jsx(
|
|
5
|
+
"svg",
|
|
6
|
+
{
|
|
7
|
+
width: "13",
|
|
8
|
+
height: "13",
|
|
9
|
+
viewBox: "0 0 24 24",
|
|
10
|
+
fill: "none",
|
|
11
|
+
stroke: "currentColor",
|
|
12
|
+
strokeWidth: "2.75",
|
|
13
|
+
strokeLinecap: "round",
|
|
14
|
+
strokeLinejoin: "round",
|
|
15
|
+
children: /* @__PURE__ */ jsx("polyline", { points: "20 6 9 17 4 12" })
|
|
16
|
+
}
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
function Steps({ steps, current, className = "" }) {
|
|
20
|
+
return /* @__PURE__ */ jsx("ol", { className: ["flex items-start", className].filter(Boolean).join(" "), children: steps.map((step, i) => {
|
|
21
|
+
const isCompleted = i < current;
|
|
22
|
+
const isCurrent = i === current;
|
|
23
|
+
const reached = isCompleted || isCurrent;
|
|
24
|
+
const isLast = i === steps.length - 1;
|
|
25
|
+
return /* @__PURE__ */ jsxs(
|
|
26
|
+
"li",
|
|
27
|
+
{
|
|
28
|
+
"aria-current": isCurrent ? "step" : void 0,
|
|
29
|
+
className: "relative flex-1 min-w-0 flex flex-col items-center text-center",
|
|
30
|
+
children: [
|
|
31
|
+
!isLast && /* @__PURE__ */ jsx(
|
|
32
|
+
"span",
|
|
33
|
+
{
|
|
34
|
+
"aria-hidden": true,
|
|
35
|
+
className: "absolute top-[15px] h-1 -translate-y-1/2 rounded-full overflow-hidden",
|
|
36
|
+
style: {
|
|
37
|
+
left: "calc(50% + 25px)",
|
|
38
|
+
width: "calc(100% - 50px)",
|
|
39
|
+
background: "var(--well)",
|
|
40
|
+
boxShadow: "var(--well-shadow)"
|
|
41
|
+
},
|
|
42
|
+
children: /* @__PURE__ */ jsx(
|
|
43
|
+
"span",
|
|
44
|
+
{
|
|
45
|
+
className: "block h-full rounded-full origin-left transition-transform duration-500 ease-[var(--ease-out-soft)]",
|
|
46
|
+
style: {
|
|
47
|
+
background: "var(--face-inverse)",
|
|
48
|
+
transform: isCompleted ? "scaleX(1)" : "scaleX(0)"
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
)
|
|
52
|
+
}
|
|
53
|
+
),
|
|
54
|
+
/* @__PURE__ */ jsxs(
|
|
55
|
+
"span",
|
|
56
|
+
{
|
|
57
|
+
className: [
|
|
58
|
+
"relative w-[30px] h-[30px] rounded-full flex items-center justify-center text-[12.5px] font-semibold tabular-nums shrink-0",
|
|
59
|
+
"transition-[box-shadow,color] duration-300",
|
|
60
|
+
reached ? "text-ink-inverse" : "text-ink-faint"
|
|
61
|
+
].join(" "),
|
|
62
|
+
style: {
|
|
63
|
+
background: reached ? "var(--face-inverse)" : "var(--field)",
|
|
64
|
+
boxShadow: isCurrent ? "var(--face-inverse-shadow), var(--halo)" : reached ? "var(--face-inverse-shadow)" : "var(--field-shadow)"
|
|
65
|
+
},
|
|
66
|
+
children: [
|
|
67
|
+
isCompleted ? /* @__PURE__ */ jsx(CheckIcon, {}) : i + 1,
|
|
68
|
+
/* @__PURE__ */ jsx("span", { className: "sr-only", children: isCompleted ? " (completed)" : "" })
|
|
69
|
+
]
|
|
70
|
+
}
|
|
71
|
+
),
|
|
72
|
+
/* @__PURE__ */ jsxs("span", { className: "mt-3 px-1.5 flex flex-col gap-0.5", children: [
|
|
73
|
+
/* @__PURE__ */ jsx(
|
|
74
|
+
"span",
|
|
75
|
+
{
|
|
76
|
+
className: [
|
|
77
|
+
"text-[13px] font-medium leading-tight transition-colors duration-200",
|
|
78
|
+
reached ? "text-ink" : "text-ink-muted"
|
|
79
|
+
].join(" "),
|
|
80
|
+
children: step.label
|
|
81
|
+
}
|
|
82
|
+
),
|
|
83
|
+
step.description && /* @__PURE__ */ jsx("span", { className: "text-[12px] text-ink-faint leading-snug", children: step.description })
|
|
84
|
+
] })
|
|
85
|
+
]
|
|
86
|
+
},
|
|
87
|
+
i
|
|
88
|
+
);
|
|
89
|
+
}) });
|
|
90
|
+
}
|
|
91
|
+
export {
|
|
92
|
+
Steps
|
|
93
|
+
};
|
|
94
|
+
//# sourceMappingURL=Steps.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../components/ui/Steps.tsx"],"sourcesContent":["import React from \"react\";\n\ninterface StepItem {\n label: string;\n description?: string;\n}\n\ninterface StepsProps {\n steps: StepItem[];\n current: number;\n className?: string;\n}\n\nfunction CheckIcon() {\n return (\n <svg\n width=\"13\"\n height=\"13\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.75\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <polyline points=\"20 6 9 17 4 12\" />\n </svg>\n );\n}\n\n/* Upcoming steps are sunken (not yet filled in), done and current steps\n are dark raised faces; the current one also wears a soft halo. Each step owns an equal column, so labels get\n real width instead of being squeezed under a 32px circle. */\nexport function Steps({ steps, current, className = \"\" }: StepsProps) {\n return (\n <ol className={[\"flex items-start\", className].filter(Boolean).join(\" \")}>\n {steps.map((step, i) => {\n const isCompleted = i < current;\n const isCurrent = i === current;\n const reached = isCompleted || isCurrent;\n const isLast = i === steps.length - 1;\n\n return (\n <li\n key={i}\n aria-current={isCurrent ? \"step\" : undefined}\n className=\"relative flex-1 min-w-0 flex flex-col items-center text-center\"\n >\n {/* One groove per gap, running between the two circles' edges\n (columns are equal, so the next centre is exactly 100% away) */}\n {!isLast && (\n <span\n aria-hidden\n className=\"absolute top-[15px] h-1 -translate-y-1/2 rounded-full overflow-hidden\"\n style={{\n left: \"calc(50% + 25px)\",\n width: \"calc(100% - 50px)\",\n background: \"var(--well)\",\n boxShadow: \"var(--well-shadow)\",\n }}\n >\n <span\n className=\"block h-full rounded-full origin-left transition-transform duration-500 ease-[var(--ease-out-soft)]\"\n style={{\n background: \"var(--face-inverse)\",\n transform: isCompleted ? \"scaleX(1)\" : \"scaleX(0)\",\n }}\n />\n </span>\n )}\n\n <span\n className={[\n \"relative w-[30px] h-[30px] rounded-full flex items-center justify-center text-[12.5px] font-semibold tabular-nums shrink-0\",\n \"transition-[box-shadow,color] duration-300\",\n reached ? \"text-ink-inverse\" : \"text-ink-faint\",\n ].join(\" \")}\n style={{\n background: reached ? \"var(--face-inverse)\" : \"var(--field)\",\n boxShadow: isCurrent\n ? \"var(--face-inverse-shadow), var(--halo)\"\n : reached\n ? \"var(--face-inverse-shadow)\"\n : \"var(--field-shadow)\",\n }}\n >\n {isCompleted ? <CheckIcon /> : i + 1}\n <span className=\"sr-only\">{isCompleted ? \" (completed)\" : \"\"}</span>\n </span>\n\n <span className=\"mt-3 px-1.5 flex flex-col gap-0.5\">\n <span\n className={[\n \"text-[13px] font-medium leading-tight transition-colors duration-200\",\n reached ? \"text-ink\" : \"text-ink-muted\",\n ].join(\" \")}\n >\n {step.label}\n </span>\n {step.description && (\n <span className=\"text-[12px] text-ink-faint leading-snug\">{step.description}</span>\n )}\n </span>\n </li>\n );\n })}\n </ol>\n );\n}\n"],"mappings":";AAyBM,cA8CM,YA9CN;AAZN,SAAS,YAAY;AACnB,SACE;AAAA,IAAC;AAAA;AAAA,MACC,OAAM;AAAA,MACN,QAAO;AAAA,MACP,SAAQ;AAAA,MACR,MAAK;AAAA,MACL,QAAO;AAAA,MACP,aAAY;AAAA,MACZ,eAAc;AAAA,MACd,gBAAe;AAAA,MAEf,8BAAC,cAAS,QAAO,kBAAiB;AAAA;AAAA,EACpC;AAEJ;AAKO,SAAS,MAAM,EAAE,OAAO,SAAS,YAAY,GAAG,GAAe;AACpE,SACE,oBAAC,QAAG,WAAW,CAAC,oBAAoB,SAAS,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG,GACpE,gBAAM,IAAI,CAAC,MAAM,MAAM;AACtB,UAAM,cAAc,IAAI;AACxB,UAAM,YAAY,MAAM;AACxB,UAAM,UAAU,eAAe;AAC/B,UAAM,SAAS,MAAM,MAAM,SAAS;AAEpC,WACE;AAAA,MAAC;AAAA;AAAA,QAEC,gBAAc,YAAY,SAAS;AAAA,QACnC,WAAU;AAAA,QAIT;AAAA,WAAC,UACA;AAAA,YAAC;AAAA;AAAA,cACC,eAAW;AAAA,cACX,WAAU;AAAA,cACV,OAAO;AAAA,gBACL,MAAM;AAAA,gBACN,OAAO;AAAA,gBACP,YAAY;AAAA,gBACZ,WAAW;AAAA,cACb;AAAA,cAEA;AAAA,gBAAC;AAAA;AAAA,kBACC,WAAU;AAAA,kBACV,OAAO;AAAA,oBACL,YAAY;AAAA,oBACZ,WAAW,cAAc,cAAc;AAAA,kBACzC;AAAA;AAAA,cACF;AAAA;AAAA,UACF;AAAA,UAGF;AAAA,YAAC;AAAA;AAAA,cACC,WAAW;AAAA,gBACT;AAAA,gBACA;AAAA,gBACA,UAAU,qBAAqB;AAAA,cACjC,EAAE,KAAK,GAAG;AAAA,cACV,OAAO;AAAA,gBACL,YAAY,UAAU,wBAAwB;AAAA,gBAC9C,WAAW,YACP,4CACA,UACE,+BACA;AAAA,cACR;AAAA,cAEC;AAAA,8BAAc,oBAAC,aAAU,IAAK,IAAI;AAAA,gBACnC,oBAAC,UAAK,WAAU,WAAW,wBAAc,iBAAiB,IAAG;AAAA;AAAA;AAAA,UAC/D;AAAA,UAEA,qBAAC,UAAK,WAAU,qCACd;AAAA;AAAA,cAAC;AAAA;AAAA,gBACC,WAAW;AAAA,kBACT;AAAA,kBACA,UAAU,aAAa;AAAA,gBACzB,EAAE,KAAK,GAAG;AAAA,gBAET,eAAK;AAAA;AAAA,YACR;AAAA,YACC,KAAK,eACJ,oBAAC,UAAK,WAAU,2CAA2C,eAAK,aAAY;AAAA,aAEhF;AAAA;AAAA;AAAA,MA1DK;AAAA,IA2DP;AAAA,EAEJ,CAAC,GACH;AAEJ;","names":[]}
|
package/dist/Table.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
|
|
4
|
+
interface Column<T> {
|
|
5
|
+
key: keyof T | string;
|
|
6
|
+
label: string;
|
|
7
|
+
align?: "left" | "right" | "center";
|
|
8
|
+
render?: (value: unknown, row: T) => React.ReactNode;
|
|
9
|
+
width?: string;
|
|
10
|
+
}
|
|
11
|
+
interface TableProps<T extends Record<string, unknown>> {
|
|
12
|
+
columns: Column<T>[];
|
|
13
|
+
rows: T[];
|
|
14
|
+
title?: string;
|
|
15
|
+
description?: string;
|
|
16
|
+
className?: string;
|
|
17
|
+
onRowClick?: (row: T) => void;
|
|
18
|
+
}
|
|
19
|
+
declare function Table<T extends Record<string, unknown>>({ columns, rows, title, description, className, onRowClick, }: TableProps<T>): react_jsx_runtime.JSX.Element;
|
|
20
|
+
|
|
21
|
+
export { Table };
|
package/dist/Table.js
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// ../../components/ui/Table.tsx
|
|
4
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
+
var alignClass = (align) => align === "right" ? "text-right" : align === "center" ? "text-center" : "text-left";
|
|
6
|
+
function Table({
|
|
7
|
+
columns,
|
|
8
|
+
rows,
|
|
9
|
+
title,
|
|
10
|
+
description,
|
|
11
|
+
className = "",
|
|
12
|
+
onRowClick
|
|
13
|
+
}) {
|
|
14
|
+
return /* @__PURE__ */ jsxs(
|
|
15
|
+
"div",
|
|
16
|
+
{
|
|
17
|
+
className: ["w-full rounded-[18px] p-1.5", title || description ? "pt-0" : "", className].join(" "),
|
|
18
|
+
style: { background: "var(--panel-bezel)", boxShadow: "var(--panel-shadow)" },
|
|
19
|
+
children: [
|
|
20
|
+
(title || description) && /* @__PURE__ */ jsxs("div", { className: "px-3.5 pt-3.5 pb-3", children: [
|
|
21
|
+
title && /* @__PURE__ */ jsx("p", { className: "text-[13px] font-semibold text-ink tracking-[-0.01em]", children: title }),
|
|
22
|
+
description && /* @__PURE__ */ jsx("p", { className: "text-[12px] text-ink-muted mt-0.5", children: description })
|
|
23
|
+
] }),
|
|
24
|
+
/* @__PURE__ */ jsx(
|
|
25
|
+
"div",
|
|
26
|
+
{
|
|
27
|
+
className: "bg-panel-face rounded-[13px] overflow-x-auto scroll-thin",
|
|
28
|
+
style: { boxShadow: "var(--panel-face-shadow)" },
|
|
29
|
+
children: /* @__PURE__ */ jsxs("table", { className: "w-full text-left border-collapse", children: [
|
|
30
|
+
title && /* @__PURE__ */ jsx("caption", { className: "sr-only", children: title }),
|
|
31
|
+
/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsx("tr", { className: "border-b border-line", children: columns.map((col) => /* @__PURE__ */ jsx(
|
|
32
|
+
"th",
|
|
33
|
+
{
|
|
34
|
+
scope: "col",
|
|
35
|
+
style: col.width ? { width: col.width } : void 0,
|
|
36
|
+
className: [
|
|
37
|
+
"px-4 pt-3 pb-2.5 text-[12px] font-medium text-ink-muted lowercase whitespace-nowrap",
|
|
38
|
+
alignClass(col.align)
|
|
39
|
+
].join(" "),
|
|
40
|
+
children: col.label
|
|
41
|
+
},
|
|
42
|
+
String(col.key)
|
|
43
|
+
)) }) }),
|
|
44
|
+
/* @__PURE__ */ jsxs("tbody", { children: [
|
|
45
|
+
rows.map((row, ri) => /* @__PURE__ */ jsx(
|
|
46
|
+
"tr",
|
|
47
|
+
{
|
|
48
|
+
onClick: () => onRowClick?.(row),
|
|
49
|
+
tabIndex: onRowClick ? 0 : void 0,
|
|
50
|
+
onKeyDown: onRowClick ? (e) => {
|
|
51
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
52
|
+
e.preventDefault();
|
|
53
|
+
onRowClick(row);
|
|
54
|
+
}
|
|
55
|
+
} : void 0,
|
|
56
|
+
className: [
|
|
57
|
+
"border-b border-line last:border-0 transition-colors duration-100",
|
|
58
|
+
onRowClick ? "cursor-pointer hover:bg-surface-hover focus-visible:bg-surface-hover outline-none focus-visible:shadow-[inset_2px_0_0_var(--ink)]" : ""
|
|
59
|
+
].join(" "),
|
|
60
|
+
children: columns.map((col, ci) => {
|
|
61
|
+
const val = row[col.key];
|
|
62
|
+
return /* @__PURE__ */ jsx(
|
|
63
|
+
"td",
|
|
64
|
+
{
|
|
65
|
+
className: [
|
|
66
|
+
"px-4 py-3 text-[13px]",
|
|
67
|
+
ci === 0 ? "font-medium text-ink" : "text-ink-body tabular-nums",
|
|
68
|
+
alignClass(col.align)
|
|
69
|
+
].join(" "),
|
|
70
|
+
children: col.render ? col.render(val, row) : String(val ?? "")
|
|
71
|
+
},
|
|
72
|
+
String(col.key)
|
|
73
|
+
);
|
|
74
|
+
})
|
|
75
|
+
},
|
|
76
|
+
ri
|
|
77
|
+
)),
|
|
78
|
+
rows.length === 0 && /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsxs("td", { colSpan: columns.length, className: "px-5 py-12 text-center", children: [
|
|
79
|
+
/* @__PURE__ */ jsx("p", { className: "text-[13px] font-medium text-ink-label", children: "nothing here yet" }),
|
|
80
|
+
/* @__PURE__ */ jsx("p", { className: "text-[12px] text-ink-muted mt-0.5", children: "rows will show up here once there are some." })
|
|
81
|
+
] }) })
|
|
82
|
+
] })
|
|
83
|
+
] })
|
|
84
|
+
}
|
|
85
|
+
)
|
|
86
|
+
]
|
|
87
|
+
}
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
export {
|
|
91
|
+
Table
|
|
92
|
+
};
|
|
93
|
+
//# sourceMappingURL=Table.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../components/ui/Table.tsx"],"sourcesContent":["\"use client\";\n\nimport React from \"react\";\n\ninterface Column<T> {\n key: keyof T | string;\n label: string;\n align?: \"left\" | \"right\" | \"center\";\n render?: (value: unknown, row: T) => React.ReactNode;\n width?: string;\n}\n\ninterface TableProps<T extends Record<string, unknown>> {\n columns: Column<T>[];\n rows: T[];\n title?: string;\n description?: string;\n className?: string;\n onRowClick?: (row: T) => void;\n}\n\nconst alignClass = (align?: \"left\" | \"right\" | \"center\") =>\n align === \"right\" ? \"text-right\" : align === \"center\" ? \"text-center\" : \"text-left\";\n\n/* Title and column headers live in the bezel; rows sit on the raised face. */\nexport function Table<T extends Record<string, unknown>>({\n columns,\n rows,\n title,\n description,\n className = \"\",\n onRowClick,\n}: TableProps<T>) {\n return (\n <div\n className={[\"w-full rounded-[18px] p-1.5\", title || description ? \"pt-0\" : \"\", className].join(\" \")}\n style={{ background: \"var(--panel-bezel)\", boxShadow: \"var(--panel-shadow)\" }}\n >\n {(title || description) && (\n <div className=\"px-3.5 pt-3.5 pb-3\">\n {title && <p className=\"text-[13px] font-semibold text-ink tracking-[-0.01em]\">{title}</p>}\n {description && <p className=\"text-[12px] text-ink-muted mt-0.5\">{description}</p>}\n </div>\n )}\n\n <div\n className=\"bg-panel-face rounded-[13px] overflow-x-auto scroll-thin\"\n style={{ boxShadow: \"var(--panel-face-shadow)\" }}\n >\n <table className=\"w-full text-left border-collapse\">\n {title && <caption className=\"sr-only\">{title}</caption>}\n <thead>\n <tr className=\"border-b border-line\">\n {columns.map((col) => (\n <th\n key={String(col.key)}\n scope=\"col\"\n style={col.width ? { width: col.width } : undefined}\n className={[\n \"px-4 pt-3 pb-2.5 text-[12px] font-medium text-ink-muted lowercase whitespace-nowrap\",\n alignClass(col.align),\n ].join(\" \")}\n >\n {col.label}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {rows.map((row, ri) => (\n <tr\n key={ri}\n onClick={() => onRowClick?.(row)}\n // Clickable rows are reachable and operable from the keyboard too\n tabIndex={onRowClick ? 0 : undefined}\n onKeyDown={\n onRowClick\n ? (e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n onRowClick(row);\n }\n }\n : undefined\n }\n className={[\n \"border-b border-line last:border-0 transition-colors duration-100\",\n onRowClick\n ? \"cursor-pointer hover:bg-surface-hover focus-visible:bg-surface-hover outline-none focus-visible:shadow-[inset_2px_0_0_var(--ink)]\"\n : \"\",\n ].join(\" \")}\n >\n {columns.map((col, ci) => {\n const val = row[col.key as keyof T] as unknown;\n return (\n <td\n key={String(col.key)}\n className={[\n \"px-4 py-3 text-[13px]\",\n ci === 0 ? \"font-medium text-ink\" : \"text-ink-body tabular-nums\",\n alignClass(col.align),\n ].join(\" \")}\n >\n {col.render ? col.render(val, row) : String(val ?? \"\")}\n </td>\n );\n })}\n </tr>\n ))}\n {rows.length === 0 && (\n <tr>\n <td colSpan={columns.length} className=\"px-5 py-12 text-center\">\n <p className=\"text-[13px] font-medium text-ink-label\">nothing here yet</p>\n <p className=\"text-[12px] text-ink-muted mt-0.5\">rows will show up here once there are some.</p>\n </td>\n </tr>\n )}\n </tbody>\n </table>\n </div>\n </div>\n );\n}\n"],"mappings":";;;AAuCQ,SACY,KADZ;AAlBR,IAAM,aAAa,CAAC,UAClB,UAAU,UAAU,eAAe,UAAU,WAAW,gBAAgB;AAGnE,SAAS,MAAyC;AAAA,EACvD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,YAAY;AAAA,EACZ;AACF,GAAkB;AAChB,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAW,CAAC,+BAA+B,SAAS,cAAc,SAAS,IAAI,SAAS,EAAE,KAAK,GAAG;AAAA,MAClG,OAAO,EAAE,YAAY,sBAAsB,WAAW,sBAAsB;AAAA,MAE1E;AAAA,kBAAS,gBACT,qBAAC,SAAI,WAAU,sBACZ;AAAA,mBAAS,oBAAC,OAAE,WAAU,yDAAyD,iBAAM;AAAA,UACrF,eAAe,oBAAC,OAAE,WAAU,qCAAqC,uBAAY;AAAA,WAChF;AAAA,QAGF;AAAA,UAAC;AAAA;AAAA,YACC,WAAU;AAAA,YACV,OAAO,EAAE,WAAW,2BAA2B;AAAA,YAE/C,+BAAC,WAAM,WAAU,oCACd;AAAA,uBAAS,oBAAC,aAAQ,WAAU,WAAW,iBAAM;AAAA,cAC9C,oBAAC,WACC,8BAAC,QAAG,WAAU,wBACX,kBAAQ,IAAI,CAAC,QACZ;AAAA,gBAAC;AAAA;AAAA,kBAEC,OAAM;AAAA,kBACN,OAAO,IAAI,QAAQ,EAAE,OAAO,IAAI,MAAM,IAAI;AAAA,kBAC1C,WAAW;AAAA,oBACT;AAAA,oBACA,WAAW,IAAI,KAAK;AAAA,kBACtB,EAAE,KAAK,GAAG;AAAA,kBAET,cAAI;AAAA;AAAA,gBARA,OAAO,IAAI,GAAG;AAAA,cASrB,CACD,GACH,GACF;AAAA,cACA,qBAAC,WACE;AAAA,qBAAK,IAAI,CAAC,KAAK,OACd;AAAA,kBAAC;AAAA;AAAA,oBAEC,SAAS,MAAM,aAAa,GAAG;AAAA,oBAE/B,UAAU,aAAa,IAAI;AAAA,oBAC3B,WACE,aACI,CAAC,MAAM;AACL,0BAAI,EAAE,QAAQ,WAAW,EAAE,QAAQ,KAAK;AACtC,0BAAE,eAAe;AACjB,mCAAW,GAAG;AAAA,sBAChB;AAAA,oBACF,IACA;AAAA,oBAEN,WAAW;AAAA,sBACT;AAAA,sBACA,aACI,sIACA;AAAA,oBACN,EAAE,KAAK,GAAG;AAAA,oBAET,kBAAQ,IAAI,CAAC,KAAK,OAAO;AACxB,4BAAM,MAAM,IAAI,IAAI,GAAc;AAClC,6BACE;AAAA,wBAAC;AAAA;AAAA,0BAEC,WAAW;AAAA,4BACT;AAAA,4BACA,OAAO,IAAI,yBAAyB;AAAA,4BACpC,WAAW,IAAI,KAAK;AAAA,0BACtB,EAAE,KAAK,GAAG;AAAA,0BAET,cAAI,SAAS,IAAI,OAAO,KAAK,GAAG,IAAI,OAAO,OAAO,EAAE;AAAA;AAAA,wBAPhD,OAAO,IAAI,GAAG;AAAA,sBAQrB;AAAA,oBAEJ,CAAC;AAAA;AAAA,kBAnCI;AAAA,gBAoCP,CACD;AAAA,gBACA,KAAK,WAAW,KACf,oBAAC,QACC,+BAAC,QAAG,SAAS,QAAQ,QAAQ,WAAU,0BACrC;AAAA,sCAAC,OAAE,WAAU,0CAAyC,8BAAgB;AAAA,kBACtE,oBAAC,OAAE,WAAU,qCAAoC,yDAA2C;AAAA,mBAC9F,GACF;AAAA,iBAEJ;AAAA,eACF;AAAA;AAAA,QACF;AAAA;AAAA;AAAA,EACF;AAEJ;","names":[]}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
|
|
3
|
+
interface TocItem {
|
|
4
|
+
key: string;
|
|
5
|
+
label: string;
|
|
6
|
+
level: 1 | 2 | 3;
|
|
7
|
+
}
|
|
8
|
+
interface TableOfContentsProps {
|
|
9
|
+
items: TocItem[];
|
|
10
|
+
activeKey?: string;
|
|
11
|
+
defaultActiveKey?: string;
|
|
12
|
+
onSelect?: (key: string) => void;
|
|
13
|
+
className?: string;
|
|
14
|
+
}
|
|
15
|
+
declare function TableOfContents({ items, activeKey, defaultActiveKey, onSelect, className, }: TableOfContentsProps): react_jsx_runtime.JSX.Element;
|
|
16
|
+
|
|
17
|
+
export { TableOfContents, type TocItem };
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// ../../components/ui/TableOfContents.tsx
|
|
4
|
+
import { useEffect, useLayoutEffect, useRef, useState } from "react";
|
|
5
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
+
var indent = { 1: 16, 2: 28, 3: 40 };
|
|
7
|
+
function TableOfContents({
|
|
8
|
+
items,
|
|
9
|
+
activeKey,
|
|
10
|
+
defaultActiveKey,
|
|
11
|
+
onSelect,
|
|
12
|
+
className = ""
|
|
13
|
+
}) {
|
|
14
|
+
const [internal, setInternal] = useState(defaultActiveKey ?? items[0]?.key ?? "");
|
|
15
|
+
const current = activeKey !== void 0 ? activeKey : internal;
|
|
16
|
+
const refs = useRef({});
|
|
17
|
+
const [marker, setMarker] = useState(null);
|
|
18
|
+
const [ready, setReady] = useState(false);
|
|
19
|
+
const measure = () => {
|
|
20
|
+
const el = refs.current[current];
|
|
21
|
+
setMarker(el ? { top: el.offsetTop, height: el.offsetHeight } : null);
|
|
22
|
+
};
|
|
23
|
+
useLayoutEffect(() => {
|
|
24
|
+
measure();
|
|
25
|
+
}, [current]);
|
|
26
|
+
useEffect(() => {
|
|
27
|
+
const id = requestAnimationFrame(() => setReady(true));
|
|
28
|
+
return () => cancelAnimationFrame(id);
|
|
29
|
+
}, []);
|
|
30
|
+
const handleSelect = (key) => {
|
|
31
|
+
setInternal(key);
|
|
32
|
+
onSelect?.(key);
|
|
33
|
+
};
|
|
34
|
+
const slide = ready ? "top 360ms var(--ease-out-soft), height 360ms var(--ease-out-soft)" : "none";
|
|
35
|
+
return /* @__PURE__ */ jsx(
|
|
36
|
+
"nav",
|
|
37
|
+
{
|
|
38
|
+
"aria-label": "On this page",
|
|
39
|
+
className: ["rounded-[18px] p-1.5", className].filter(Boolean).join(" "),
|
|
40
|
+
style: { background: "var(--panel-bezel)", boxShadow: "var(--panel-shadow)" },
|
|
41
|
+
children: /* @__PURE__ */ jsxs(
|
|
42
|
+
"div",
|
|
43
|
+
{
|
|
44
|
+
className: "bg-panel-face rounded-[13px] px-5 pt-4 pb-4",
|
|
45
|
+
style: { boxShadow: "var(--panel-face-shadow)" },
|
|
46
|
+
children: [
|
|
47
|
+
/* @__PURE__ */ jsx("p", { "aria-hidden": true, className: "text-[12px] font-medium text-ink-faint mb-3", children: "on this page" }),
|
|
48
|
+
/* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
49
|
+
/* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "absolute left-0 top-0 bottom-0 w-px bg-ink/[0.08]" }),
|
|
50
|
+
marker && /* @__PURE__ */ jsx(
|
|
51
|
+
"span",
|
|
52
|
+
{
|
|
53
|
+
"aria-hidden": true,
|
|
54
|
+
className: "absolute -left-[0.5px] w-[2px] rounded-full bg-ink",
|
|
55
|
+
style: { top: marker.top + 6, height: marker.height - 12, transition: slide }
|
|
56
|
+
}
|
|
57
|
+
),
|
|
58
|
+
items.map((item) => {
|
|
59
|
+
const isActive = current === item.key;
|
|
60
|
+
return /* @__PURE__ */ jsx(
|
|
61
|
+
"button",
|
|
62
|
+
{
|
|
63
|
+
ref: (el) => {
|
|
64
|
+
refs.current[item.key] = el;
|
|
65
|
+
},
|
|
66
|
+
type: "button",
|
|
67
|
+
onClick: () => handleSelect(item.key),
|
|
68
|
+
"aria-current": isActive ? "location" : void 0,
|
|
69
|
+
className: [
|
|
70
|
+
// Weight stays fixed so the active item doesn't reflow its line
|
|
71
|
+
"relative block w-full text-left py-1.5 text-[13px] leading-5 rounded-[6px] cursor-pointer",
|
|
72
|
+
"transition-colors duration-200 outline-none",
|
|
73
|
+
"focus-visible:outline-2 focus-visible:outline-offset-[-2px] focus-visible:outline-ink",
|
|
74
|
+
isActive ? "text-ink font-medium" : item.level === 1 ? "text-ink-body hover:text-ink" : "text-ink-faint hover:text-ink-label"
|
|
75
|
+
].join(" "),
|
|
76
|
+
style: { paddingLeft: indent[item.level] },
|
|
77
|
+
children: item.label
|
|
78
|
+
},
|
|
79
|
+
item.key
|
|
80
|
+
);
|
|
81
|
+
})
|
|
82
|
+
] })
|
|
83
|
+
]
|
|
84
|
+
}
|
|
85
|
+
)
|
|
86
|
+
}
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
export {
|
|
90
|
+
TableOfContents
|
|
91
|
+
};
|
|
92
|
+
//# sourceMappingURL=TableOfContents.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../components/ui/TableOfContents.tsx"],"sourcesContent":["\"use client\";\n\nimport React, { useEffect, useLayoutEffect, useRef, useState } from \"react\";\n\nexport interface TocItem {\n key: string;\n label: string;\n level: 1 | 2 | 3;\n}\n\ninterface TableOfContentsProps {\n items: TocItem[];\n activeKey?: string;\n defaultActiveKey?: string;\n onSelect?: (key: string) => void;\n className?: string;\n}\n\nconst indent: Record<1 | 2 | 3, number> = { 1: 16, 2: 28, 3: 40 };\n\n/* A hairline track runs down the left edge; a slim dark marker glides\n along it to the active heading. Nothing else moves — the active label\n just darkens. */\nexport function TableOfContents({\n items,\n activeKey,\n defaultActiveKey,\n onSelect,\n className = \"\",\n}: TableOfContentsProps) {\n const [internal, setInternal] = useState(defaultActiveKey ?? items[0]?.key ?? \"\");\n const current = activeKey !== undefined ? activeKey : internal;\n const refs = useRef<Record<string, HTMLButtonElement | null>>({});\n const [marker, setMarker] = useState<{ top: number; height: number } | null>(null);\n const [ready, setReady] = useState(false);\n\n const measure = () => {\n const el = refs.current[current];\n setMarker(el ? { top: el.offsetTop, height: el.offsetHeight } : null);\n };\n\n useLayoutEffect(() => {\n measure();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [current]);\n\n useEffect(() => {\n // Only animate moves after the first placement\n const id = requestAnimationFrame(() => setReady(true));\n return () => cancelAnimationFrame(id);\n }, []);\n\n const handleSelect = (key: string) => {\n setInternal(key);\n onSelect?.(key);\n };\n\n const slide = ready ? \"top 360ms var(--ease-out-soft), height 360ms var(--ease-out-soft)\" : \"none\";\n\n return (\n <nav\n aria-label=\"On this page\"\n className={[\"rounded-[18px] p-1.5\", className].filter(Boolean).join(\" \")}\n style={{ background: \"var(--panel-bezel)\", boxShadow: \"var(--panel-shadow)\" }}\n >\n <div\n className=\"bg-panel-face rounded-[13px] px-5 pt-4 pb-4\"\n style={{ boxShadow: \"var(--panel-face-shadow)\" }}\n >\n <p aria-hidden className=\"text-[12px] font-medium text-ink-faint mb-3\">\n on this page\n </p>\n\n <div className=\"relative\">\n <span aria-hidden className=\"absolute left-0 top-0 bottom-0 w-px bg-ink/[0.08]\" />\n {marker && (\n <span\n aria-hidden\n className=\"absolute -left-[0.5px] w-[2px] rounded-full bg-ink\"\n style={{ top: marker.top + 6, height: marker.height - 12, transition: slide }}\n />\n )}\n\n {items.map((item) => {\n const isActive = current === item.key;\n return (\n <button\n key={item.key}\n ref={(el) => {\n refs.current[item.key] = el;\n }}\n type=\"button\"\n onClick={() => handleSelect(item.key)}\n aria-current={isActive ? \"location\" : undefined}\n className={[\n // Weight stays fixed so the active item doesn't reflow its line\n \"relative block w-full text-left py-1.5 text-[13px] leading-5 rounded-[6px] cursor-pointer\",\n \"transition-colors duration-200 outline-none\",\n \"focus-visible:outline-2 focus-visible:outline-offset-[-2px] focus-visible:outline-ink\",\n isActive\n ? \"text-ink font-medium\"\n : item.level === 1\n ? \"text-ink-body hover:text-ink\"\n : \"text-ink-faint hover:text-ink-label\",\n ].join(\" \")}\n style={{ paddingLeft: indent[item.level] }}\n >\n {item.label}\n </button>\n );\n })}\n </div>\n </div>\n </nav>\n );\n}\n"],"mappings":";;;AAEA,SAAgB,WAAW,iBAAiB,QAAQ,gBAAgB;AAmE5D,cAIA,YAJA;AAnDR,IAAM,SAAoC,EAAE,GAAG,IAAI,GAAG,IAAI,GAAG,GAAG;AAKzD,SAAS,gBAAgB;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,YAAY;AACd,GAAyB;AACvB,QAAM,CAAC,UAAU,WAAW,IAAI,SAAS,oBAAoB,MAAM,CAAC,GAAG,OAAO,EAAE;AAChF,QAAM,UAAU,cAAc,SAAY,YAAY;AACtD,QAAM,OAAO,OAAiD,CAAC,CAAC;AAChE,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAiD,IAAI;AACjF,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAS,KAAK;AAExC,QAAM,UAAU,MAAM;AACpB,UAAM,KAAK,KAAK,QAAQ,OAAO;AAC/B,cAAU,KAAK,EAAE,KAAK,GAAG,WAAW,QAAQ,GAAG,aAAa,IAAI,IAAI;AAAA,EACtE;AAEA,kBAAgB,MAAM;AACpB,YAAQ;AAAA,EAEV,GAAG,CAAC,OAAO,CAAC;AAEZ,YAAU,MAAM;AAEd,UAAM,KAAK,sBAAsB,MAAM,SAAS,IAAI,CAAC;AACrD,WAAO,MAAM,qBAAqB,EAAE;AAAA,EACtC,GAAG,CAAC,CAAC;AAEL,QAAM,eAAe,CAAC,QAAgB;AACpC,gBAAY,GAAG;AACf,eAAW,GAAG;AAAA,EAChB;AAEA,QAAM,QAAQ,QAAQ,sEAAsE;AAE5F,SACE;AAAA,IAAC;AAAA;AAAA,MACC,cAAW;AAAA,MACX,WAAW,CAAC,wBAAwB,SAAS,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG;AAAA,MACvE,OAAO,EAAE,YAAY,sBAAsB,WAAW,sBAAsB;AAAA,MAE5E;AAAA,QAAC;AAAA;AAAA,UACC,WAAU;AAAA,UACV,OAAO,EAAE,WAAW,2BAA2B;AAAA,UAE/C;AAAA,gCAAC,OAAE,eAAW,MAAC,WAAU,+CAA8C,0BAEvE;AAAA,YAEA,qBAAC,SAAI,WAAU,YACb;AAAA,kCAAC,UAAK,eAAW,MAAC,WAAU,qDAAoD;AAAA,cAC/E,UACC;AAAA,gBAAC;AAAA;AAAA,kBACC,eAAW;AAAA,kBACX,WAAU;AAAA,kBACV,OAAO,EAAE,KAAK,OAAO,MAAM,GAAG,QAAQ,OAAO,SAAS,IAAI,YAAY,MAAM;AAAA;AAAA,cAC9E;AAAA,cAGD,MAAM,IAAI,CAAC,SAAS;AACnB,sBAAM,WAAW,YAAY,KAAK;AAClC,uBACE;AAAA,kBAAC;AAAA;AAAA,oBAEC,KAAK,CAAC,OAAO;AACX,2BAAK,QAAQ,KAAK,GAAG,IAAI;AAAA,oBAC3B;AAAA,oBACA,MAAK;AAAA,oBACL,SAAS,MAAM,aAAa,KAAK,GAAG;AAAA,oBACpC,gBAAc,WAAW,aAAa;AAAA,oBACtC,WAAW;AAAA;AAAA,sBAET;AAAA,sBACA;AAAA,sBACA;AAAA,sBACA,WACI,yBACA,KAAK,UAAU,IACb,iCACA;AAAA,oBACR,EAAE,KAAK,GAAG;AAAA,oBACV,OAAO,EAAE,aAAa,OAAO,KAAK,KAAK,EAAE;AAAA,oBAExC,eAAK;AAAA;AAAA,kBApBD,KAAK;AAAA,gBAqBZ;AAAA,cAEJ,CAAC;AAAA,eACH;AAAA;AAAA;AAAA,MACF;AAAA;AAAA,EACF;AAEJ;","names":[]}
|
package/dist/Tabs.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
|
|
4
|
+
interface Tab {
|
|
5
|
+
key: string;
|
|
6
|
+
label: string;
|
|
7
|
+
content?: React.ReactNode;
|
|
8
|
+
}
|
|
9
|
+
interface TabsProps {
|
|
10
|
+
tabs: Tab[];
|
|
11
|
+
defaultTab?: string;
|
|
12
|
+
onChange?: (key: string) => void;
|
|
13
|
+
className?: string;
|
|
14
|
+
}
|
|
15
|
+
declare function Tabs({ tabs, defaultTab, onChange, className }: TabsProps): react_jsx_runtime.JSX.Element;
|
|
16
|
+
|
|
17
|
+
export { Tabs };
|
package/dist/Tabs.js
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// ../../components/ui/Tabs.tsx
|
|
4
|
+
import { useState, useRef, useEffect, useLayoutEffect, useId } from "react";
|
|
5
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
+
function Tabs({ tabs, defaultTab, onChange, className = "" }) {
|
|
7
|
+
const [active, setActive] = useState(defaultTab ?? tabs[0]?.key ?? "");
|
|
8
|
+
const [direction, setDirection] = useState("right");
|
|
9
|
+
const [pill, setPill] = useState({ left: 0, width: 0, ready: false });
|
|
10
|
+
const listRef = useRef(null);
|
|
11
|
+
const btnRefs = useRef({});
|
|
12
|
+
const uid = useId();
|
|
13
|
+
const measurePill = (key) => {
|
|
14
|
+
const btn = btnRefs.current[key];
|
|
15
|
+
const list = listRef.current;
|
|
16
|
+
if (!btn || !list) return;
|
|
17
|
+
const lr = list.getBoundingClientRect();
|
|
18
|
+
const br = btn.getBoundingClientRect();
|
|
19
|
+
setPill({ left: br.left - lr.left, width: br.width, ready: true });
|
|
20
|
+
};
|
|
21
|
+
useLayoutEffect(() => {
|
|
22
|
+
measurePill(active);
|
|
23
|
+
}, [active]);
|
|
24
|
+
useEffect(() => {
|
|
25
|
+
const ro = new ResizeObserver(() => measurePill(active));
|
|
26
|
+
if (listRef.current) ro.observe(listRef.current);
|
|
27
|
+
return () => ro.disconnect();
|
|
28
|
+
}, [active]);
|
|
29
|
+
const handleSelect = (key) => {
|
|
30
|
+
const prevIndex = tabs.findIndex((t) => t.key === active);
|
|
31
|
+
const nextIndex = tabs.findIndex((t) => t.key === key);
|
|
32
|
+
setDirection(nextIndex > prevIndex ? "right" : "left");
|
|
33
|
+
setActive(key);
|
|
34
|
+
onChange?.(key);
|
|
35
|
+
};
|
|
36
|
+
const onKeyDown = (e) => {
|
|
37
|
+
const i = tabs.findIndex((t) => t.key === active);
|
|
38
|
+
let next = -1;
|
|
39
|
+
if (e.key === "ArrowRight") next = (i + 1) % tabs.length;
|
|
40
|
+
if (e.key === "ArrowLeft") next = (i - 1 + tabs.length) % tabs.length;
|
|
41
|
+
if (e.key === "Home") next = 0;
|
|
42
|
+
if (e.key === "End") next = tabs.length - 1;
|
|
43
|
+
if (next < 0) return;
|
|
44
|
+
e.preventDefault();
|
|
45
|
+
const key = tabs[next].key;
|
|
46
|
+
handleSelect(key);
|
|
47
|
+
btnRefs.current[key]?.focus();
|
|
48
|
+
};
|
|
49
|
+
const activeTab = tabs.find((t) => t.key === active);
|
|
50
|
+
return /* @__PURE__ */ jsxs("div", { className: ["flex flex-col gap-4", className].join(" "), children: [
|
|
51
|
+
/* @__PURE__ */ jsxs(
|
|
52
|
+
"div",
|
|
53
|
+
{
|
|
54
|
+
ref: listRef,
|
|
55
|
+
role: "tablist",
|
|
56
|
+
onKeyDown,
|
|
57
|
+
className: "relative flex w-full sm:inline-flex sm:w-auto sm:self-start items-center rounded-[13px] p-1",
|
|
58
|
+
style: { background: "var(--well)", boxShadow: "var(--well-shadow)" },
|
|
59
|
+
children: [
|
|
60
|
+
pill.ready && /* @__PURE__ */ jsx(
|
|
61
|
+
"span",
|
|
62
|
+
{
|
|
63
|
+
"aria-hidden": true,
|
|
64
|
+
className: "absolute top-1 bottom-1 rounded-[9px] pointer-events-none",
|
|
65
|
+
style: {
|
|
66
|
+
left: pill.left,
|
|
67
|
+
width: pill.width,
|
|
68
|
+
background: "var(--face)",
|
|
69
|
+
boxShadow: "var(--thumb-shadow)",
|
|
70
|
+
transition: "left 300ms var(--ease-spring), width 300ms var(--ease-spring)"
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
),
|
|
74
|
+
tabs.map((tab) => {
|
|
75
|
+
const isActive = active === tab.key;
|
|
76
|
+
return /* @__PURE__ */ jsx(
|
|
77
|
+
"button",
|
|
78
|
+
{
|
|
79
|
+
ref: (el) => {
|
|
80
|
+
btnRefs.current[tab.key] = el;
|
|
81
|
+
},
|
|
82
|
+
id: `${uid}-tab-${tab.key}`,
|
|
83
|
+
role: "tab",
|
|
84
|
+
type: "button",
|
|
85
|
+
"aria-selected": isActive,
|
|
86
|
+
"aria-controls": tab.content ? `${uid}-panel-${tab.key}` : void 0,
|
|
87
|
+
tabIndex: isActive ? 0 : -1,
|
|
88
|
+
onClick: () => handleSelect(tab.key),
|
|
89
|
+
className: [
|
|
90
|
+
"relative z-10 flex-1 sm:flex-none px-3.5 py-2 rounded-[9px] text-[13px] font-medium text-center whitespace-nowrap cursor-pointer",
|
|
91
|
+
"transition-colors duration-150",
|
|
92
|
+
"focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-ink",
|
|
93
|
+
isActive ? "text-ink" : "text-ink-muted hover:text-ink-soft"
|
|
94
|
+
].join(" "),
|
|
95
|
+
children: tab.label
|
|
96
|
+
},
|
|
97
|
+
tab.key
|
|
98
|
+
);
|
|
99
|
+
})
|
|
100
|
+
]
|
|
101
|
+
}
|
|
102
|
+
),
|
|
103
|
+
activeTab?.content && /* @__PURE__ */ jsx(
|
|
104
|
+
"div",
|
|
105
|
+
{
|
|
106
|
+
id: `${uid}-panel-${active}`,
|
|
107
|
+
role: "tabpanel",
|
|
108
|
+
"aria-labelledby": `${uid}-tab-${active}`,
|
|
109
|
+
tabIndex: 0,
|
|
110
|
+
className: [
|
|
111
|
+
"text-[13px] text-ink-body leading-relaxed rounded-lg focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-ink",
|
|
112
|
+
direction === "right" ? "animate-tab-slide-right" : "animate-tab-slide-left"
|
|
113
|
+
].join(" "),
|
|
114
|
+
children: activeTab.content
|
|
115
|
+
},
|
|
116
|
+
active
|
|
117
|
+
)
|
|
118
|
+
] });
|
|
119
|
+
}
|
|
120
|
+
export {
|
|
121
|
+
Tabs
|
|
122
|
+
};
|
|
123
|
+
//# sourceMappingURL=Tabs.js.map
|
package/dist/Tabs.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../components/ui/Tabs.tsx"],"sourcesContent":["\"use client\";\n\nimport React, { useState, useRef, useEffect, useLayoutEffect, useId } from \"react\";\n\ninterface Tab {\n key: string;\n label: string;\n content?: React.ReactNode;\n}\n\ninterface TabsProps {\n tabs: Tab[];\n defaultTab?: string;\n onChange?: (key: string) => void;\n className?: string;\n}\n\n/* A sunken well holding a raised thumb — the same segmented control as\n Pagination. One Tab stop; arrows move between tabs and select them. */\nexport function Tabs({ tabs, defaultTab, onChange, className = \"\" }: TabsProps) {\n const [active, setActive] = useState(defaultTab ?? tabs[0]?.key ?? \"\");\n const [direction, setDirection] = useState<\"left\" | \"right\">(\"right\");\n const [pill, setPill] = useState({ left: 0, width: 0, ready: false });\n const listRef = useRef<HTMLDivElement>(null);\n const btnRefs = useRef<Record<string, HTMLButtonElement | null>>({});\n const uid = useId();\n\n const measurePill = (key: string) => {\n const btn = btnRefs.current[key];\n const list = listRef.current;\n if (!btn || !list) return;\n const lr = list.getBoundingClientRect();\n const br = btn.getBoundingClientRect();\n setPill({ left: br.left - lr.left, width: br.width, ready: true });\n };\n\n // Before paint, so the thumb is never seen out of place\n useLayoutEffect(() => { measurePill(active); }, [active]);\n\n useEffect(() => {\n const ro = new ResizeObserver(() => measurePill(active));\n if (listRef.current) ro.observe(listRef.current);\n return () => ro.disconnect();\n }, [active]);\n\n const handleSelect = (key: string) => {\n const prevIndex = tabs.findIndex((t) => t.key === active);\n const nextIndex = tabs.findIndex((t) => t.key === key);\n setDirection(nextIndex > prevIndex ? \"right\" : \"left\");\n setActive(key);\n onChange?.(key);\n };\n\n const onKeyDown = (e: React.KeyboardEvent) => {\n const i = tabs.findIndex((t) => t.key === active);\n let next = -1;\n if (e.key === \"ArrowRight\") next = (i + 1) % tabs.length;\n if (e.key === \"ArrowLeft\") next = (i - 1 + tabs.length) % tabs.length;\n if (e.key === \"Home\") next = 0;\n if (e.key === \"End\") next = tabs.length - 1;\n if (next < 0) return;\n e.preventDefault();\n const key = tabs[next].key;\n handleSelect(key);\n btnRefs.current[key]?.focus();\n };\n\n const activeTab = tabs.find((t) => t.key === active);\n\n return (\n <div className={[\"flex flex-col gap-4\", className].join(\" \")}>\n <div\n ref={listRef}\n role=\"tablist\"\n onKeyDown={onKeyDown}\n className=\"relative flex w-full sm:inline-flex sm:w-auto sm:self-start items-center rounded-[13px] p-1\"\n style={{ background: \"var(--well)\", boxShadow: \"var(--well-shadow)\" }}\n >\n {pill.ready && (\n <span\n aria-hidden\n className=\"absolute top-1 bottom-1 rounded-[9px] pointer-events-none\"\n style={{\n left: pill.left,\n width: pill.width,\n background: \"var(--face)\",\n boxShadow: \"var(--thumb-shadow)\",\n transition: \"left 300ms var(--ease-spring), width 300ms var(--ease-spring)\",\n }}\n />\n )}\n\n {tabs.map((tab) => {\n const isActive = active === tab.key;\n return (\n <button\n key={tab.key}\n ref={(el) => { btnRefs.current[tab.key] = el; }}\n id={`${uid}-tab-${tab.key}`}\n role=\"tab\"\n type=\"button\"\n aria-selected={isActive}\n aria-controls={tab.content ? `${uid}-panel-${tab.key}` : undefined}\n tabIndex={isActive ? 0 : -1}\n onClick={() => handleSelect(tab.key)}\n className={[\n \"relative z-10 flex-1 sm:flex-none px-3.5 py-2 rounded-[9px] text-[13px] font-medium text-center whitespace-nowrap cursor-pointer\",\n \"transition-colors duration-150\",\n \"focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-ink\",\n isActive ? \"text-ink\" : \"text-ink-muted hover:text-ink-soft\",\n ].join(\" \")}\n >\n {tab.label}\n </button>\n );\n })}\n </div>\n\n {activeTab?.content && (\n <div\n key={active}\n id={`${uid}-panel-${active}`}\n role=\"tabpanel\"\n aria-labelledby={`${uid}-tab-${active}`}\n tabIndex={0}\n className={[\n \"text-[13px] text-ink-body leading-relaxed rounded-lg focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-ink\",\n direction === \"right\" ? \"animate-tab-slide-right\" : \"animate-tab-slide-left\",\n ].join(\" \")}\n >\n {activeTab.content}\n </div>\n )}\n </div>\n );\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
|
|
3
|
+
interface TagInputProps {
|
|
4
|
+
value?: string[];
|
|
5
|
+
defaultValue?: string[];
|
|
6
|
+
onChange?: (tags: string[]) => void;
|
|
7
|
+
placeholder?: string;
|
|
8
|
+
label?: string;
|
|
9
|
+
hint?: string;
|
|
10
|
+
maxTags?: number;
|
|
11
|
+
fullWidth?: boolean;
|
|
12
|
+
className?: string;
|
|
13
|
+
}
|
|
14
|
+
declare function TagInput({ value, defaultValue, onChange, placeholder, label, hint, maxTags, fullWidth, className, }: TagInputProps): react_jsx_runtime.JSX.Element;
|
|
15
|
+
|
|
16
|
+
export { TagInput };
|