@orangecheck/app-design 1.4.1 → 1.6.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.
Files changed (45) hide show
  1. package/dist/chrome.d.mts +2 -2
  2. package/dist/chrome.d.ts +2 -2
  3. package/dist/chrome.js +162 -35
  4. package/dist/chrome.js.map +1 -1
  5. package/dist/chrome.mjs +163 -36
  6. package/dist/chrome.mjs.map +1 -1
  7. package/dist/components.d.mts +99 -6
  8. package/dist/components.d.ts +99 -6
  9. package/dist/components.js +546 -26
  10. package/dist/components.js.map +1 -1
  11. package/dist/components.mjs +535 -28
  12. package/dist/components.mjs.map +1 -1
  13. package/dist/index.d.mts +4 -4
  14. package/dist/index.d.ts +4 -4
  15. package/dist/index.js +737 -82
  16. package/dist/index.js.map +1 -1
  17. package/dist/index.mjs +727 -84
  18. package/dist/index.mjs.map +1 -1
  19. package/dist/mdx.js.map +1 -1
  20. package/dist/mdx.mjs.map +1 -1
  21. package/dist/primitives.d.mts +1 -0
  22. package/dist/primitives.d.ts +1 -0
  23. package/dist/primitives.js +27 -0
  24. package/dist/primitives.js.map +1 -1
  25. package/dist/primitives.mjs +27 -0
  26. package/dist/primitives.mjs.map +1 -1
  27. package/dist/session.d.mts +3 -3
  28. package/dist/session.d.ts +3 -3
  29. package/dist/session.js.map +1 -1
  30. package/dist/session.mjs.map +1 -1
  31. package/dist/styles/chart.css +76 -0
  32. package/dist/styles/theme.css +7 -0
  33. package/dist/styles/tokens.css +18 -0
  34. package/dist/styles.css +1 -0
  35. package/dist/tokens.d.mts +314 -21
  36. package/dist/tokens.d.ts +314 -21
  37. package/dist/tokens.js +166 -26
  38. package/dist/tokens.js.map +1 -1
  39. package/dist/tokens.mjs +165 -27
  40. package/dist/tokens.mjs.map +1 -1
  41. package/dist/{tool-shell-D8Q8XX11.d.mts → tool-shell-CQZNRUgH.d.mts} +8 -4
  42. package/dist/{tool-shell-gmlj47Ie.d.ts → tool-shell-CRmceGrV.d.ts} +8 -4
  43. package/dist/{tools-DFIxIj5p.d.mts → tools-Bg1gi2HO.d.mts} +1 -1
  44. package/dist/{tools-BggNN5DV.d.ts → tools-Bw7RhO92.d.ts} +1 -1
  45. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -58,36 +58,174 @@ var TabsPrimitive__namespace = /*#__PURE__*/_interopNamespace(TabsPrimitive);
58
58
  var QRCode__default = /*#__PURE__*/_interopDefault(QRCode);
59
59
  var Link6__default = /*#__PURE__*/_interopDefault(Link6);
60
60
 
61
+ // src/tokens/palette.ts
62
+ var lightPalette = {
63
+ accent: "#f4f4f4",
64
+ accentDisplay: "#f55819",
65
+ accentForeground: "#0a0a0a",
66
+ accentInk: "#c73f09",
67
+ background: "#fafafa",
68
+ border: "#ececec",
69
+ brand: "#f66d36",
70
+ brandForeground: "#0a0a0a",
71
+ card: "#ffffff",
72
+ cardForeground: "#0a0a0a",
73
+ chart1: "#ea580b",
74
+ chart2: "#2563eb",
75
+ chart3: "#9d2b77",
76
+ chart4: "#92400e",
77
+ chartDown: "#c2262e",
78
+ chartGrid: "#ececec",
79
+ chartNeutral: "#8a8f96",
80
+ chartUp: "#15803d",
81
+ codeAdded: "#86d39b",
82
+ codeAddedLine: "#1a2c20",
83
+ codeComment: "#909397",
84
+ codeFunction: "#9db4ec",
85
+ codeKeyword: "#e3a8c2",
86
+ codeLine: "#2a2a2a",
87
+ codeLink: "#9db4ec",
88
+ codeMark: "#232323",
89
+ codeNumber: "#fcb781",
90
+ codePackage: "#e99a8f",
91
+ codeProperty: "#9db4ec",
92
+ codePunctuation: "#d5d8dc",
93
+ codeRemoved: "#f19a9a",
94
+ codeRemovedLine: "#2f1c1c",
95
+ codeString: "#e99a8f",
96
+ codeSurface: "#161616",
97
+ codeTag: "#e3a8c2",
98
+ codeType: "#8fd0c2",
99
+ destructive: "#c2262e",
100
+ destructiveForeground: "#ffffff",
101
+ foreground: "#0a0a0a",
102
+ hairlineStrong: "#dadada",
103
+ info: "#1d4ed8",
104
+ infoForeground: "#ffffff",
105
+ ink: "#0a0a0a",
106
+ inkCard: "#1e1e1e",
107
+ inkEyebrow: "#f0835a",
108
+ inkForeground: "#ffffff",
109
+ inkLine: "#2a2a2a",
110
+ inkMuted: "#d5d8dc",
111
+ inkSubtle: "#909397",
112
+ inkTitle: "#fcb781",
113
+ input: "#8f8f8f",
114
+ muted: "#f2f2f2",
115
+ mutedForeground: "#54585e",
116
+ ocWalletReady: "#15803d",
117
+ ocWalletSurface: "#ffffff",
118
+ orange: "#f66d36",
119
+ orangeDeep: "#ea580b",
120
+ orangeLight: "#fb933c",
121
+ outline: "#f2cfc3",
122
+ peach: "#fed8ab",
123
+ popover: "#ffffff",
124
+ popoverForeground: "#0a0a0a",
125
+ primary: "#0a0a0a",
126
+ primaryForeground: "#ffffff",
127
+ ring: "#ea580b",
128
+ secondary: "#ffffff",
129
+ secondaryForeground: "#0a0a0a",
130
+ skeleton: "#e8e8e8",
131
+ sphereFrom: "#ff6f33",
132
+ sphereTo: "#ffd9c4",
133
+ subtleForeground: "#686c72",
134
+ success: "#15803d",
135
+ successForeground: "#ffffff",
136
+ tableHead: "#ededed",
137
+ warning: "#a15c07",
138
+ warningForeground: "#ffffff"
139
+ };
140
+ var darkPalette = {
141
+ accent: "#1e1e1e",
142
+ accentDisplay: "#f66d36",
143
+ accentForeground: "#fafafa",
144
+ accentInk: "#f0835a",
145
+ background: "#0a0a0a",
146
+ bandLine: "#262626",
147
+ border: "#2a2a2a",
148
+ brand: "#f66d36",
149
+ brandForeground: "#0a0a0a",
150
+ card: "#161616",
151
+ cardForeground: "#fafafa",
152
+ chart1: "#f66d36",
153
+ chart2: "#3b82f6",
154
+ chart3: "#f9a8d4",
155
+ chart4: "#fde047",
156
+ chartDown: "#f87171",
157
+ chartGrid: "#2a2a2a",
158
+ chartNeutral: "#62676e",
159
+ chartUp: "#4ade80",
160
+ codeAdded: "#86d39b",
161
+ codeAddedLine: "#132519",
162
+ codeComment: "#909397",
163
+ codeFunction: "#9db4ec",
164
+ codeKeyword: "#e3a8c2",
165
+ codeLine: "#2a2a2a",
166
+ codeLink: "#9db4ec",
167
+ codeMark: "#1b1b1b",
168
+ codeNumber: "#fcb781",
169
+ codePackage: "#e99a8f",
170
+ codeProperty: "#9db4ec",
171
+ codePunctuation: "#d5d8dc",
172
+ codeRemoved: "#f19a9a",
173
+ codeRemovedLine: "#271414",
174
+ codeString: "#e99a8f",
175
+ codeSurface: "#0e0e0e",
176
+ codeTag: "#e3a8c2",
177
+ codeType: "#8fd0c2",
178
+ destructive: "#f87171",
179
+ destructiveForeground: "#0a0a0a",
180
+ foreground: "#fafafa",
181
+ hairlineStrong: "#333333",
182
+ iconRing: "#333333",
183
+ iconTile: "#1e1e1e",
184
+ info: "#93c5fd",
185
+ infoForeground: "#0a0a0a",
186
+ ink: "#171717",
187
+ inkCard: "#1e1e1e",
188
+ inkEyebrow: "#f0835a",
189
+ inkForeground: "#ffffff",
190
+ inkLine: "#2a2a2a",
191
+ inkMuted: "#d5d8dc",
192
+ inkSubtle: "#909397",
193
+ inkTitle: "#fcb781",
194
+ input: "#6a6a6a",
195
+ muted: "#1e1e1e",
196
+ mutedForeground: "#a3a6aa",
197
+ ocWalletReady: "#4ade80",
198
+ ocWalletSurface: "#161616",
199
+ orange: "#f66d36",
200
+ orangeDeep: "#ea580b",
201
+ orangeLight: "#fb933c",
202
+ outline: "#3a2a24",
203
+ peach: "#fed8ab",
204
+ popover: "#1a1a1a",
205
+ popoverForeground: "#fafafa",
206
+ primary: "#fafafa",
207
+ primaryForeground: "#0a0a0a",
208
+ ring: "#f66d36",
209
+ secondary: "#1c1c1c",
210
+ secondaryForeground: "#fafafa",
211
+ skeleton: "#222222",
212
+ sphereFrom: "#ff6f33",
213
+ sphereTo: "#ffd9c4",
214
+ subtleForeground: "#8b8e93",
215
+ success: "#4ade80",
216
+ successForeground: "#0a0a0a",
217
+ tableHead: "#1e1e1e",
218
+ warning: "#fbbf24",
219
+ warningForeground: "#0a0a0a"
220
+ };
221
+
61
222
  // src/tokens/index.ts
