@vadimcomanescu/nadicode-design-system 4.0.3 → 4.0.5

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.
Files changed (69) hide show
  1. package/.agents/skills/seed/SKILL.md +24 -3
  2. package/dist/catalog/catalog.d.ts +186 -0
  3. package/dist/catalog/catalog.js +194 -0
  4. package/dist/catalog/components.d.ts +26 -0
  5. package/dist/catalog/components.js +71 -40
  6. package/dist/{chunk-RMGDDOCD.js → chunk-3ZPNIY2Z.js} +2 -2
  7. package/dist/chunk-4KZLCCIR.js +88 -0
  8. package/dist/{chunk-AWZFQQGN.js → chunk-6NCLYJAI.js} +2 -2
  9. package/dist/{chunk-K4U67BVG.js → chunk-7ALMTY6W.js} +1 -1
  10. package/dist/chunk-CZ7NGW7N.js +60 -0
  11. package/dist/chunk-FRGZSR2P.js +86 -0
  12. package/dist/{chunk-LGW7FVG5.js → chunk-HMFIUUYC.js} +1 -1
  13. package/dist/chunk-IC3BMFHV.js +86 -0
  14. package/dist/chunk-JVIRZNQ6.js +37 -0
  15. package/dist/chunk-K5AFXZDL.js +30 -0
  16. package/dist/{chunk-LK2L3C7D.js → chunk-LCMAB2BX.js} +3 -3
  17. package/dist/chunk-LIJYUSSE.js +152 -0
  18. package/dist/chunk-MB6TIORE.js +103 -0
  19. package/dist/chunk-PTJPPKDR.js +115 -0
  20. package/dist/chunk-PV62D7H6.js +75 -0
  21. package/dist/chunk-QVAV4MA2.js +60 -0
  22. package/dist/chunk-RPVG37RB.js +24 -0
  23. package/dist/{chunk-QW5II6YK.js → chunk-TEWCCMRH.js} +2 -2
  24. package/dist/chunk-W74WK3HB.js +184 -0
  25. package/dist/chunk-WVKJNHQM.js +120 -0
  26. package/dist/chunk-XAAJBX6R.js +100 -0
  27. package/dist/chunk-ZXVDDZZL.js +96 -0
  28. package/dist/components/blocks/ApiKeysBlock.d.ts +18 -0
  29. package/dist/components/blocks/ApiKeysBlock.js +128 -0
  30. package/dist/components/blocks/BenchmarksBlock.d.ts +20 -0
  31. package/dist/components/blocks/BenchmarksBlock.js +11 -0
  32. package/dist/components/blocks/CheckEmailBlock.d.ts +9 -0
  33. package/dist/components/blocks/CheckEmailBlock.js +13 -0
  34. package/dist/components/blocks/CommandPaletteBlock.d.ts +9 -0
  35. package/dist/components/blocks/CommandPaletteBlock.js +125 -0
  36. package/dist/components/blocks/EmailVerifiedBlock.d.ts +10 -0
  37. package/dist/components/blocks/EmailVerifiedBlock.js +10 -0
  38. package/dist/components/blocks/ForgotPasswordBlock.d.ts +14 -0
  39. package/dist/components/blocks/ForgotPasswordBlock.js +15 -0
  40. package/dist/components/blocks/IntegrationsBlock.js +4 -4
  41. package/dist/components/blocks/MagicLinkBlock.d.ts +12 -0
  42. package/dist/components/blocks/MagicLinkBlock.js +18 -0
  43. package/dist/components/blocks/OTPBlock.d.ts +10 -0
  44. package/dist/components/blocks/OTPBlock.js +121 -0
  45. package/dist/components/blocks/PasswordChangedBlock.d.ts +10 -0
  46. package/dist/components/blocks/PasswordChangedBlock.js +10 -0
  47. package/dist/components/blocks/PricingTableBlock.d.ts +19 -0
  48. package/dist/components/blocks/PricingTableBlock.js +12 -0
  49. package/dist/components/blocks/SavingsCalculatorBlock.d.ts +30 -0
  50. package/dist/components/blocks/SavingsCalculatorBlock.js +22 -0
  51. package/dist/components/blocks/TimezonePickerBlock.d.ts +11 -0
  52. package/dist/components/blocks/TimezonePickerBlock.js +126 -0
  53. package/dist/components/blocks/WorkspaceSwitcherBlock.d.ts +11 -0
  54. package/dist/components/blocks/WorkspaceSwitcherBlock.js +129 -0
  55. package/dist/components/logos/index.js +3 -3
  56. package/dist/components/page-kits/BlogContentPageKit.js +4 -4
  57. package/dist/components/page-kits/CheckoutPageKit.js +3 -3
  58. package/dist/components/page-kits/CompanySuitePageKit.js +4 -4
  59. package/dist/components/page-kits/LandingPageKit.js +5 -5
  60. package/dist/components/page-kits/MarketingShellPageKit.js +2 -2
  61. package/dist/components/page-kits/PricingPageKit.js +4 -4
  62. package/dist/components/page-kits/ServiceSuitePageKit.js +3 -3
  63. package/dist/components/ui/SearchCommand.js +4 -152
  64. package/dist/hooks/useHotkey.js +1 -37
  65. package/dist/lib/timezones.d.ts +14 -0
  66. package/dist/lib/timezones.js +1 -0
  67. package/package.json +6 -2
  68. package/dist/{chunk-6HGSU24S.js → chunk-4TUJJ3UI.js} +3 -3
  69. package/dist/{chunk-Z233ZQZE.js → chunk-E4L6LR6P.js} +1 -1