62
223
  var APP_ATTRIBUTE = "data-oc-app";
63
224
  var APP_ID = "ochk";
64
225
  var appColors = {
65
- light: {
66
- background: "#FAFAFA",
67
- foreground: "#0A0A0A",
68
- card: "#FFFFFF",
69
- muted: "#F2F2F2",
70
- mutedForeground: "#54585E",
71
- subtleForeground: "#686C72",
72
- border: "#ECECEC",
73
- hairlineStrong: "#DADADA",
74
- accentDisplay: "#F55819",
75
- accentInk: "#C73F09",
76
- ring: "#EA580B"
77
- },
78
- dark: {
79
- background: "#0A0A0A",
80
- foreground: "#FAFAFA",
81
- card: "#161616",
82
- muted: "#1E1E1E",
83
- mutedForeground: "#A3A6AA",
84
- subtleForeground: "#8B8E93",
85
- border: "#2A2A2A",
86
- hairlineStrong: "#333333",
87
- accentDisplay: "#F66D36",
88
- accentInk: "#F0835A",
89
- ring: "#F66D36"
90
- },
226
+ /** Every colour token, generated from tokens.css (palette.ts): the chart series, code, ink and status colours too. */
227
+ light: lightPalette,
228
+ dark: darkPalette,
91
229
  brand: {
92
230
  orange: "#F66D36",
93
231
  orangeLight: "#FB933C",
@@ -966,7 +1104,9 @@ var none = () => null;
966
1104
  function PromptBody({ ask: a }) {
967
1105
  const o = a.options;
968
1106
  const [value, setValue] = react.useState(o.defaultValue ?? "");
1107
+ const [again, setAgain] = react.useState("");
969
1108
  const [error, setError] = react.useState(null);
1109
+ const [mismatch, setMismatch] = react.useState(false);
970
1110
  const submit = (e) => {
971
1111
  e.preventDefault();
972
1112
  if (o.minLength && value.length < o.minLength) {
@@ -978,6 +1118,10 @@ function PromptBody({ ask: a }) {
978
1118
  setError(refused);
979
1119
  return;
980
1120
  }
1121
+ if (o.confirmField && again !== value) {
1122
+ setMismatch(true);
1123
+ return;
1124
+ }
981
1125
  a.settle(value);
982
1126
  done();
983
1127
  };
@@ -993,9 +1137,30 @@ function PromptBody({ ask: a }) {
993
1137
  onChange: (e) => {
994
1138
  setValue(e.target.value);
995
1139
  setError(null);
1140
+ setMismatch(false);
996
1141
  }
997
1142
  }
998
1143
  ) }),
1144
+ o.confirmField ? /* @__PURE__ */ jsxRuntime.jsx(
1145
+ Field,
1146
+ {
1147
+ label: o.confirmField === true ? "Type it again" : o.confirmField,
1148
+ error: mismatch ? "The two do not match." : null,
1149
+ className: "mt-4",
1150
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1151
+ Input,
1152
+ {
1153
+ type: o.secret ? "password" : "text",
1154
+ autoComplete: o.secret ? "new-password" : "off",
1155
+ value: again,
1156
+ onChange: (e) => {
1157
+ setAgain(e.target.value);
1158
+ setMismatch(false);
1159
+ }
1160
+ }
1161
+ )
1162
+ }
1163
+ ) : null,
999
1164
  /* @__PURE__ */ jsxRuntime.jsxs(DialogFooter, { children: [
1000
1165
  /* @__PURE__ */ jsxRuntime.jsx(
1001
1166
  Button,
@@ -2036,7 +2201,7 @@ var JS_TAG = /<\/?(?=[A-Za-z])/y;
2036
2201
  var JS_TAG_NAME = /[A-Za-z][\w$.:-]*/y;
2037
2202
  var JS_PUNCT = /=>|\.\.\.|[{}()[\];,.<>=+\-*/%!?:&|^~#]/y;
2038
2203
  var JSX_BEFORE = /* @__PURE__ */ new Set(["(", ",", "=", "?", ":", "{", "[", ";", ">", "&&", "||", "=>", "return"]);
2039
- function scanJs(src, emit2, jsx50) {
2204
+ function scanJs(src, emit2, jsx52) {
2040
2205
  let i = 0;
2041
2206
  let prev = "";
2042
2207
  let tagDepth = 0;
@@ -2062,7 +2227,7 @@ function scanJs(src, emit2, jsx50) {
2062
2227
  sig('"');
2063
2228
  continue;
2064
2229
  }
2065
- if (jsx50 && tagDepth === 0 && (m = at(JS_TAG, src, i)) && (prev === "" || JSX_BEFORE.has(prev))) {
2230
+ if (jsx52 && tagDepth === 0 && (m = at(JS_TAG, src, i)) && (prev === "" || JSX_BEFORE.has(prev))) {
2066
2231
  const name = at(JS_TAG_NAME, src, i + m.length);
2067
2232
  if (name) {
2068
2233
  emit2(m);
@@ -2074,7 +2239,7 @@ function scanJs(src, emit2, jsx50) {
2074
2239
  continue;
2075
2240
  }
2076
2241
  }
2077
- if (jsx50 && tagDepth > 0 && braceInTag === 0) {
2242
+ if (jsx52 && tagDepth > 0 && braceInTag === 0) {
2078
2243
  if (src.startsWith("/>", i) || src[i] === ">") {
2079
2244
  const close = src[i] === ">" ? ">" : "/>";
2080
2245
  emit2(close);
@@ -2094,7 +2259,7 @@ function scanJs(src, emit2, jsx50) {
2094
2259
  continue;
2095
2260
  }
2096
2261
  if (src[i] === "{") braceInTag = 1;
2097
- } else if (jsx50 && tagDepth > 0 && braceInTag > 0) {
2262
+ } else if (jsx52 && tagDepth > 0 && braceInTag > 0) {
2098
2263
  if (src[i] === "{") braceInTag++;
2099
2264
  else if (src[i] === "}") braceInTag--;
2100
2265
  }
@@ -2512,7 +2677,22 @@ function PageHeader({
2512
2677
  ] });
2513
2678
  }
2514
2679
  var InStatGrid = react.createContext(false);
2515
- function StatCard({ label, value, hint, size, className }) {
2680
+ function Delta({ value, suffix = "", good = "up", label }) {
2681
+ const dir = value > 0 ? "up" : value < 0 ? "down" : "flat";
2682
+ const tone = dir === "flat" ? "text-muted-foreground" : dir === good ? "text-success" : "text-destructive";
2683
+ const sign = value > 0 ? "+" : value < 0 ? "\u2212" : "";
2684
+ return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: cn("inline-flex items-baseline gap-1 text-[0.8125rem] font-normal tracking-normal oca-tabular", tone), children: [
2685
+ /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, children: dir === "up" ? "\u2191" : dir === "down" ? "\u2193" : "\xB7" }),
2686
+ sign,
2687
+ Math.abs(value).toLocaleString("en-US", { maximumFractionDigits: 2 }),
2688
+ suffix,
2689
+ label ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-muted-foreground", children: [
2690
+ " ",
2691
+ label
2692
+ ] }) : null
2693
+ ] });
2694
+ }
2695
+ function StatCard({ label, value, hint, size, delta, className }) {
2516
2696
  const inGrid = react.useContext(InStatGrid);
2517
2697
  const density = useDensity();
2518
2698
  const sm = (size ?? (density === "compact" ? "sm" : "md")) === "sm";
@@ -2530,15 +2710,19 @@ function StatCard({ label, value, hint, size, className }) {
2530
2710
  ),
2531
2711
  children: [
2532
2712
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("leading-snug text-muted-foreground", sm ? "text-[0.8125rem]" : "text-[0.875rem]"), children: label }),
2533
- /* @__PURE__ */ jsxRuntime.jsx(
2713
+ /* @__PURE__ */ jsxRuntime.jsxs(
2534
2714
  "span",
2535
2715
  {
2536
2716
  className: cn(
2537
2717
  "break-words oca-tabular leading-tight tracking-[-0.02em]",
2538
2718
  sm ? "text-[1.25rem]" : "text-[1.5rem] md:text-[1.75rem]",
2539
- inGrid && "self-end"
2719
+ inGrid && "self-end",
2720
+ delta && "flex flex-wrap items-baseline gap-x-2"
2540
2721
  ),
2541
- children: value
2722
+ children: [
2723
+ value,
2724
+ delta ? /* @__PURE__ */ jsxRuntime.jsx(Delta, { ...delta }) : null
2725
+ ]
2542
2726
  }
2543
2727
  ),
2544
2728
  hint ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[0.8125rem] leading-snug text-muted-foreground", children: hint }) : inGrid ? /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true }) : null
@@ -2627,6 +2811,13 @@ function StatGrid({ columns, empty, isEmpty, className, children, ...props }) {
2627
2811
  }
2628
2812
  ) });
2629
2813
  }
2814
+ var TONE_TEXT = {
2815
+ good: "text-success",
2816
+ caution: "text-warning",
2817
+ bad: "text-destructive",
2818
+ brand: "text-oca-accent-ink",
2819
+ muted: "text-muted-foreground"
2820
+ };
2630
2821
  function KeyValueList({
2631
2822
  items,
2632
2823
  dense,
@@ -2645,15 +2836,19 @@ function KeyValueList({
2645
2836
  ),
2646
2837
  children: [
2647
2838
  /* @__PURE__ */ jsxRuntime.jsx("dt", { className: cn("shrink-0 text-muted-foreground", tight ? "text-[0.8125rem] @md:w-36" : "text-[0.875rem] @md:w-48"), children: it.label }),
2648
- /* @__PURE__ */ jsxRuntime.jsx(
2839
+ /* @__PURE__ */ jsxRuntime.jsxs(
2649
2840
  "dd",
2650
2841
  {
2651
2842
  className: cn(
2652
2843
  "min-w-0 break-words",
2653
2844
  tight ? "text-[0.875rem]" : "text-[0.9375rem]",
2654
- it.mono && (tight ? "font-mono text-[0.8125rem]" : "font-mono text-[0.875rem]")
2845
+ it.mono && (tight ? "font-mono text-[0.8125rem]" : "font-mono text-[0.875rem]"),
2846
+ it.tone && !it.note && TONE_TEXT[it.tone]
2655
2847
  ),
2656
- children: it.value
2848
+ children: [
2849
+ it.value,
2850
+ it.note ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("ml-2 font-sans text-[0.8125rem]", TONE_TEXT[it.tone ?? "muted"]), children: it.note }) : null
2851
+ ]
2657
2852
  }
2658
2853
  )
2659
2854
  ]
@@ -3809,6 +4004,310 @@ function ErrorPage({
3809
4004
  art !== null ? /* @__PURE__ */ jsxRuntime.jsx("div", { "aria-hidden": true, className: "oca-enter hidden justify-center md:col-span-5 md:flex [--enter-delay:120ms]", children: art ?? /* @__PURE__ */ jsxRuntime.jsx(MarkOutline, { className: "w-full max-w-[20rem] text-oca-hairline-strong" }) }) : null
3810
4005
  ] }) });
3811
4006
  }