@@ -0,0 +1,86 @@
1
+ import { CountingNumber } from './chunk-F3T2U7YL.js';
2
+ import { StaggerChildren } from './chunk-DQPK2XRL.js';
3
+ import { Heading } from './chunk-WI547C47.js';
4
+ import { Table, TableHeader, TableRow, TableHead, TableBody, TableCell } from './chunk-PXDHNGTG.js';
5
+ import { Card, CardHeader, CardTitle, CardDescription, CardContent } from './chunk-AH6YSYYT.js';
6
+ import { Badge } from './chunk-S4JAHKOP.js';
7
+ import { cn } from './chunk-QYZT24TS.js';
8
+ import { jsx, jsxs } from 'react/jsx-runtime';
9
+
10
+ var DEFAULT_BILLING_MODELS = [
11
+ { model: "Claude Opus 4.5/4.6", inputRate: "$5.00", savedPerRead: "$0.009" },
12
+ { model: "Claude Sonnet 4.5/4.6", inputRate: "$3.00", savedPerRead: "$0.0054" },
13
+ { model: "GPT-4o", inputRate: "$2.50", savedPerRead: "$0.0045" }
14
+ ];
15
+ var DEFAULT_PROJECTIONS = [
16
+ { label: "On Sonnet ($3/MTok)", amount: 49, suffix: "/mo", detail: "16.2M tokens/mo saved" },
17
+ { label: "On Opus ($5/MTok)", amount: 81, suffix: "/mo", detail: "16.2M tokens/mo saved" }
18
+ ];
19
+ var DEFAULT_SUMMARY_ITEMS = [
20
+ { label: "Team of 5 on Opus", value: "$400+/mo saved" },
21
+ { label: "Subscription stretch (Sonnet)", value: "1.6x further" }
22
+ ];
23
+ function SavingsCalculatorBlock({
24
+ title = "What this saves you",
25
+ description = "Real numbers from API billing rates and SWE-Bench token data.",
26
+ badgeLabel = "Savings",
27
+ billingTitle = "API billing savings",
28
+ billingDescription = "Per file read, avg 1,800 tokens saved",
29
+ billingModels = DEFAULT_BILLING_MODELS,
30
+ projectionTitle = "Monthly projections",
31
+ projectionDescription = "Active developer, 300 pruned reads/day",
32
+ projections = DEFAULT_PROJECTIONS,
33
+ summaryItems = DEFAULT_SUMMARY_ITEMS,
34
+ className
35
+ }) {
36
+ return /* @__PURE__ */ jsx("section", { className: cn("py-16 md:py-24", className), children: /* @__PURE__ */ jsxs("div", { className: "container mx-auto px-6 lg:px-8", children: [
37
+ /* @__PURE__ */ jsxs("div", { className: "text-center mb-16 max-w-2xl mx-auto", children: [
38
+ /* @__PURE__ */ jsx(Badge, { variant: "outline", className: "mb-4", children: badgeLabel }),
39
+ /* @__PURE__ */ jsx(Heading, { level: 2, className: "mb-4", children: title }),
40
+ /* @__PURE__ */ jsx("p", { className: "text-text-secondary text-lg", children: description })
41
+ ] }),
42
+ /* @__PURE__ */ jsxs(StaggerChildren, { staggerMs: 120, className: "grid gap-8 lg:grid-cols-2 [grid-auto-rows:1fr]", children: [
43
+ /* @__PURE__ */ jsxs(Card, { className: "h-full", children: [
44
+ /* @__PURE__ */ jsxs(CardHeader, { children: [
45
+ /* @__PURE__ */ jsx(CardTitle, { children: billingTitle }),
46
+ /* @__PURE__ */ jsx(CardDescription, { children: billingDescription })
47
+ ] }),
48
+ /* @__PURE__ */ jsx(CardContent, { className: "flex-1 overflow-x-auto", children: /* @__PURE__ */ jsxs(Table, { children: [
49
+ /* @__PURE__ */ jsx(TableHeader, { children: /* @__PURE__ */ jsxs(TableRow, { children: [
50
+ /* @__PURE__ */ jsx(TableHead, { children: "Model" }),
51
+ /* @__PURE__ */ jsx(TableHead, { className: "text-right", children: "Input $/MTok" }),
52
+ /* @__PURE__ */ jsx(TableHead, { className: "text-right", children: "Saved/read" })
53
+ ] }) }),
54
+ /* @__PURE__ */ jsx(TableBody, { children: billingModels.map((row) => /* @__PURE__ */ jsxs(TableRow, { children: [
55
+ /* @__PURE__ */ jsx(TableCell, { className: "font-medium", children: row.model }),
56
+ /* @__PURE__ */ jsx(TableCell, { className: "text-right", children: row.inputRate }),
57
+ /* @__PURE__ */ jsx(TableCell, { className: "text-right font-semibold text-chart-4", children: row.savedPerRead })
58
+ ] }, row.model)) })
59
+ ] }) })
60
+ ] }),
61
+ /* @__PURE__ */ jsxs(Card, { className: "h-full", children: [
62
+ /* @__PURE__ */ jsxs(CardHeader, { children: [
63
+ /* @__PURE__ */ jsx(CardTitle, { children: projectionTitle }),
64
+ /* @__PURE__ */ jsx(CardDescription, { children: projectionDescription })
65
+ ] }),
66
+ /* @__PURE__ */ jsxs(CardContent, { className: "flex-1 space-y-8", children: [
67
+ /* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 gap-6", children: projections.map((proj) => /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
68
+ /* @__PURE__ */ jsx("div", { className: "text-sm text-text-tertiary", children: proj.label }),
69
+ /* @__PURE__ */ jsxs("div", { className: "text-3xl font-bold tabular-nums text-text-primary", children: [
70
+ "~$",
71
+ /* @__PURE__ */ jsx(CountingNumber, { number: proj.amount, inViewOnce: true }),
72
+ /* @__PURE__ */ jsx("span", { className: "text-lg text-text-secondary", children: proj.suffix })
73
+ ] }),
74
+ /* @__PURE__ */ jsx("div", { className: "text-xs text-text-tertiary", children: proj.detail })
75
+ ] }, proj.label)) }),
76
+ summaryItems.length > 0 && /* @__PURE__ */ jsx("div", { className: "border-t border-border/50 pt-6 space-y-4", children: summaryItems.map((item) => /* @__PURE__ */ jsxs("div", { className: "flex justify-between items-baseline", children: [
77
+ /* @__PURE__ */ jsx("span", { className: "text-sm text-text-secondary", children: item.label }),
78
+ /* @__PURE__ */ jsx("span", { className: "text-lg font-bold text-chart-4", children: item.value })
79
+ ] }, item.label)) })
80
+ ] })
81
+ ] })
82
+ ] })
83
+ ] }) });
84
+ }
85
+
86
+ export { SavingsCalculatorBlock };
@@ -0,0 +1,37 @@
1
+ import { useRef, useEffect, useMemo } from 'react';
2
+
3
+ // src/hooks/useHotkey.ts
4
+ function parseCombo(combo) {
5
+ const parts = combo.toLowerCase().split("+");
6
+ return {
7
+ key: parts[parts.length - 1],
8
+ mod: parts.includes("mod"),
9
+ shift: parts.includes("shift"),
10
+ alt: parts.includes("alt")
11
+ };
12
+ }
13
+ function useHotkey(combo, callback, options) {
14
+ const callbackRef = useRef(callback);
15
+ const enabled = options?.enabled ?? true;
16
+ useEffect(() => {
17
+ callbackRef.current = callback;
18
+ });
19
+ const parsed = useMemo(() => parseCombo(combo), [combo]);
20
+ useEffect(() => {
21
+ if (!enabled) return;
22
+ function handler(event) {
23
+ const mac = typeof navigator !== "undefined" && /Mac|iPhone|iPad/.test(navigator.userAgent);
24
+ const modPressed = mac ? event.metaKey : event.ctrlKey;
25
+ if (parsed.mod && !modPressed) return;
26
+ if (parsed.shift && !event.shiftKey) return;
27
+ if (parsed.alt && !event.altKey) return;
28
+ if (event.key.toLowerCase() !== parsed.key) return;
29
+ event.preventDefault();
30
+ callbackRef.current(event);
31
+ }
32
+ document.addEventListener("keydown", handler);
33
+ return () => document.removeEventListener("keydown", handler);
34
+ }, [parsed, enabled]);
35
+ }
36
+
37
+ export { useHotkey };
@@ -0,0 +1,30 @@
1
+ import { InputOTP, InputOTPGroup, InputOTPSlot } from './chunk-WN5ONOHC.js';
2
+ import { Card, CardHeader, CardTitle, CardDescription, CardContent } from './chunk-AH6YSYYT.js';
3
+ import { Button } from './chunk-7KIDDF3I.js';
4
+ import { m, scaleIn } from './chunk-PD2YEH3H.js';
5
+ import { cn } from './chunk-QYZT24TS.js';
6
+ import * as React from 'react';
7
+ import { jsx, jsxs } from 'react/jsx-runtime';
8
+
9
+ function OTPBlock({
10
+ className,
11
+ title = "One-Time Password",
12
+ description = "Please enter the one-time password sent to your phone.",
13
+ maxLength = 6,
14
+ buttonText = "Verify",
15
+ onVerify
16
+ }) {
17
+ const [otp, setOtp] = React.useState("");
18
+ return /* @__PURE__ */ jsx(m.div, { ...scaleIn, className: cn("w-full max-w-sm mx-auto", className), children: /* @__PURE__ */ jsxs(Card, { className: "text-center", children: [
19
+ /* @__PURE__ */ jsxs(CardHeader, { children: [
20
+ /* @__PURE__ */ jsx(CardTitle, { className: "text-2xl", children: title }),
21
+ /* @__PURE__ */ jsx(CardDescription, { children: description })
22
+ ] }),
23
+ /* @__PURE__ */ jsxs(CardContent, { className: "grid gap-4 justify-center", children: [
24
+ /* @__PURE__ */ jsx(InputOTP, { maxLength, value: otp, onChange: setOtp, children: /* @__PURE__ */ jsx(InputOTPGroup, { children: Array.from({ length: maxLength }, (_, i) => /* @__PURE__ */ jsx(InputOTPSlot, { index: i }, i)) }) }),
25
+ /* @__PURE__ */ jsx(Button, { className: "w-full", onClick: () => onVerify?.(otp), children: buttonText })
26
+ ] })
27
+ ] }) });
28
+ }
29
+
30
+ export { OTPBlock };
@@ -1,8 +1,8 @@
1
- import { MarketingShellPageKit } from './chunk-Z233ZQZE.js';
2
- import { SocialProofBlock } from './chunk-C7WHMSF3.js';
1
+ import { MarketingShellPageKit } from './chunk-E4L6LR6P.js';
3
2
  import { StatsMarketingBlock } from './chunk-QIHA7S3A.js';