4007
+ function onSecond(tick) {
4008
+ const id = setInterval(tick, 1e3);
4009
+ return () => clearInterval(id);
4010
+ }
4011
+ var nowSeconds = () => Math.floor(Date.now() / 1e3);
4012
+ function CountdownRing({
4013
+ period,
4014
+ remaining,
4015
+ warnAt = 5,
4016
+ size = 18,
4017
+ showSeconds = true,
4018
+ className
4019
+ }) {
4020
+ const now = react.useSyncExternalStore(onSecond, nowSeconds, () => null);
4021
+ const left = remaining ?? (now === null ? null : period - now % period);
4022
+ const share = left === null ? 1 : Math.max(0, Math.min(1, left / period));
4023
+ const warn = left !== null && left <= warnAt;
4024
+ const r = size / 2 - 1.5;
4025
+ const c = 2 * Math.PI * r;
4026
+ return /* @__PURE__ */ jsxRuntime.jsxs(
4027
+ "span",
4028
+ {
4029
+ role: "timer",
4030
+ "aria-label": left === null ? void 0 : `${left} second${left === 1 ? "" : "s"} left`,
4031
+ className: cn("inline-flex items-center gap-1.5", warn ? "text-destructive" : "text-muted-foreground", className),
4032
+ children: [
4033
+ /* @__PURE__ */ jsxRuntime.jsxs("svg", { "aria-hidden": true, width: size, height: size, viewBox: `0 0 ${size} ${size}`, className: "-rotate-90", children: [
4034
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: size / 2, cy: size / 2, r, fill: "none", stroke: "var(--border)", strokeWidth: 2 }),
4035
+ /* @__PURE__ */ jsxRuntime.jsx(
4036
+ "circle",
4037
+ {
4038
+ cx: size / 2,
4039
+ cy: size / 2,
4040
+ r,
4041
+ fill: "none",
4042
+ stroke: "currentColor",
4043
+ strokeWidth: 2,
4044
+ strokeLinecap: "round",
4045
+ strokeDasharray: c,
4046
+ strokeDashoffset: c * (1 - share),
4047
+ className: cn(left !== null && left < period && "transition-[stroke-dashoffset] duration-1000 ease-linear motion-reduce:transition-none")
4048
+ }
4049
+ )
4050
+ ] }),
4051
+ showSeconds && left !== null ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-[0.8125rem] oca-tabular", children: [
4052
+ left,
4053
+ "s"
4054
+ ] }) : null
4055
+ ]
4056
+ }
4057
+ );
4058
+ }
4059
+ function PlanCard({
4060
+ name,
4061
+ subtitle,
4062
+ price,
4063
+ period,
4064
+ footnote,
4065
+ features = [],
4066
+ action,
4067
+ badge,
4068
+ badgeTone = "neutral",
4069
+ highlight: highlight2 = false,
4070
+ className
4071
+ }) {
4072
+ return /* @__PURE__ */ jsxRuntime.jsxs(
4073
+ "section",
4074
+ {
4075
+ className: cn(
4076
+ "flex h-full flex-col gap-5 rounded-[1.25rem] border bg-card p-6",
4077
+ highlight2 ? "border-foreground shadow-sm ring-1 ring-foreground" : "border-border",
4078
+ className
4079
+ ),
4080
+ children: [
4081
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1.5", children: [
4082
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-3", children: [
4083
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-[1.0625rem] font-medium leading-snug", children: name }),
4084
+ badge ? /* @__PURE__ */ jsxRuntime.jsx(Badge, { tone: badgeTone, children: badge }) : null
4085
+ ] }),
4086
+ subtitle ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[0.875rem] leading-snug text-muted-foreground", children: subtitle }) : null
4087
+ ] }),
4088
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
4089
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "flex flex-wrap items-baseline gap-x-1.5", children: [
4090
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "oca-display-3 oca-tabular", children: price }),
4091
+ period ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[0.9375rem] text-muted-foreground", children: period }) : null
4092
+ ] }),
4093
+ footnote ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[0.8125rem] text-muted-foreground", children: footnote }) : null
4094
+ ] }),
4095
+ features.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "flex flex-col gap-2.5 text-[0.9375rem]", children: features.map((f, i) => /* @__PURE__ */ jsxRuntime.jsxs("li", { className: "flex items-start gap-2.5", children: [
4096
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { "aria-hidden": true, className: "mt-1 size-4 shrink-0 text-muted-foreground" }),
4097
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0", children: f })
4098
+ ] }, i)) }) : null,
4099
+ action ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-auto flex flex-col pt-1 [&>*]:w-full", children: action }) : null
4100
+ ]
4101
+ }
4102
+ );
4103
+ }
4104
+ function LockedPreview({
4105
+ title,
4106
+ description,
4107
+ action,
4108
+ children,
4109
+ className
4110
+ }) {
4111
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("relative", className), children: [
4112
+ children ? /* @__PURE__ */ jsxRuntime.jsx(
4113
+ "div",
4114
+ {
4115
+ inert: true,
4116
+ "aria-hidden": true,
4117
+ "data-oca-locked": "",
4118
+ className: "pointer-events-none max-h-[28rem] select-none overflow-hidden [mask-image:linear-gradient(to_bottom,#000_25%,transparent_85%)]",
4119
+ children
4120
+ }
4121
+ ) : null,
4122
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("relative mx-auto flex max-w-md flex-col items-center gap-4 rounded-[1.25rem] border border-border bg-card px-6 py-7 text-center shadow-sm", children && "-mt-40"), children: [
4123
+ /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, className: "flex size-10 items-center justify-center rounded-full bg-muted text-foreground", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Lock, { className: "size-[1.125rem]" }) }),
4124
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1.5", children: [
4125
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[1.0625rem] font-medium leading-snug", children: title }),
4126
+ description ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[0.9375rem] leading-snug text-muted-foreground", children: description }) : null
4127
+ ] }),
4128
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap justify-center gap-2", children: action })
4129
+ ] })
4130
+ ] });
4131
+ }
4132
+ function chartColor(series) {
4133
+ if (typeof series === "string") return `var(--oca-chart-${series})`;
4134
+ const n = series >= 1 && series <= 4 && Number.isInteger(series) ? series : (series % 4 + 4) % 4 + 1;
4135
+ return `var(--oca-chart-${n})`;
4136
+ }
4137
+ function ChartFrame({
4138
+ legend,
4139
+ caption,
4140
+ children,
4141
+ className
4142
+ }) {
4143
+ return /* @__PURE__ */ jsxRuntime.jsxs("figure", { className: cn("oca-chart flex min-w-0 flex-col gap-3", className), children: [
4144
+ legend && legend.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "oca-chart-legend", "aria-label": "Legend", children: legend.map((l, i) => {
4145
+ const c = typeof l.color === "number" || ["neutral", "up", "down"].includes(String(l.color)) ? chartColor(l.color) : String(l.color);
4146
+ return /* @__PURE__ */ jsxRuntime.jsxs("li", { children: [
4147
+ /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, "data-swatch": l.dashed ? "dashed" : "", style: { "--swatch": c } }),
4148
+ l.label
4149
+ ] }, i);
4150
+ }) }) : null,
4151
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative min-w-0", children }),
4152
+ caption ? /* @__PURE__ */ jsxRuntime.jsx("figcaption", { className: "text-[0.8125rem] leading-snug text-muted-foreground", children: caption }) : null
4153
+ ] });
4154
+ }
4155
+ function Sparkline({
4156
+ values,
4157
+ label,
4158
+ tone = "ink",
4159
+ area = false,
4160
+ width = 96,
4161
+ height = 24,
4162
+ className
4163
+ }) {
4164
+ const gradient = react.useId().replace(/[^a-zA-Z0-9]/g, "");
4165
+ const pts = values.filter((v) => Number.isFinite(v));
4166
+ const lo = Math.min(...pts);
4167
+ const hi = Math.max(...pts);
4168
+ const span = hi - lo || 1;
4169
+ const pad3 = 1.5;
4170
+ const x = (i) => pts.length < 2 ? width / 2 : i / (pts.length - 1) * width;
4171
+ const y = (v) => pad3 + (1 - (v - lo) / span) * (height - pad3 * 2);
4172
+ const line = pts.map((v, i) => `${i === 0 ? "M" : "L"}${x(i).toFixed(2)},${y(v).toFixed(2)}`).join(" ");
4173
+ const color = tone === "ink" ? "var(--foreground)" : tone === "muted" ? "var(--muted-foreground)" : tone === "trend" ? chartColor(pts.length > 1 && pts[pts.length - 1] < pts[0] ? "down" : "up") : chartColor(tone);
4174
+ return /* @__PURE__ */ jsxRuntime.jsx(
4175
+ "svg",
4176
+ {
4177
+ role: "img",
4178
+ "aria-label": label,
4179
+ viewBox: `0 0 ${width} ${height}`,
4180
+ preserveAspectRatio: "none",
4181
+ width,
4182
+ height,
4183
+ className: cn("block overflow-visible", className),
4184
+ style: { color },
4185
+ children: pts.length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
4186
+ area ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
4187
+ /* @__PURE__ */ jsxRuntime.jsx("defs", { children: /* @__PURE__ */ jsxRuntime.jsxs("linearGradient", { id: gradient, x1: "0", y1: "0", x2: "0", y2: "1", children: [
4188
+ /* @__PURE__ */ jsxRuntime.jsx("stop", { offset: "0", stopColor: "currentColor", stopOpacity: 0.22 }),
4189
+ /* @__PURE__ */ jsxRuntime.jsx("stop", { offset: "1", stopColor: "currentColor", stopOpacity: 0 })
4190
+ ] }) }),
4191
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: `${line} L${x(pts.length - 1).toFixed(2)},${height} L${x(0).toFixed(2)},${height} Z`, fill: `url(#${gradient})` })
4192
+ ] }) : null,
4193
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: line, fill: "none", stroke: "currentColor", strokeWidth: 1.5, strokeLinejoin: "round", strokeLinecap: "round", vectorEffect: "non-scaling-stroke" })
4194
+ ] }) : null
4195
+ }
4196
+ );
4197
+ }
4198
+ function SourceNote({ source, href, detail, updated, variant = "popover", className }) {
4199
+ const name = href ? /* @__PURE__ */ jsxRuntime.jsxs("a", { href, className: "text-foreground underline decoration-foreground/35 underline-offset-4 hover:decoration-foreground", rel: "noreferrer", target: "_blank", children: [
4200
+ source,
4201
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: " (opens in a new tab)" })
4202
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-foreground", children: source });
4203
+ if (variant === "line") {
4204
+ return /* @__PURE__ */ jsxRuntime.jsxs("p", { className: cn("text-[0.75rem] leading-snug text-muted-foreground", className), children: [
4205
+ "Source: ",
4206
+ name,
4207
+ updated ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
4208
+ " \xB7 ",
4209
+ updated
4210
+ ] }) : null
4211
+ ] });
4212
+ }
4213
+ return /* @__PURE__ */ jsxRuntime.jsxs(Popover, { children: [
4214
+ /* @__PURE__ */ jsxRuntime.jsxs(
4215
+ PopoverTrigger,
4216
+ {
4217
+ className: cn(
4218
+ "inline-flex h-7 items-center gap-1 rounded-full px-2 text-[0.75rem] text-muted-foreground transition-colors hover:bg-accent hover:text-foreground",
4219
+ className
4220
+ ),
4221
+ children: [
4222
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Info, { "aria-hidden": true, className: "size-3.5" }),
4223
+ "Source"
4224
+ ]
4225
+ }
4226
+ ),
4227
+ /* @__PURE__ */ jsxRuntime.jsxs(PopoverContent, { align: "start", className: "flex w-[min(calc(100vw-2rem),20rem)] flex-col gap-2 p-4 text-[0.875rem]", children: [
4228
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[0.75rem] text-muted-foreground", children: "Where this number comes from" }),
4229
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "font-medium", children: name }),
4230
+ detail ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-[0.8125rem] leading-snug text-muted-foreground [&_code]:font-mono", children: detail }) : null,
4231
+ updated ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[0.8125rem] text-muted-foreground", children: updated }) : null
4232
+ ] })
4233
+ ] });
4234
+ }
4235
+ function Panel({
4236
+ title,
4237
+ description,
4238
+ actions,
4239
+ source,
4240
+ expandable = false,
4241
+ children,
4242
+ className
4243
+ }) {
4244
+ const [open, setOpen] = react.useState(false);
4245
+ const body = (expanded) => typeof children === "function" ? children(expanded) : children;
4246
+ const head = (expanded) => /* @__PURE__ */ jsxRuntime.jsxs("header", { className: "flex flex-wrap items-start justify-between gap-x-4 gap-y-2", children: [
4247
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-col gap-1", children: [
4248
+ expanded ? /* @__PURE__ */ jsxRuntime.jsx(DialogTitle, { className: "text-[1.0625rem] font-medium leading-snug", children: title }) : /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-[1rem] font-medium leading-snug", children: title }),
4249
+ description ? expanded ? /* @__PURE__ */ jsxRuntime.jsx(DialogDescription, { className: "text-[0.875rem] leading-snug text-muted-foreground", children: description }) : /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[0.875rem] leading-snug text-muted-foreground", children: description }) : null
4250
+ ] }),
4251
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex shrink-0 items-center gap-1", children: [
4252
+ actions,
4253
+ expandable && !expanded ? /* @__PURE__ */ jsxRuntime.jsx(
4254
+ "button",
4255
+ {
4256
+ type: "button",
4257
+ onClick: () => setOpen(true),
4258
+ "aria-label": "Open full screen",
4259
+ className: "inline-flex size-8 items-center justify-center rounded-full text-muted-foreground transition-colors hover:bg-accent hover:text-foreground",
4260
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Maximize2, { "aria-hidden": true, className: "size-4" })
4261
+ }
4262
+ ) : null
4263
+ ] })
4264
+ ] });
4265
+ return /* @__PURE__ */ jsxRuntime.jsxs("section", { className: cn("flex min-w-0 flex-col gap-4 rounded-[1.25rem] border border-border bg-card p-5 md:p-6", className), children: [
4266
+ head(false),
4267
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-w-0", children: body(false) }),
4268
+ source ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "-mb-1 border-t border-border pt-3", children: source }) : null,
4269
+ expandable ? /* @__PURE__ */ jsxRuntime.jsx(Dialog, { open, onOpenChange: setOpen, children: /* @__PURE__ */ jsxRuntime.jsxs(
4270
+ DialogContent,
4271
+ {
4272
+ ...description ? {} : { "aria-describedby": void 0 },
4273
+ className: "flex h-[min(92dvh,56rem)] w-[min(96vw,80rem)] max-w-none flex-col gap-4 overflow-y-auto",
4274
+ children: [
4275
+ head(true),
4276
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-h-0 min-w-0 flex-1", children: open ? body(true) : null }),
4277
+ source ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-t border-border pt-3", children: source }) : null
4278
+ ]
4279
+ }
4280
+ ) }) : null
4281
+ ] });
4282
+ }
4283
+ function HudCard({
4284
+ eyebrow,
4285
+ live = false,
4286
+ title,
4287
+ children,
4288
+ footer,
4289
+ className
4290
+ }) {
4291
+ return /* @__PURE__ */ jsxRuntime.jsxs(
4292
+ "div",
4293
+ {
4294
+ "data-oca-hud": "",
4295
+ className: cn(
4296
+ "flex w-60 max-w-[calc(100vw-2rem)] flex-col gap-2 rounded-xl border border-border bg-background/85 p-3 text-[0.8125rem] shadow-sm backdrop-blur-md",
4297
+ className
4298
+ ),
4299
+ children: [
4300
+ eyebrow ? /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "flex items-center gap-1.5 text-[0.75rem] text-muted-foreground", children: [
4301
+ live ? /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, className: "size-1.5 rounded-full bg-oca-orange-deep motion-safe:animate-pulse" }) : null,
4302
+ eyebrow
4303
+ ] }) : null,
4304
+ title ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[1.125rem] font-medium leading-tight oca-tabular", children: title }) : null,
4305
+ children,
4306
+ footer ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-t border-border pt-2", children: footer }) : null
4307
+ ]
4308
+ }
4309
+ );
4310
+ }
3812
4311
  function SectionHeading({
3813
4312
  eyebrow,
3814
4313
  title,
@@ -4966,6 +5465,7 @@ function SearchDialog({
4966
5465
  idle,
4967
5466
  defaultQuery = "",
4968
5467
  debounceMs = 120,
5468
+ browse = false,
4969
5469
  className
4970
5470
  }) {
4971
5471
  const [own, setOwn] = react.useState(false);
@@ -5002,7 +5502,7 @@ function SearchDialog({
5002
5502
  }, [hotkey]);
5003
5503
  react.useEffect(() => {
5004
5504
  const q = query.trim();
5005
- if (!q) {
5505
+ if (!q && !(browse && open)) {
5006
5506
  setGroups([]);
5007
5507
  setState("idle");
5008
5508
  return;
@@ -5024,14 +5524,15 @@ function SearchDialog({
5024
5524
  clearTimeout(t);
5025
5525
  ctl.abort();
5026
5526
  };
5027
- }, [query, debounceMs]);
5527
+ }, [query, debounceMs, browse, open]);
5028
5528
  react.useEffect(() => {
5029
5529
  listRef.current?.querySelector('[aria-selected="true"]')?.scrollIntoView({ block: "nearest" });
5030
5530
  }, [active]);
5031
5531
  const choose = (r) => {
5032
5532
  setOpen(false);
5033
- if (onSelect) onSelect(r);
5034
- else window.location.assign(r.href);
5533
+ if (r.run) r.run();
5534
+ else if (onSelect) onSelect(r);
5535
+ else if (r.href) window.location.assign(r.href);
5035
5536
  };
5036
5537
  const optionId = (i) => `${listId}-o${i}`;
5037
5538
  const showList = state === "done" && flat.length > 0;
@@ -5102,25 +5603,28 @@ function SearchDialog({
5102
5603
  index++;
5103
5604
  const i = index;
5104
5605
  const on = i === active;
5606
+ const Option = r.href ? "a" : "div";
5105
5607
  return /* @__PURE__ */ jsxRuntime.jsxs(
5106
- "a",
5608
+ Option,
5107
5609
  {
5108
5610
  id: optionId(i),
5109
- href: r.href,
5611
+ ...r.href ? { href: r.href } : {},
5110
5612
  role: "option",
5111
5613
  "aria-selected": on,
5112
5614
  tabIndex: -1,
5113
5615
  onMouseMove: () => setActive(i),
5114
5616
  onClick: (e) => {
5115
- if (e.metaKey || e.ctrlKey || e.shiftKey) return;
5617
+ if (r.href && (e.metaKey || e.ctrlKey || e.shiftKey)) return;
5116
5618
  e.preventDefault();
5117
5619
  choose(r);
5118
5620
  },
5119
5621
  className: cn(
5120
5622
  "flex items-start gap-3 rounded-xl px-3 py-2.5 transition-colors",
5121
- on ? "bg-accent" : "hover:bg-accent"
5623
+ on ? "bg-accent" : "hover:bg-accent",
5624
+ !r.href && "cursor-pointer"
5122
5625
  ),
5123
5626
  children: [
5627
+ r.icon ? /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, className: "mt-0.5 flex size-5 shrink-0 items-center justify-center text-muted-foreground [&_svg]:size-[1.0625rem]", children: r.icon }) : null,
5124
5628
  /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex min-w-0 flex-1 flex-col gap-0.5", children: [
5125
5629
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-[0.9375rem] font-medium text-foreground", children: r.title }),
5126
5630
  r.section ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-[0.8125rem] text-muted-foreground", children: r.section }) : null,
@@ -5132,6 +5636,7 @@ function SearchDialog({
5132
5636
  }
5133
5637
  ) : r.excerpt ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "line-clamp-2 text-[0.875rem] leading-snug text-muted-foreground", children: r.excerpt }) : null
5134
5638
  ] }),
5639
+ r.meta ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "mt-0.5 shrink-0 text-[0.8125rem] text-muted-foreground", children: r.meta }) : null,
5135
5640
  /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CornerDownLeft, { "aria-hidden": true, className: cn("mt-1 size-4 shrink-0 text-muted-foreground", !on && "invisible") })