4
- import { NewsletterBlock } from './chunk-K7NQ6ZAW.js';
5
3
  import { PricingBlock } from './chunk-VNNAL4A6.js';
4
+ import { SocialProofBlock } from './chunk-C7WHMSF3.js';
5
+ import { NewsletterBlock } from './chunk-K7NQ6ZAW.js';
6
6
  import { HeroBlock } from './chunk-GJ557DGH.js';
7
7
  import { FAQBlock } from './chunk-NEHCPO53.js';
8
8
  import { FeatureBlock } from './chunk-HJ3A2YNO.js';
@@ -0,0 +1,152 @@
1
+ import { SearchIcon } from './chunk-T6BRD7TS.js';
2
+ import { CornerDownLeftIcon } from './chunk-4FEAWXJD.js';
3
+ import { cn } from './chunk-QYZT24TS.js';
4
+ import * as React from 'react';
5
+ import { useTranslations } from 'next-intl';
6
+ import { cva } from 'class-variance-authority';
7
+ import { jsxs, jsx } from 'react/jsx-runtime';
8
+
9
+ var searchCommandVariants = cva(
10
+ "flex flex-col rounded-xl glass-panel overflow-hidden",
11
+ {
12
+ variants: {
13
+ variant: {
14
+ default: "",
15
+ floating: "shadow-lg shadow-black/20"
16
+ },
17
+ size: {
18
+ sm: "max-w-sm",
19
+ default: "max-w-lg",
20
+ lg: "max-w-2xl"
21
+ }
22
+ },
23
+ defaultVariants: {
24
+ variant: "default",
25
+ size: "default"
26
+ }
27
+ }
28
+ );
29
+ var EMPTY_RESULTS = [];
30
+ function SearchCommand({
31
+ className,
32
+ variant,
33
+ size,
34
+ value = "",
35
+ onChange,
36
+ results = EMPTY_RESULTS,
37
+ onSelect,
38
+ placeholder,
39
+ loading = false,
40
+ showShortcut = true,
41
+ ref,
42
+ ...props
43
+ }) {
44
+ const t = useTranslations("components.searchCommand");
45
+ const resolvedPlaceholder = placeholder ?? t("placeholder");
46
+ const [selectedIndex, setSelectedIndex] = React.useState(0);
47
+ const inputRef = React.useRef(null);
48
+ const prevResultsRef = React.useRef(results);
49
+ if (prevResultsRef.current !== results) {
50
+ prevResultsRef.current = results;
51
+ if (selectedIndex !== 0) setSelectedIndex(0);
52
+ }
53
+ const handleKeyDown = (e) => {
54
+ if (e.key === "ArrowDown") {
55
+ e.preventDefault();
56
+ setSelectedIndex((prev) => (prev + 1) % Math.max(results.length, 1));
57
+ } else if (e.key === "ArrowUp") {
58
+ e.preventDefault();
59
+ setSelectedIndex(
60
+ (prev) => prev <= 0 ? Math.max(results.length - 1, 0) : prev - 1
61
+ );
62
+ } else if (e.key === "Enter" && results[selectedIndex]) {
63
+ e.preventDefault();
64
+ onSelect?.(results[selectedIndex]);
65
+ }
66
+ };
67
+ const groupedResults = React.useMemo(() => results.reduce(
68
+ (acc, result) => {
69
+ const category = result.category ?? "Results";
70
+ if (!acc[category]) acc[category] = [];
71
+ acc[category].push(result);
72
+ return acc;
73
+ },
74
+ {}
75
+ ), [results]);
76
+ let flatIndex = -1;
77
+ return /* @__PURE__ */ jsxs(
78
+ "div",
79
+ {
80
+ ref,
81
+ className: cn(searchCommandVariants({ variant, size }), "w-full", className),
82
+ role: "combobox",
83
+ "aria-expanded": results.length > 0,
84
+ "aria-controls": "search-command-listbox",
85
+ "aria-haspopup": "listbox",
86
+ ...props,
87
+ children: [
88
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 border-b border-border pl-4 pr-12 transition-[border-color]", children: [
89
+ /* @__PURE__ */ jsx(SearchIcon, { size: 16, className: "shrink-0 text-text-tertiary" }),
90
+ /* @__PURE__ */ jsx(
91
+ "input",
92
+ {
93
+ ref: inputRef,
94
+ className: "flex-1 bg-transparent py-4 text-sm text-text-primary placeholder:text-text-tertiary outline-none focus-visible:outline-1 focus-visible:outline-border",
95
+ placeholder: resolvedPlaceholder,
96
+ value,
97
+ onChange: (e) => onChange?.(e.target.value),
98
+ onKeyDown: handleKeyDown,
99
+ role: "searchbox",
100
+ "aria-label": "Search",
101
+ "aria-autocomplete": "list",
102
+ "aria-activedescendant": results[selectedIndex] ? `search-option-${results[selectedIndex].id}` : void 0
103
+ }
104
+ ),
105
+ !!showShortcut && /* @__PURE__ */ jsx("div", { className: "flex items-center gap-1.5 text-text-tertiary", children: /* @__PURE__ */ jsx(CornerDownLeftIcon, { size: 12 }) })
106
+ ] }),
107
+ !!loading && /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center py-6", children: /* @__PURE__ */ jsx("span", { className: "text-sm text-text-tertiary animate-pulse", children: t("searching") }) }),
108
+ !loading && results.length > 0 && /* @__PURE__ */ jsx(
109
+ "ul",
110
+ {
111
+ id: "search-command-listbox",
112
+ className: "max-h-[300px] overflow-y-auto py-1.5",
113
+ role: "listbox",
114
+ "aria-label": "Search results",
115
+ children: Object.entries(groupedResults).map(([category, items]) => /* @__PURE__ */ jsxs("li", { role: "presentation", children: [
116
+ /* @__PURE__ */ jsx("div", { className: "px-4 py-1.5 text-[10px] font-semibold uppercase tracking-wider text-text-tertiary", children: category }),
117
+ /* @__PURE__ */ jsx("ul", { role: "group", "aria-label": category, children: items.map((result) => {
118
+ flatIndex++;
119
+ const idx = flatIndex;
120
+ return /* @__PURE__ */ jsxs(
121
+ "li",
122
+ {
123
+ id: `search-option-${result.id}`,
124
+ role: "option",
125
+ "aria-selected": idx === selectedIndex,
126
+ className: cn(
127
+ "flex items-center gap-4 cursor-pointer px-4 py-2 text-sm transition-colors",
128
+ idx === selectedIndex ? "bg-accent/10 text-accent" : "text-text-primary hover:bg-surface-hover"
129
+ ),
130
+ onClick: () => onSelect?.(result),
131
+ onMouseEnter: () => setSelectedIndex(idx),
132
+ children: [
133
+ result.icon && /* @__PURE__ */ jsx("span", { className: "shrink-0 text-text-tertiary", children: result.icon }),
134
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
135
+ /* @__PURE__ */ jsx("p", { className: "truncate", children: result.title }),
136
+ result.description && /* @__PURE__ */ jsx("p", { className: "text-xs text-text-tertiary truncate", children: result.description })
137
+ ] })
138
+ ]
139
+ },
140
+ result.id
141
+ );
142
+ }) })
143
+ ] }, category))
144
+ }
145
+ ),
146
+ !loading && value && results.length === 0 && /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center py-6", children: /* @__PURE__ */ jsx("span", { className: "text-sm text-text-tertiary", children: t("noResults") }) })
147
+ ]
148
+ }
149
+ );
150
+ }
151
+
152
+ export { SearchCommand, searchCommandVariants };
@@ -0,0 +1,103 @@
1
+ import { StaggerChildren } from './chunk-DQPK2XRL.js';
2
+ import { Heading } from './chunk-WI547C47.js';
3
+ import { Table, TableHeader, TableRow, TableHead, TableBody, TableCell } from './chunk-PXDHNGTG.js';
4
+ import { Card, CardHeader, CardTitle, CardDescription, CardContent } from './chunk-AH6YSYYT.js';
5
+ import { Badge } from './chunk-S4JAHKOP.js';
6
+ import { cn } from './chunk-QYZT24TS.js';
7
+ import { jsx, jsxs } from 'react/jsx-runtime';
8
+
9
+ var DEFAULT_DATASETS = [
10
+ {
11
+ name: "Latency (p95)",
12
+ description: "End-to-end response time under load",
13
+ columns: ["Configuration", "p95 (ms)", "Throughput"],
14
+ rows: [
15
+ { cells: ["Baseline", "420ms", "1.2K rps"] },
16
+ { cells: ["+ Cache layer", "185ms", "3.1K rps"], highlight: true },
17
+ { cells: ["+ Connection pool", "210ms", "2.8K rps"] }
18
+ ]
19
+ },
20
+ {
21
+ name: "Accuracy",
22
+ description: "Precision and recall across evaluation sets",
23
+ columns: ["Model", "Precision", "Recall"],
24
+ rows: [
25
+ { cells: ["v1.0", "82.3%", "78.1%"] },
26
+ { cells: ["v2.0", "89.7%", "85.4%"] },
27
+ { cells: ["v2.1 (current)", "91.2%", "88.6%"], highlight: true }
28
+ ]
29
+ },
30
+ {
31
+ name: "Resource usage",
32
+ description: "Memory and CPU utilization per instance",
33
+ columns: ["Tier", "Memory", "CPU"],
34
+ rows: [
35
+ { cells: ["Small", "256 MB", "0.25 vCPU"] },
36
+ { cells: ["Medium", "512 MB", "0.5 vCPU"], highlight: true },
37
+ { cells: ["Large", "1024 MB", "1.0 vCPU"] }
38
+ ]
39
+ },
40
+ {
41
+ name: "Cost efficiency",
42
+ description: "Normalized cost per 1M operations",
43
+ columns: ["Provider", "Cost", "Savings"],
44
+ rows: [
45
+ { cells: ["Legacy", "$4.20", "-"] },
46
+ { cells: ["Current", "$1.85", "56%"], highlight: true },
47
+ { cells: ["Projected", "$0.92", "78%"] }
48
+ ]
49
+ }
50
+ ];
51
+ function BenchmarksBlock({
52
+ badgeLabel = "Benchmarks",
53
+ title = "Performance at a glance",
54
+ subtitle = "Key metrics across latency, accuracy, resource usage, and cost.",
55
+ datasets = DEFAULT_DATASETS,
56
+ staggerMs = 120,
57
+ className
58
+ }) {
59
+ return /* @__PURE__ */ jsx("section", { className: cn("py-16 md:py-24", className), children: /* @__PURE__ */ jsxs("div", { className: "container mx-auto px-6 lg:px-8", children: [
60
+ /* @__PURE__ */ jsxs("div", { className: "text-center mb-16 max-w-2xl mx-auto", children: [
61
+ /* @__PURE__ */ jsx(Badge, { variant: "outline", className: "mb-4", children: badgeLabel }),
62
+ /* @__PURE__ */ jsx(Heading, { level: 2, className: "mb-4", children: title }),
63
+ /* @__PURE__ */ jsx("p", { className: "text-text-secondary text-lg", children: subtitle })
64
+ ] }),
65
+ datasets.length === 0 ? /* @__PURE__ */ jsx("p", { className: "text-center text-text-secondary py-12", children: "No benchmark data available." }) : /* @__PURE__ */ jsx(StaggerChildren, { staggerMs, className: "grid gap-8 lg:grid-cols-2 [grid-auto-rows:1fr]", children: datasets.map((dataset) => /* @__PURE__ */ jsxs(Card, { className: "h-full", children: [
66
+ /* @__PURE__ */ jsxs(CardHeader, { children: [
67
+ /* @__PURE__ */ jsx(CardTitle, { children: dataset.name }),
68
+ /* @__PURE__ */ jsx(CardDescription, { children: dataset.description })
69
+ ] }),
70
+ /* @__PURE__ */ jsx(CardContent, { className: "flex-1 overflow-x-auto", children: /* @__PURE__ */ jsxs(Table, { children: [
71
+ /* @__PURE__ */ jsx(TableHeader, { children: /* @__PURE__ */ jsx(TableRow, { children: dataset.columns.map((col) => /* @__PURE__ */ jsx(
72
+ TableHead,
73
+ {
74
+ className: col === dataset.columns[0] ? void 0 : "text-right",
75
+ children: col
76
+ },
77
+ col
78
+ )) }) }),
79
+ /* @__PURE__ */ jsx(TableBody, { children: dataset.rows.map((row, rowIdx) => /* @__PURE__ */ jsx(
80
+ TableRow,
81
+ {
82
+ className: row.highlight ? "bg-accent/5 font-semibold" : void 0,
83
+ children: row.cells.map((cell, cellIdx) => /* @__PURE__ */ jsx(
84
+ TableCell,
85
+ {
86
+ className: cn(
87
+ cellIdx === 0 ? "font-medium" : "text-right",
88
+ row.highlight && cellIdx === 0 && "text-accent",
89
+ row.highlight && cellIdx > 0 && "text-chart-4"
90
+ ),
91
+ children: cell
92
+ },
93
+ cellIdx
94
+ ))
95
+ },
96
+ rowIdx
97
+ )) })
98
+ ] }) })
99
+ ] }, dataset.name)) })
100
+ ] }) });
101
+ }
102
+
103
+ export { BenchmarksBlock };
@@ -0,0 +1,115 @@
1
+ // src/lib/timezones.ts
2
+ var FALLBACK_TIMEZONES = [
3
+ "Etc/UTC",
4
+ "America/New_York",
5
+ "America/Chicago",
6
+ "America/Denver",
7
+ "America/Los_Angeles",
8
+ "Europe/London",
9
+ "Europe/Rome",
10
+ "Europe/Bucharest",
11
+ "Asia/Tokyo",
12
+ "Australia/Sydney"
13
+ ];
14
+ function getTimezoneGroups(referenceDate = /* @__PURE__ */ new Date()) {
15
+ const allTimezones = getAllTimezones();
16
+ const entries = allTimezones.filter((timezone) => timezone.includes("/") || timezone === "UTC").map((timezone) => {
17
+ const normalizedTimezone = timezone === "UTC" ? "Etc/UTC" : timezone;
18
+ const [region, ...rest] = normalizedTimezone.split("/");
19
+ const labelSource = rest.length > 0 ? rest[rest.length - 1] : normalizedTimezone;
20
+ const offsetMinutes = getOffsetMinutes(normalizedTimezone, referenceDate);
21
+ return {
22
+ value: normalizedTimezone,
23
+ label: labelSource.replaceAll("_", " "),
24
+ region,
25
+ offset: formatOffset(offsetMinutes),
26
+ offsetMinutes
27
+ };
28
+ });
29
+ const groupedByRegion = /* @__PURE__ */ new Map();
30
+ for (const entry of entries) {
31
+ const regionEntries = groupedByRegion.get(entry.region) ?? [];
32
+ regionEntries.push(entry);
33
+ groupedByRegion.set(entry.region, regionEntries);
34
+ }
35
+ const groups = Array.from(groupedByRegion.entries()).map(([region, timezones]) => ({
36
+ region,
37
+ timezones: timezones.slice().sort(
38
+ (left, right) => left.offsetMinutes - right.offsetMinutes || left.label.localeCompare(right.label)
39
+ )
40
+ }));
41
+ return groups.sort((left, right) => left.region.localeCompare(right.region));
42
+ }
43
+ function searchTimezones(query, groups) {
44
+ const normalizedQuery = query.trim().toLowerCase();
45
+ if (!normalizedQuery) {
46
+ return groups.flatMap((group) => group.timezones);
47
+ }
48
+ const matches = [];
49
+ for (const group of groups) {
50
+ for (const timezone of group.timezones) {
51
+ const candidate = `${timezone.value} ${timezone.label} ${timezone.region} ${timezone.offset}`;
52
+ if (candidate.toLowerCase().includes(normalizedQuery)) {
53
+ matches.push(timezone);
54
+ }
55
+ }
56
+ }
57
+ return matches;
58
+ }
59
+ function detectBrowserTimezone() {
60
+ try {
61
+ const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
62
+ if (!timezone) {
63
+ return "Etc/UTC";
64
+ }
65
+ return timezone === "UTC" ? "Etc/UTC" : timezone;
66
+ } catch {
67
+ return "Etc/UTC";
68
+ }
69
+ }
70
+ function getAllTimezones() {
71
+ const supportedValuesOf = Intl.supportedValuesOf;
72
+ if (typeof supportedValuesOf !== "function") {
73
+ return FALLBACK_TIMEZONES;
74
+ }
75
+ try {
76
+ const supported = supportedValuesOf("timeZone");
77
+ if (supported.length === 0) {
78
+ return FALLBACK_TIMEZONES;
79
+ }
80
+ return supported;
81
+ } catch {
82
+ return FALLBACK_TIMEZONES;
83
+ }
84
+ }
85
+ function getOffsetMinutes(timezone, referenceDate) {
86
+ try {
87
+ const formatter = new Intl.DateTimeFormat("en-US", {
88
+ timeZone: timezone,
89
+ timeZoneName: "shortOffset"
90
+ });
91
+ const timezoneName = formatter.formatToParts(referenceDate).find((part) => part.type === "timeZoneName")?.value ?? "GMT";
92
+ const match = timezoneName.match(/^GMT(?:(\+|-)(\d{1,2})(?::(\d{2}))?)?$/);
93
+ if (!match) {
94
+ return 0;
95
+ }
96
+ if (!match[1] || !match[2]) {
97
+ return 0;
98
+ }
99
+ const sign = match[1] === "-" ? -1 : 1;
100
+ const hours = Number.parseInt(match[2], 10);
101
+ const minutes = Number.parseInt(match[3] ?? "0", 10);
102
+ return sign * (hours * 60 + minutes);
103
+ } catch {
104
+ return 0;
105
+ }
106
+ }
107
+ function formatOffset(offsetMinutes) {
108
+ const sign = offsetMinutes >= 0 ? "+" : "-";
109
+ const absoluteMinutes = Math.abs(offsetMinutes);
110
+ const hours = String(Math.floor(absoluteMinutes / 60)).padStart(2, "0");
111
+ const minutes = String(absoluteMinutes % 60).padStart(2, "0");
112
+ return `UTC${sign}${hours}:${minutes}`;
113
+ }
114
+
115
+ export { detectBrowserTimezone, getTimezoneGroups, searchTimezones };
@@ -0,0 +1,75 @@
1
+ import { Spinner } from './chunk-ZLSWCV55.js';
2
+ import { Field, FieldLabel } from './chunk-RX5EUODB.js';
3
+ import { Input } from './chunk-AP3XXYAY.js';
4
+ import { Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter } from './chunk-AH6YSYYT.js';
5
+ import { Button } from './chunk-7KIDDF3I.js';
6
+ import { m, scaleIn } from './chunk-PD2YEH3H.js';
7
+ import { MailIcon } from './chunk-XQ2UDMPO.js';
8
+ import { CheckIcon } from './chunk-CXACRCZ4.js';
9
+ import { cn } from './chunk-QYZT24TS.js';
10
+ import * as React from 'react';
11
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
12
+
13
+ function ForgotPasswordBlock({
14
+ className,
15
+ onSubmit,
16
+ onBackToLogin,
17
+ title = "Forgot password?",
18
+ description = "Enter your email to reset your password",
19
+ successTitle = "Email sent",
20
+ submitLabel = "Send reset link",
21
+ loadingLabel = "Sending...",
22
+ backLabel = "Back to login",
23
+ emailPlaceholder = "name@example.com"
24
+ }) {
25
+ const [email, setEmail] = React.useState("");
26
+ const [state, setState] = React.useState("idle");
27
+ const handleSubmit = (e) => {
28
+ e.preventDefault();
29
+ if (!email) return;
30
+ setState("loading");
31
+ onSubmit?.(email);
32
+ setTimeout(() => setState("success"), 1500);
33
+ };
34
+ return /* @__PURE__ */ jsx(m.div, { ...scaleIn, className: cn("w-full max-w-sm mx-auto", className), children: /* @__PURE__ */ jsxs(Card, { children: [
35
+ /* @__PURE__ */ jsxs(CardHeader, { className: "text-center", children: [
36
+ state === "success" ? /* @__PURE__ */ jsx("div", { className: "mx-auto mb-2 flex h-16 w-16 items-center justify-center rounded-full bg-success/10 shadow-[0_0_24px_rgba(61,214,140,0.2)]", children: /* @__PURE__ */ jsx(CheckIcon, { size: 32, className: "text-success" }) }) : /* @__PURE__ */ jsx("div", { className: "mx-auto mb-2", children: /* @__PURE__ */ jsx(MailIcon, { size: 32, className: "text-text-secondary" }) }),
37
+ /* @__PURE__ */ jsx(CardTitle, { className: "text-2xl", children: state === "success" ? successTitle : title }),
38
+ /* @__PURE__ */ jsx(CardDescription, { children: state === "success" ? `We sent a reset link to ${email}` : description })
39
+ ] }),
40
+ state !== "success" && /* @__PURE__ */ jsx(CardContent, { children: /* @__PURE__ */ jsxs("form", { noValidate: true, onSubmit: handleSubmit, className: "grid gap-4", children: [
41
+ /* @__PURE__ */ jsxs(Field, { children: [
42
+ /* @__PURE__ */ jsx(FieldLabel, { htmlFor: "forgot-email", children: "Email" }),
43
+ /* @__PURE__ */ jsx(
44
+ Input,
45
+ {
46
+ id: "forgot-email",
47
+ name: "email",
48
+ type: "email",
49
+ placeholder: emailPlaceholder,
50
+ value: email,
51
+ onChange: (e) => setEmail(e.target.value),
52
+ autoComplete: "email",
53
+ required: true
54
+ }
55
+ )
56
+ ] }),
57
+ /* @__PURE__ */ jsx(Button, { variant: "accent", className: "w-full", disabled: state === "loading", children: state === "loading" ? /* @__PURE__ */ jsxs(Fragment, { children: [
58
+ /* @__PURE__ */ jsx(Spinner, { className: "mr-2" }),
59
+ loadingLabel
60
+ ] }) : submitLabel })
61
+ ] }) }),
62
+ /* @__PURE__ */ jsx(CardFooter, { className: "justify-center", children: /* @__PURE__ */ jsx(
63
+ "button",
64
+ {
65
+ type: "button",
66
+ onClick: onBackToLogin,
67
+ "aria-label": backLabel,
68
+ className: "text-sm text-text-tertiary hover:text-text-primary transition-colors",
69
+ children: backLabel
70
+ }
71
+ ) })
72
+ ] }) });
73
+ }
74
+
75
+ export { ForgotPasswordBlock };