5136
5641
  ]
5137
5642
  },
@@ -5140,11 +5645,11 @@ function SearchDialog({
5140
5645
  })
5141
5646
  ] }, gi)) }),
5142
5647
  state === "idle" ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-3 py-6 text-[0.9375rem] text-muted-foreground", children: idle ?? "Type a word: a protocol, a function, an error." }) : null,
5143
- state === "done" && flat.length === 0 ? /* @__PURE__ */ jsxRuntime.jsxs("p", { role: "status", className: "px-3 py-6 text-[0.9375rem] text-muted-foreground", children: [
5648
+ state === "done" && flat.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("p", { role: "status", className: "px-3 py-6 text-[0.9375rem] text-muted-foreground", children: query.trim() ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
5144
5649
  "No results for \u201C",
5145
5650
  query.trim(),
5146
5651
  "\u201D."
5147
- ] }) : null,
5652
+ ] }) : "Nothing here yet." }) : null,
5148
5653
  state === "error" ? /* @__PURE__ */ jsxRuntime.jsx("p", { role: "status", className: "px-3 py-6 text-[0.9375rem] text-muted-foreground", children: "Search is not available right now. Try again in a moment." }) : null
5149
5654
  ] }),
5150
5655
  /* @__PURE__ */ jsxRuntime.jsxs("div", { "aria-hidden": true, className: "hidden shrink-0 items-center gap-4 border-t border-border px-5 py-2.5 text-[0.75rem] text-muted-foreground sm:flex", children: [
@@ -5169,6 +5674,13 @@ function SearchDialog({
5169
5674
  ] }) })
5170
5675
  ] });
5171
5676
  }
5677
+ function CommandDialog({
5678
+ label = "Commands",
5679
+ placeholder = "Search, or run a command",
5680
+ ...props
5681
+ }) {
5682
+ return /* @__PURE__ */ jsxRuntime.jsx(SearchDialog, { ...props, label, placeholder, button: false, browse: true });
5683
+ }
5172
5684
  function pretty(content) {
5173
5685
  try {
5174
5686
  return JSON.stringify(JSON.parse(content), null, 2);
@@ -5597,6 +6109,13 @@ function BlockCountdown({
5597
6109
  ] }) : null
5598
6110
  ] });
5599
6111
  }
6112
+ var METER_FILL = {
6113
+ ink: "bg-foreground",
6114
+ brand: "bg-oca-orange-deep",
6115
+ good: "bg-success",
6116
+ caution: "bg-warning",
6117
+ bad: "bg-destructive"
6118
+ };
5600
6119
  function Meter({
5601
6120
  value,
5602
6121
  max,
@@ -5631,7 +6150,7 @@ function Meter({
5631
6150
  /* @__PURE__ */ jsxRuntime.jsx(
5632
6151
  "div",
5633
6152
  {
5634
- className: cn("h-full shrink-0 rounded-full", tone === "brand" ? "bg-oca-orange-deep" : "bg-foreground"),
6153
+ className: cn("h-full shrink-0 rounded-full", METER_FILL[tone]),
5635
6154
  style: { width: `${v * 100}%` }
5636
6155
  }
5637
6156
  ),
@@ -5878,48 +6397,106 @@ function SectionSwitch({
5878
6397
  }
5879
6398
  );
5880
6399
  }
6400
+ function NavBadge({ badge, className }) {
6401
+ if (typeof badge === "number") {
6402
+ return /* @__PURE__ */ jsxRuntime.jsx(
6403
+ "span",
6404
+ {
6405
+ "aria-hidden": true,
6406
+ className: cn(
6407
+ "absolute flex h-4 min-w-4 items-center justify-center rounded-full bg-primary px-1 text-[0.625rem] font-medium leading-none text-primary-foreground ring-2 ring-background oca-tabular",
6408
+ className
6409
+ ),
6410
+ children: badge > 99 ? "99+" : badge
6411
+ }
6412
+ );
6413
+ }
6414
+ return /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, className: cn("absolute size-2 rounded-full bg-oca-orange-deep ring-2 ring-background", className) });
6415
+ }
6416
+ var TAB = "flex min-w-0 flex-col items-center justify-center gap-1 rounded-2xl text-[0.6875rem] leading-none outline-none transition-colors [-webkit-tap-highlight-color:transparent] focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring";
6417
+ function TabFace({ icon, label, badge, active }) {
6418
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
6419
+ /* @__PURE__ */ jsxRuntime.jsxs(
6420
+ "span",
6421
+ {
6422
+ className: cn(
6423
+ "relative flex h-7 w-12 items-center justify-center rounded-full transition-[background-color,box-shadow] duration-200",
6424
+ "[&_svg]:size-[1.125rem] [&_svg]:shrink-0",
6425
+ active ? "bg-card shadow-sm ring-1 ring-border [&_svg]:stroke-2" : "[&_svg]:stroke-[1.75]"
6426
+ ),
6427
+ children: [
6428
+ icon,
6429
+ badge ? /* @__PURE__ */ jsxRuntime.jsx(NavBadge, { badge, className: typeof badge === "number" ? "-top-1 right-0.5" : "right-2.5 top-0.5" }) : null
6430
+ ]
6431
+ }
6432
+ ),
6433
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "max-w-full truncate px-0.5", children: label }),
6434
+ badge ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: badge }) : null
6435
+ ] });
6436
+ }
5881
6437
  function TabBar({ items }) {
6438
+ const [more, setMore] = react.useState(false);
6439
+ const overflow = items.length > 5;
6440
+ const shown = overflow ? items.slice(0, 4) : items;
6441
+ const rest = overflow ? items.slice(4) : [];
6442
+ const restBadge = rest.find((it) => it.badge)?.badge;
5882
6443
  return /* @__PURE__ */ jsxRuntime.jsx(
5883
6444
  "nav",
5884
6445
  {
5885
6446
  "aria-label": "Pages",
5886
6447
  "data-oca-tabbar": "",
5887
6448
  className: "fixed inset-x-0 bottom-0 z-40 border-t border-border bg-background/90 pb-[env(safe-area-inset-bottom)] backdrop-blur-md md:hidden",
5888
- children: /* @__PURE__ */ jsxRuntime.jsx(
6449
+ children: /* @__PURE__ */ jsxRuntime.jsxs(
5889
6450
  "div",
5890
6451
  {
5891
6452
  className: "mx-auto grid h-14 max-w-[32rem] px-1.5",
5892
- style: { gridTemplateColumns: `repeat(${items.length}, minmax(0, 1fr))` },
5893
- children: items.map((it) => /* @__PURE__ */ jsxRuntime.jsxs(
5894
- Link6__default.default,
5895
- {
5896
- href: it.href,
5897
- "aria-current": it.active ? "page" : void 0,
5898
- className: cn(
5899
- "flex min-w-0 flex-col items-center justify-center gap-1 rounded-2xl text-[0.6875rem] leading-none outline-none transition-colors [-webkit-tap-highlight-color:transparent] focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring",
5900
- it.active ? "text-foreground" : "text-muted-foreground hover:text-foreground"
6453
+ style: { gridTemplateColumns: `repeat(${shown.length + (overflow ? 1 : 0)}, minmax(0, 1fr))` },
6454
+ children: [
6455
+ shown.map((it) => /* @__PURE__ */ jsxRuntime.jsx(
6456
+ Link6__default.default,
6457
+ {
6458
+ href: it.href,
6459
+ "aria-current": it.active ? "page" : void 0,
6460
+ className: cn(TAB, it.active ? "text-foreground" : "text-muted-foreground hover:text-foreground"),
6461
+ children: /* @__PURE__ */ jsxRuntime.jsx(TabFace, { icon: it.icon, label: it.label, badge: it.badge, active: it.active })
6462
+ },
6463
+ it.href
6464
+ )),
6465
+ overflow ? /* @__PURE__ */ jsxRuntime.jsxs(Sheet, { open: more, onOpenChange: setMore, children: [
6466
+ /* @__PURE__ */ jsxRuntime.jsx(
6467
+ SheetTrigger,
6468
+ {
6469
+ className: cn(TAB, rest.some((it) => it.active) ? "text-foreground" : "text-muted-foreground hover:text-foreground"),
6470
+ children: /* @__PURE__ */ jsxRuntime.jsx(TabFace, { icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Ellipsis, {}), label: "More", badge: restBadge ? true : void 0, active: rest.some((it) => it.active) })
6471
+ }
5901
6472
  ),
5902
- children: [
5903
- /* @__PURE__ */ jsxRuntime.jsxs(
5904
- "span",
6473
+ /* @__PURE__ */ jsxRuntime.jsxs(SheetContent, { side: "bottom", className: "pb-[calc(1.5rem+env(safe-area-inset-bottom))]", children: [
6474
+ /* @__PURE__ */ jsxRuntime.jsx(SheetTitle, { className: "px-1 text-[1.0625rem] font-medium", children: "More" }),
6475
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-4 grid grid-cols-3 gap-2", children: rest.map((it) => /* @__PURE__ */ jsxRuntime.jsxs(
6476
+ Link6__default.default,
5905
6477
  {
6478
+ href: it.href,
6479
+ onClick: () => setMore(false),
6480
+ "aria-current": it.active ? "page" : void 0,
5906
6481
  className: cn(
5907
- "relative flex h-7 w-12 items-center justify-center rounded-full transition-[background-color,box-shadow] duration-200",
5908
- "[&_svg]:size-[1.125rem] [&_svg]:shrink-0",
5909
- it.active ? "bg-card shadow-sm ring-1 ring-border [&_svg]:stroke-2" : "[&_svg]:stroke-[1.75]"
6482
+ "flex min-h-20 flex-col items-center justify-center gap-2 rounded-2xl border px-2 text-center text-[0.8125rem] transition-colors",
6483
+ "[&_svg]:size-5",
6484
+ it.active ? "border-foreground bg-card text-foreground" : "border-border text-muted-foreground hover:text-foreground"
5910
6485
  ),
5911
6486
  children: [
5912
- it.icon,
5913
- it.badge ? /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, className: "absolute right-2.5 top-0.5 size-2 rounded-full bg-oca-orange ring-2 ring-background" }) : null
6487
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "relative", children: [
6488
+ it.icon,
6489
+ it.badge ? /* @__PURE__ */ jsxRuntime.jsx(NavBadge, { badge: it.badge, className: typeof it.badge === "number" ? "-right-3 -top-2" : "-right-1 -top-0.5" }) : null
6490
+ ] }),
6491
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "max-w-full truncate", children: it.label }),
6492
+ it.badge ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: it.badge }) : null
5914
6493
  ]
5915
- }
5916
- ),
5917
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "max-w-full truncate px-0.5", children: it.label }),
5918
- it.badge ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: it.badge }) : null
5919
- ]
5920
- },
5921
- it.href
5922
- ))
6494
+ },
6495
+ it.href
6496
+ )) })
6497
+ ] })
6498
+ ] }) : null
6499
+ ]
5923
6500
  }
5924
6501
  )
5925
6502
  }
@@ -5927,7 +6504,11 @@ function TabBar({ items }) {
5927
6504
  }
5928
6505
  function tabsFor(groups) {
5929
6506
  const items = groups.flatMap((g) => g.items);
5930
- return items.length >= 2 && items.length <= 5 && items.every((it) => it.icon) ? items : null;
6507
+ return items.length >= 2 && items.every((it) => it.icon) ? items : null;
6508
+ }
6509
+ function sectionTabs(sections, current2) {
6510
+ if (!sections || !current2 || sections.length < 2 || !sections.every((sec) => sec.icon)) return null;
6511
+ return sections.map((sec) => ({ href: sec.href, label: sec.label, icon: sec.icon, active: sec.id === current2.id }));
5931
6512
  }
5932
6513
  var activeItem = (groups) => groups.flatMap((g) => g.items).find((it) => it.active);
5933
6514
  var warned = /* @__PURE__ */ new Set();
@@ -5942,7 +6523,10 @@ function warnDuplicateLabels(groups) {
5942
6523
  seen.add(it.label);
5943
6524
  }
5944
6525
  }
5945
- function AppShell({
6526
+ function AppShell(props) {
6527
+ return props.variant === "rail" ? /* @__PURE__ */ jsxRuntime.jsx(RailShell, { ...props }) : /* @__PURE__ */ jsxRuntime.jsx(SidebarShell, { ...props });
6528
+ }
6529
+ function SidebarShell({
5946
6530
  nav,
5947
6531
  sections,
5948
6532
  activeSection,
@@ -5960,7 +6544,8 @@ function AppShell({
5960
6544
  const current2 = sections && sections.length > 0 ? sections.find((sec) => sec.id === activeSection) ?? sections.find((sec) => activeItem(sec.groups)) ?? sections[0] : void 0;
5961
6545
  const groups = current2 ? [...current2.groups, ...persistent] : [...nav ?? [], ...persistent];
5962
6546
  warnDuplicateLabels(groups);
5963
- const tabs = current2 ? null : tabsFor(groups);
6547
+ const sectionTabsFor = sectionTabs(sections, current2);
6548
+ const tabs = current2 ? sectionTabsFor : tabsFor(groups);
5964
6549
  const page = activeItem(groups);
5965
6550
  const place = react.useMemo(
5966
6551
  () => ({
@@ -5988,8 +6573,8 @@ function AppShell({
5988
6573
  {
5989
6574
  className: cn(
5990
6575
  "inline-flex size-10 items-center justify-center rounded-full hover:bg-accent",
5991
- // The tab bar holds every page; the sheet is left for a footer.
5992
- tabs && !footer && "max-md:hidden"
6576
+ // The tab bar holds every page; the sheet is left for a footer. Section tabs leave the pages here.
6577
+ tabs && !sectionTabsFor && !footer && "max-md:hidden"
5993
6578
  ),
5994
6579
  "aria-label": "Open navigation",
5995
6580
  children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Menu, { className: "size-5" })
@@ -5997,8 +6582,8 @@ function AppShell({
5997
6582
  ),
5998
6583
  /* @__PURE__ */ jsxRuntime.jsxs(SheetContent, { side: "left", className: "flex flex-col gap-6 overflow-y-auto p-4 pt-16", children: [
5999
6584
  /* @__PURE__ */ jsxRuntime.jsx(SheetTitle, { className: "sr-only", children: "Navigation" }),
6000
- switcher,
6001
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: tabs ? "max-md:hidden" : void 0, children: /* @__PURE__ */ jsxRuntime.jsx(SideNav, { groups, onNavigate: () => setOpen(false) }) }),
6585
+ switcher ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: sectionTabsFor ? "max-md:hidden" : void 0, children: switcher }) : null,
6586
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: tabs && !sectionTabsFor ? "max-md:hidden" : void 0, children: /* @__PURE__ */ jsxRuntime.jsx(SideNav, { groups, onNavigate: () => setOpen(false) }) }),
6002
6587
  footer ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-auto flex flex-col gap-3", children: footer }) : null
6003
6588
  ] })
6004
6589
  ] }),
@@ -6012,7 +6597,7 @@ function AppShell({
6012
6597
  className: cn(
6013
6598
  "flex h-9 items-center gap-1.5 border-t border-border px-4 text-[0.875rem]",
6014
6599
  // The active tab already names the page.
6015
- tabs && !pageOverride && "max-md:hidden"
6600
+ tabs && !sectionTabsFor && !pageOverride && "max-md:hidden"
6016
6601
  ),
6017
6602
  children: [
6018
6603
  place.section ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
@@ -6045,6 +6630,64 @@ function AppShell({
6045
6630
  }
6046
6631
  ) });
6047
6632
  }
6633
+ function RailItem({ item }) {
6634
+ return /* @__PURE__ */ jsxRuntime.jsxs(Tooltip, { children: [
6635
+ /* @__PURE__ */ jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
6636
+ Link6__default.default,
6637
+ {
6638
+ href: item.href,
6639
+ "aria-current": item.active ? "page" : void 0,
6640
+ className: cn(
6641
+ "relative flex size-10 items-center justify-center rounded-xl outline-none transition-colors focus-visible:ring-2 focus-visible:ring-ring",
6642
+ "[&_svg]:size-5 [&_svg]:shrink-0",
6643
+ item.active ? "bg-card text-foreground shadow-sm ring-1 ring-border" : "text-muted-foreground hover:bg-accent hover:text-foreground"
6644
+ ),
6645
+ children: [
6646
+ item.icon,
6647
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "sr-only", children: [
6648
+ item.label,
6649
+ item.badge ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
6650
+ ", ",
6651
+ item.badge
6652
+ ] }) : null
6653
+ ] }),
6654
+ item.badge ? /* @__PURE__ */ jsxRuntime.jsx(NavBadge, { badge: item.badge, className: typeof item.badge === "number" ? "-right-1 -top-1" : "right-1 top-1" }) : null
6655
+ ]
6656
+ }
6657
+ ) }),
6658
+ /* @__PURE__ */ jsxRuntime.jsx(TooltipContent, { side: "right", children: item.label })
6659
+ ] });
6660
+ }
6661
+ function RailShell({ nav = [], persistent = [], page: pageOverride, header, account, banner, children, className }) {
6662
+ const main = nav.flatMap((g) => g.items);
6663
+ const foot = persistent.flatMap((g) => g.items);
6664
+ warnDuplicateLabels([...nav, ...persistent]);
6665
+ const tabs = tabsFor([{ items: [...main, ...foot] }]);
6666
+ const active = activeItem([...nav, ...persistent]);
6667
+ const place = react.useMemo(() => ({ page: pageOverride ?? active?.label }), [pageOverride, active?.label]);
6668
+ return /* @__PURE__ */ jsxRuntime.jsx(ShellContext.Provider, { value: place, children: /* @__PURE__ */ jsxRuntime.jsx(TooltipProvider, { delayDuration: 300, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex h-dvh flex-col overflow-hidden bg-background", className), children: [
6669
+ header,
6670
+ banner,
6671
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-h-0 flex-1", children: [
6672
+ /* @__PURE__ */ jsxRuntime.jsxs("nav", { "aria-label": "Pages", className: "hidden w-14 shrink-0 flex-col items-center gap-1 border-r border-border py-3 md:flex", children: [
6673
+ main.map((it) => /* @__PURE__ */ jsxRuntime.jsx(RailItem, { item: it }, it.href)),
6674
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-auto flex flex-col items-center gap-1", children: [
6675
+ foot.map((it) => /* @__PURE__ */ jsxRuntime.jsx(RailItem, { item: it }, it.href)),
6676
+ account
6677
+ ] })
6678
+ ] }),
6679
+ /* @__PURE__ */ jsxRuntime.jsx(
6680
+ "main",
6681
+ {
6682
+ id: "main-content",
6683
+ className: cn("flex min-h-0 min-w-0 flex-1 flex-col", tabs && "max-md:pb-[calc(3.5rem_+_env(safe-area-inset-bottom))]"),
6684
+ children
6685
+ }
6686
+ )
6687
+ ] }),
6688
+ tabs ? /* @__PURE__ */ jsxRuntime.jsx(TabBar, { items: tabs }) : null
6689
+ ] }) }) });
6690
+ }
6048
6691
  function AccountMenu({
6049
6692
  name,
6050
6693
  detail,
@@ -6985,13 +7628,16 @@ exports.CardGrid = CardGrid;
6985
7628
  exports.CardHeader = CardHeader;
6986
7629
  exports.CardNumeral = CardNumeral;
6987
7630
  exports.CardTitle = CardTitle;
7631
+ exports.ChartFrame = ChartFrame;
6988
7632
  exports.Checkbox = Checkbox;
6989
7633
  exports.Closing = Closing;
6990
7634
  exports.CodeBlock = CodeBlock;
6991
7635
  exports.CodeTabs = CodeTabs;
7636
+ exports.CommandDialog = CommandDialog;
6992
7637
  exports.ComparisonTable = ComparisonTable;
6993
7638
  exports.Container = Container;
6994
7639
  exports.CopyButton = CopyButton;
7640
+ exports.CountdownRing = CountdownRing;
6995
7641
  exports.Crowd = Crowd;
6996
7642
  exports.DOCS_HEADER_NAV = DOCS_HEADER_NAV;
6997
7643
  exports.DOCS_HREF = DOCS_HREF;
@@ -7042,6 +7688,7 @@ exports.FormSection = FormSection;
7042
7688
  exports.HalftoneCanvas = HalftoneCanvas;
7043
7689
  exports.HalftoneSphere = HalftoneSphere;
7044
7690
  exports.HashChip = HashChip;
7691
+ exports.HudCard = HudCard;
7045
7692
  exports.Input = Input;
7046
7693
  exports.InstallTabs = InstallTabs;
7047
7694
  exports.IsoCheck = IsoCheck;
@@ -7053,6 +7700,7 @@ exports.Lead = Lead;
7053
7700
  exports.LegalDocument = LegalDocument;
7054
7701
  exports.LinkCard = LinkCard;
7055
7702
  exports.LoadingBlock = LoadingBlock;
7703
+ exports.LockedPreview = LockedPreview;
7056
7704
  exports.Lockup = Lockup;
7057
7705
  exports.MARK_FACES = MARK_FACES;
7058
7706
  exports.Mark = Mark;
@@ -7072,7 +7720,9 @@ exports.PackageCard = PackageCard;
7072
7720
  exports.PageHeader = PageHeader;
7073
7721
  exports.PageHero = PageHero;
7074
7722
  exports.Pagination = Pagination;
7723
+ exports.Panel = Panel;
7075
7724
  exports.PhoneFrame = PhoneFrame;
7725
+ exports.PlanCard = PlanCard;
7076
7726
  exports.Popover = Popover;
7077
7727
  exports.PopoverAnchor = PopoverAnchor;
7078
7728
  exports.PopoverContent = PopoverContent;
@@ -7120,6 +7770,8 @@ exports.SiteFooter = SiteFooter;
7120
7770
  exports.SiteHeader = SiteHeader;
7121
7771
  exports.Skeleton = Skeleton;
7122
7772
  exports.SkipLink = SkipLink;
7773
+ exports.SourceNote = SourceNote;
7774
+ exports.Sparkline = Sparkline;
7123
7775
  exports.SpecCard = SpecCard;
7124
7776
  exports.Spinner = Spinner;
7125
7777
  exports.SplitBar = SplitBar;
@@ -7159,10 +7811,12 @@ exports.badgeVariants = badgeVariants;
7159
7811
  exports.blocksToDuration = blocksToDuration;
7160
7812
  exports.buttonVariants = buttonVariants;
7161
7813
  exports.cardVariants = cardVariants;
7814
+ exports.chartColor = chartColor;
7162
7815
  exports.cn = cn;
7163
7816
  exports.confirm = confirm;
7164
7817
  exports.createMdxComponents = createMdxComponents;
7165
7818
  exports.createStateBadge = createStateBadge;
7819
+ exports.darkPalette = darkPalette;
7166
7820
  exports.escapeHtml = escapeHtml;
7167
7821
  exports.explorerUrl = explorerUrl;
7168
7822
  exports.familyByGroup = familyByGroup;
@@ -7174,6 +7828,7 @@ exports.grammarOf = grammarOf;
7174
7828
  exports.highlight = highlight;
7175
7829
  exports.highlightToHtml = highlightToHtml;
7176
7830
  exports.languageName = languageName;
7831
+ exports.lightPalette = lightPalette;
7177
7832
  exports.linesToHtml = linesToHtml;
7178
7833
  exports.mdxComponents = mdxComponents;
7179
7834
  exports.monogramGround = monogramGround;