@orangecheck/ui 0.3.0 → 0.3.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/dist/index.d.mts CHANGED
@@ -1,4 +1,5 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { ReactNode } from 'react';
2
3
 
3
4
  type EcosystemSlug = 'home' | 'docs' | 'fleet' | 'me' | 'vault' | 'attest' | 'lock' | 'vote' | 'stamp' | 'agent' | 'pledge';
4
5
  interface EcosystemSwitcherProps {
@@ -7,4 +8,54 @@ interface EcosystemSwitcherProps {
7
8
  }
8
9
  declare function EcosystemSwitcher({ current, className, }: EcosystemSwitcherProps): react_jsx_runtime.JSX.Element;
9
10
 
10
- export { type EcosystemSlug, EcosystemSwitcher, type EcosystemSwitcherProps };
11
+ interface AppShellProps {
12
+ eyebrow?: ReactNode;
13
+ title?: ReactNode;
14
+ description?: ReactNode;
15
+ headerActions?: ReactNode;
16
+ children: ReactNode;
17
+ className?: string;
18
+ }
19
+ declare function AppShell({ eyebrow, title, description, headerActions, children, className, }: AppShellProps): react_jsx_runtime.JSX.Element;
20
+
21
+ interface SectionHeaderProps {
22
+ label: string;
23
+ meta?: ReactNode;
24
+ tone?: 'primary' | 'muted' | 'warning' | 'success' | 'destructive';
25
+ className?: string;
26
+ }
27
+ declare function SectionHeader({ label, meta, tone, className, }: SectionHeaderProps): react_jsx_runtime.JSX.Element;
28
+
29
+ interface EmptyStateCta {
30
+ label: string;
31
+ href: string;
32
+ external?: boolean;
33
+ }
34
+ interface EmptyStateProps {
35
+ label: string;
36
+ children: ReactNode;
37
+ cta?: EmptyStateCta;
38
+ secondary?: EmptyStateCta;
39
+ tone?: 'info' | 'warning' | 'muted';
40
+ className?: string;
41
+ }
42
+ declare function EmptyState({ label, children, cta, secondary, tone, className, }: EmptyStateProps): react_jsx_runtime.JSX.Element;
43
+
44
+ interface StatItem {
45
+ label: string;
46
+ value: string;
47
+ sub?: string;
48
+ accent?: boolean;
49
+ tone?: 'default' | 'primary' | 'success' | 'warning' | 'destructive' | 'muted';
50
+ }
51
+ interface StatGridProps {
52
+ items: StatItem[];
53
+ columns?: 1 | 2 | 3 | 4;
54
+ className?: string;
55
+ }
56
+ declare function StatGrid({ items, columns, className }: StatGridProps): react_jsx_runtime.JSX.Element;
57
+ declare function StatTile({ children, ...item }: StatItem & {
58
+ children?: ReactNode;
59
+ }): react_jsx_runtime.JSX.Element;
60
+
61
+ export { AppShell, type AppShellProps, type EcosystemSlug, EcosystemSwitcher, type EcosystemSwitcherProps, EmptyState, type EmptyStateCta, type EmptyStateProps, SectionHeader, type SectionHeaderProps, StatGrid, type StatGridProps, type StatItem, StatTile };
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { ReactNode } from 'react';
2
3
 
3
4
  type EcosystemSlug = 'home' | 'docs' | 'fleet' | 'me' | 'vault' | 'attest' | 'lock' | 'vote' | 'stamp' | 'agent' | 'pledge';
4
5
  interface EcosystemSwitcherProps {
@@ -7,4 +8,54 @@ interface EcosystemSwitcherProps {
7
8
  }
8
9
  declare function EcosystemSwitcher({ current, className, }: EcosystemSwitcherProps): react_jsx_runtime.JSX.Element;
9
10
 
10
- export { type EcosystemSlug, EcosystemSwitcher, type EcosystemSwitcherProps };
11
+ interface AppShellProps {
12
+ eyebrow?: ReactNode;
13
+ title?: ReactNode;
14
+ description?: ReactNode;
15
+ headerActions?: ReactNode;
16
+ children: ReactNode;
17
+ className?: string;
18
+ }
19
+ declare function AppShell({ eyebrow, title, description, headerActions, children, className, }: AppShellProps): react_jsx_runtime.JSX.Element;
20
+
21
+ interface SectionHeaderProps {
22
+ label: string;
23
+ meta?: ReactNode;
24
+ tone?: 'primary' | 'muted' | 'warning' | 'success' | 'destructive';
25
+ className?: string;
26
+ }
27
+ declare function SectionHeader({ label, meta, tone, className, }: SectionHeaderProps): react_jsx_runtime.JSX.Element;
28
+
29
+ interface EmptyStateCta {
30
+ label: string;
31
+ href: string;
32
+ external?: boolean;
33
+ }
34
+ interface EmptyStateProps {
35
+ label: string;
36
+ children: ReactNode;
37
+ cta?: EmptyStateCta;
38
+ secondary?: EmptyStateCta;
39
+ tone?: 'info' | 'warning' | 'muted';
40
+ className?: string;
41
+ }
42
+ declare function EmptyState({ label, children, cta, secondary, tone, className, }: EmptyStateProps): react_jsx_runtime.JSX.Element;
43
+
44
+ interface StatItem {
45
+ label: string;
46
+ value: string;
47
+ sub?: string;
48
+ accent?: boolean;
49
+ tone?: 'default' | 'primary' | 'success' | 'warning' | 'destructive' | 'muted';
50
+ }
51
+ interface StatGridProps {
52
+ items: StatItem[];
53
+ columns?: 1 | 2 | 3 | 4;
54
+ className?: string;
55
+ }
56
+ declare function StatGrid({ items, columns, className }: StatGridProps): react_jsx_runtime.JSX.Element;
57
+ declare function StatTile({ children, ...item }: StatItem & {
58
+ children?: ReactNode;
59
+ }): react_jsx_runtime.JSX.Element;
60
+
61
+ export { AppShell, type AppShellProps, type EcosystemSlug, EcosystemSwitcher, type EcosystemSwitcherProps, EmptyState, type EmptyStateCta, type EmptyStateProps, SectionHeader, type SectionHeaderProps, StatGrid, type StatGridProps, type StatItem, StatTile };
package/dist/index.js CHANGED
@@ -178,7 +178,134 @@ function EcosystemSwitcher({
178
178
  )
179
179
  ] });
180
180
  }
181
+ function AppShell({
182
+ eyebrow,
183
+ title,
184
+ description,
185
+ headerActions,
186
+ children,
187
+ className
188
+ }) {
189
+ const hasHeader = Boolean(title);
190
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "container " + (className ?? ""), children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex min-h-[calc(100vh-3rem)] flex-col", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex min-w-0 flex-1 flex-col", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pt-6 md:pt-8", children: [
191
+ hasHeader && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between", children: [
192
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "max-w-3xl", children: [
193
+ eyebrow && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "label-mono text-primary mb-3", children: eyebrow }),
194
+ /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "font-display text-2xl font-bold tracking-tight sm:text-3xl", children: title }),
195
+ description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-muted-foreground mt-3 max-w-[64ch] text-sm leading-relaxed", children: description })
196
+ ] }),
197
+ headerActions && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex shrink-0 items-center gap-2", children: headerActions })
198
+ ] }),
199
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: hasHeader ? "mt-8 pb-12" : "pb-12", children })
200
+ ] }) }) }) });
201
+ }
202
+ var TONE_CLASS = {
203
+ primary: "text-primary",
204
+ muted: "text-muted-foreground",
205
+ warning: "text-warning",
206
+ success: "text-success",
207
+ destructive: "text-destructive"
208
+ };
209
+ function SectionHeader({
210
+ label,
211
+ meta,
212
+ tone = "primary",
213
+ className = ""
214
+ }) {
215
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `mb-3 flex items-baseline justify-between gap-2 ${className}`, children: [
216
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-1.5", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `label-mono ${TONE_CLASS[tone]}`, children: [
217
+ "\xA7 ",
218
+ label
219
+ ] }) }),
220
+ meta && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground/70 font-mono text-[10px] tracking-widest uppercase", children: meta })
221
+ ] });
222
+ }
223
+ var TONE_CLASS2 = {
224
+ info: "border-primary/30 bg-primary/5",
225
+ warning: "border-warning/40 bg-warning/5",
226
+ muted: "border-border bg-muted/20"
227
+ };
228
+ var LABEL_TONE_CLASS = {
229
+ info: "text-primary",
230
+ warning: "text-warning",
231
+ muted: "text-muted-foreground"
232
+ };
233
+ function EmptyState({
234
+ label,
235
+ children,
236
+ cta,
237
+ secondary,
238
+ tone = "info",
239
+ className = ""
240
+ }) {
241
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `border p-5 md:p-6 ${TONE_CLASS2[tone]} ${className}`, children: [
242
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `label-mono mb-2 ${LABEL_TONE_CLASS[tone]}`, children: [
243
+ "\xA7 ",
244
+ label
245
+ ] }),
246
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-foreground/85 max-w-2xl text-sm leading-relaxed", children }),
247
+ (cta || secondary) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-4 flex flex-wrap gap-3", children: [
248
+ cta && /* @__PURE__ */ jsxRuntime.jsx(CtaLink, { ...cta, variant: "primary" }),
249
+ secondary && /* @__PURE__ */ jsxRuntime.jsx(CtaLink, { ...secondary, variant: "secondary" })
250
+ ] })
251
+ ] });
252
+ }
253
+ function CtaLink({
254
+ label,
255
+ href,
256
+ external,
257
+ variant
258
+ }) {
259
+ const cls = variant === "primary" ? "bg-primary text-primary-foreground hover:bg-primary/90 inline-flex h-9 items-center justify-center rounded-md px-4 font-mono text-[11px] font-semibold tracking-widest uppercase" : "text-muted-foreground hover:text-foreground border-input hover:bg-accent inline-flex h-9 items-center justify-center rounded-md border px-4 font-mono text-[11px] tracking-widest uppercase";
260
+ const text = external ? `${label} \u2197` : label;
261
+ if (external) {
262
+ return /* @__PURE__ */ jsxRuntime.jsx("a", { href, target: "_blank", rel: "noreferrer", className: cls, children: text });
263
+ }
264
+ return /* @__PURE__ */ jsxRuntime.jsx(Link__default.default, { href, className: cls, children: text });
265
+ }
266
+ var TONE_CLASS3 = {
267
+ default: "",
268
+ primary: "text-primary",
269
+ success: "text-success",
270
+ warning: "text-warning",
271
+ destructive: "text-destructive",
272
+ muted: "text-muted-foreground"
273
+ };
274
+ var COL_CLASS = {
275
+ 1: "",
276
+ 2: "md:grid-cols-2",
277
+ 3: "md:grid-cols-3",
278
+ 4: "md:grid-cols-2 lg:grid-cols-4"
279
+ };
280
+ function StatGrid({ items, columns = 3, className = "" }) {
281
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: `bg-border grid gap-px border ${COL_CLASS[columns]} ${className}`, children: items.map((it, i) => /* @__PURE__ */ jsxRuntime.jsx(Tile, { item: it }, `${it.label}-${i}`)) });
282
+ }
283
+ function Tile({ item }) {
284
+ const tone = item.tone ?? (item.accent ? "primary" : "default");
285
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-background p-5", children: [
286
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-muted-foreground/80 font-mono text-[10px] tracking-widest uppercase", children: item.label }),
287
+ /* @__PURE__ */ jsxRuntime.jsx(
288
+ "div",
289
+ {
290
+ className: `font-display mt-1 text-2xl font-bold tabular-nums tracking-tight ${TONE_CLASS3[tone]}`,
291
+ children: item.value
292
+ }
293
+ ),
294
+ item.sub && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-muted-foreground/70 mt-1 font-mono text-[10px] tracking-widest uppercase", children: item.sub })
295
+ ] });
296
+ }
297
+ function StatTile({ children, ...item }) {
298
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
299
+ /* @__PURE__ */ jsxRuntime.jsx(Tile, { item }),
300
+ children
301
+ ] });
302
+ }
181
303
 
304
+ exports.AppShell = AppShell;
182
305
  exports.EcosystemSwitcher = EcosystemSwitcher;
306
+ exports.EmptyState = EmptyState;
307
+ exports.SectionHeader = SectionHeader;
308
+ exports.StatGrid = StatGrid;
309
+ exports.StatTile = StatTile;
183
310
  //# sourceMappingURL=index.js.map
184
311
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/ecosystem-switcher.tsx"],"names":["useState","useRef","useEffect","jsxs","jsx","Boxes","ChevronDown","Link","Check"],"mappings":"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","file":"index.js","sourcesContent":["import { Boxes, Check, ChevronDown } from 'lucide-react';\nimport Link from 'next/link';\nimport { useEffect, useRef, useState } from 'react';\n\n/**\n * EcosystemSwitcher — cross-product dropdown for jumping between every\n * site in the OrangeCheck family. Drop one into every site's LayoutHeader\n * and mark the active site via the `current` prop.\n *\n * <EcosystemSwitcher current=\"lock\" />\n *\n * The component is dependency-self-contained: no Radix, no Headless UI,\n * just outside-click + Escape handling so it works identically in every\n * site without forcing a peer-dep upgrade. Every link stays in-tab — the\n * family is one app from the user's POV.\n */\n\nexport type EcosystemSlug =\n | 'home'\n | 'docs'\n | 'fleet'\n | 'me'\n | 'vault'\n | 'attest'\n | 'lock'\n | 'vote'\n | 'stamp'\n | 'agent'\n | 'pledge';\n\ninterface SwitcherEntry {\n slug: EcosystemSlug;\n href: string;\n label: string;\n sub: string;\n docsHref: string;\n}\n\nconst ENTRIES: SwitcherEntry[] = [\n {\n slug: 'home',\n href: 'https://ochk.io',\n label: 'orangecheck',\n sub: 'umbrella',\n docsHref: 'https://docs.ochk.io',\n },\n {\n slug: 'docs',\n href: 'https://docs.ochk.io',\n label: 'oc·docs',\n sub: 'unified docs',\n docsHref: 'https://docs.ochk.io',\n },\n {\n slug: 'fleet',\n href: 'https://fleet.ochk.io',\n label: 'oc·fleet',\n sub: 'managed — agent fleet',\n docsHref: 'https://docs.ochk.io/fleet',\n },\n {\n slug: 'me',\n href: 'https://me.ochk.io',\n label: 'oc·me',\n sub: 'earn — consumer identity',\n docsHref: 'https://docs.ochk.io/me',\n },\n {\n slug: 'vault',\n href: 'https://vault.ochk.io',\n label: 'oc·vault',\n sub: 'keep — encrypted secrets',\n docsHref: 'https://docs.ochk.io/vault',\n },\n {\n slug: 'attest',\n href: 'https://attest.ochk.io',\n label: 'oc·attest',\n sub: 'am — sybil resistance',\n docsHref: 'https://docs.ochk.io/attest',\n },\n {\n slug: 'lock',\n href: 'https://lock.ochk.io',\n label: 'oc·lock',\n sub: 'whisper — encryption',\n docsHref: 'https://docs.ochk.io/lock',\n },\n {\n slug: 'vote',\n href: 'https://vote.ochk.io',\n label: 'oc·vote',\n sub: 'decide — polls',\n docsHref: 'https://docs.ochk.io/vote',\n },\n {\n slug: 'stamp',\n href: 'https://stamp.ochk.io',\n label: 'oc·stamp',\n sub: 'declare — block-anchored',\n docsHref: 'https://docs.ochk.io/stamp',\n },\n {\n slug: 'agent',\n href: 'https://agent.ochk.io',\n label: 'oc·agent',\n sub: 'delegate — scoped auth',\n docsHref: 'https://docs.ochk.io/agent',\n },\n {\n slug: 'pledge',\n href: 'https://pledge.ochk.io',\n label: 'oc·pledge',\n sub: 'swear — bonded commitment',\n docsHref: 'https://docs.ochk.io/pledge',\n },\n];\n\nexport interface EcosystemSwitcherProps {\n current: EcosystemSlug;\n className?: string;\n}\n\nexport function EcosystemSwitcher({\n current,\n className,\n}: EcosystemSwitcherProps) {\n const [open, setOpen] = useState(false);\n const containerRef = useRef<HTMLDivElement | null>(null);\n\n // Outside-click + Escape close.\n useEffect(() => {\n if (!open) return;\n function onDoc(e: MouseEvent) {\n if (!containerRef.current) return;\n if (!containerRef.current.contains(e.target as Node)) setOpen(false);\n }\n function onKey(e: KeyboardEvent) {\n if (e.key === 'Escape') setOpen(false);\n }\n document.addEventListener('mousedown', onDoc);\n document.addEventListener('keydown', onKey);\n return () => {\n document.removeEventListener('mousedown', onDoc);\n document.removeEventListener('keydown', onKey);\n };\n }, [open]);\n\n return (\n <div ref={containerRef} className={'relative ' + (className ?? '')}>\n <button\n type=\"button\"\n aria-haspopup=\"menu\"\n aria-expanded={open}\n aria-label=\"Switch OrangeCheck product\"\n title=\"Switch product\"\n onClick={() => setOpen((v) => !v)}\n className={\n 'inline-flex items-center gap-1 px-2 py-1 transition-colors ' +\n (open\n ? 'text-foreground'\n : 'text-muted-foreground hover:text-foreground')\n }\n >\n <Boxes className=\"h-4 w-4\" />\n <ChevronDown\n className={\n 'h-3.5 w-3.5 transition-transform ' + (open ? 'rotate-180' : '')\n }\n />\n </button>\n\n {open && (\n <div\n role=\"menu\"\n aria-label=\"Switch OrangeCheck product\"\n className=\"bg-background absolute right-0 top-full z-[60] mt-2 w-72 border shadow-lg\"\n >\n <div className=\"label-mono text-primary border-b px-4 py-2\">\n § the family\n </div>\n <ul className=\"py-1\">\n {ENTRIES.map((e) => {\n const isActive = e.slug === current;\n return (\n <li key={e.slug}>\n <Link\n href={e.href}\n onClick={() => setOpen(false)}\n aria-current={isActive ? 'page' : undefined}\n className={\n 'group flex items-baseline gap-3 px-4 py-2 transition-colors ' +\n (isActive\n ? 'bg-primary/5'\n : 'hover:bg-muted')\n }\n >\n <span\n className={\n 'font-display flex-1 text-[12px] font-semibold tracking-tight ' +\n (isActive\n ? 'text-primary'\n : 'text-foreground group-hover:text-primary transition-colors')\n }\n >\n {e.label}\n </span>\n <span className=\"text-muted-foreground font-mono text-[10px] tracking-wider uppercase\">\n {e.sub}\n </span>\n {isActive && (\n <Check className=\"text-primary h-3 w-3\" />\n )}\n </Link>\n </li>\n );\n })}\n </ul>\n <div className=\"border-t px-4 py-2 font-mono text-[10px] tracking-widest uppercase\">\n <Link\n href=\"https://docs.ochk.io\"\n onClick={() => setOpen(false)}\n className=\"text-muted-foreground hover:text-foreground inline-block transition-colors\"\n >\n docs.ochk.io →\n </Link>\n </div>\n </div>\n )}\n </div>\n );\n}\n"]}
1
+ {"version":3,"sources":["../src/ecosystem-switcher.tsx","../src/app-shell.tsx","../src/section-header.tsx","../src/empty-state.tsx","../src/stat-grid.tsx"],"names":["useState","useRef","useEffect","jsxs","jsx","Boxes","ChevronDown","Link","Check","TONE_CLASS"],"mappings":"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","file":"index.js","sourcesContent":["import { Boxes, Check, ChevronDown } from 'lucide-react';\nimport Link from 'next/link';\nimport { useEffect, useRef, useState } from 'react';\n\n/**\n * EcosystemSwitcher — cross-product dropdown for jumping between every\n * site in the OrangeCheck family. Drop one into every site's LayoutHeader\n * and mark the active site via the `current` prop.\n *\n * <EcosystemSwitcher current=\"lock\" />\n *\n * The component is dependency-self-contained: no Radix, no Headless UI,\n * just outside-click + Escape handling so it works identically in every\n * site without forcing a peer-dep upgrade. Every link stays in-tab — the\n * family is one app from the user's POV.\n */\n\nexport type EcosystemSlug =\n | 'home'\n | 'docs'\n | 'fleet'\n | 'me'\n | 'vault'\n | 'attest'\n | 'lock'\n | 'vote'\n | 'stamp'\n | 'agent'\n | 'pledge';\n\ninterface SwitcherEntry {\n slug: EcosystemSlug;\n href: string;\n label: string;\n sub: string;\n docsHref: string;\n}\n\nconst ENTRIES: SwitcherEntry[] = [\n {\n slug: 'home',\n href: 'https://ochk.io',\n label: 'orangecheck',\n sub: 'umbrella',\n docsHref: 'https://docs.ochk.io',\n },\n {\n slug: 'docs',\n href: 'https://docs.ochk.io',\n label: 'oc·docs',\n sub: 'unified docs',\n docsHref: 'https://docs.ochk.io',\n },\n {\n slug: 'fleet',\n href: 'https://fleet.ochk.io',\n label: 'oc·fleet',\n sub: 'managed — agent fleet',\n docsHref: 'https://docs.ochk.io/fleet',\n },\n {\n slug: 'me',\n href: 'https://me.ochk.io',\n label: 'oc·me',\n sub: 'earn — consumer identity',\n docsHref: 'https://docs.ochk.io/me',\n },\n {\n slug: 'vault',\n href: 'https://vault.ochk.io',\n label: 'oc·vault',\n sub: 'keep — encrypted secrets',\n docsHref: 'https://docs.ochk.io/vault',\n },\n {\n slug: 'attest',\n href: 'https://attest.ochk.io',\n label: 'oc·attest',\n sub: 'am — sybil resistance',\n docsHref: 'https://docs.ochk.io/attest',\n },\n {\n slug: 'lock',\n href: 'https://lock.ochk.io',\n label: 'oc·lock',\n sub: 'whisper — encryption',\n docsHref: 'https://docs.ochk.io/lock',\n },\n {\n slug: 'vote',\n href: 'https://vote.ochk.io',\n label: 'oc·vote',\n sub: 'decide — polls',\n docsHref: 'https://docs.ochk.io/vote',\n },\n {\n slug: 'stamp',\n href: 'https://stamp.ochk.io',\n label: 'oc·stamp',\n sub: 'declare — block-anchored',\n docsHref: 'https://docs.ochk.io/stamp',\n },\n {\n slug: 'agent',\n href: 'https://agent.ochk.io',\n label: 'oc·agent',\n sub: 'delegate — scoped auth',\n docsHref: 'https://docs.ochk.io/agent',\n },\n {\n slug: 'pledge',\n href: 'https://pledge.ochk.io',\n label: 'oc·pledge',\n sub: 'swear — bonded commitment',\n docsHref: 'https://docs.ochk.io/pledge',\n },\n];\n\nexport interface EcosystemSwitcherProps {\n current: EcosystemSlug;\n className?: string;\n}\n\nexport function EcosystemSwitcher({\n current,\n className,\n}: EcosystemSwitcherProps) {\n const [open, setOpen] = useState(false);\n const containerRef = useRef<HTMLDivElement | null>(null);\n\n // Outside-click + Escape close.\n useEffect(() => {\n if (!open) return;\n function onDoc(e: MouseEvent) {\n if (!containerRef.current) return;\n if (!containerRef.current.contains(e.target as Node)) setOpen(false);\n }\n function onKey(e: KeyboardEvent) {\n if (e.key === 'Escape') setOpen(false);\n }\n document.addEventListener('mousedown', onDoc);\n document.addEventListener('keydown', onKey);\n return () => {\n document.removeEventListener('mousedown', onDoc);\n document.removeEventListener('keydown', onKey);\n };\n }, [open]);\n\n return (\n <div ref={containerRef} className={'relative ' + (className ?? '')}>\n <button\n type=\"button\"\n aria-haspopup=\"menu\"\n aria-expanded={open}\n aria-label=\"Switch OrangeCheck product\"\n title=\"Switch product\"\n onClick={() => setOpen((v) => !v)}\n className={\n 'inline-flex items-center gap-1 px-2 py-1 transition-colors ' +\n (open\n ? 'text-foreground'\n : 'text-muted-foreground hover:text-foreground')\n }\n >\n <Boxes className=\"h-4 w-4\" />\n <ChevronDown\n className={\n 'h-3.5 w-3.5 transition-transform ' + (open ? 'rotate-180' : '')\n }\n />\n </button>\n\n {open && (\n <div\n role=\"menu\"\n aria-label=\"Switch OrangeCheck product\"\n className=\"bg-background absolute right-0 top-full z-[60] mt-2 w-72 border shadow-lg\"\n >\n <div className=\"label-mono text-primary border-b px-4 py-2\">\n § the family\n </div>\n <ul className=\"py-1\">\n {ENTRIES.map((e) => {\n const isActive = e.slug === current;\n return (\n <li key={e.slug}>\n <Link\n href={e.href}\n onClick={() => setOpen(false)}\n aria-current={isActive ? 'page' : undefined}\n className={\n 'group flex items-baseline gap-3 px-4 py-2 transition-colors ' +\n (isActive\n ? 'bg-primary/5'\n : 'hover:bg-muted')\n }\n >\n <span\n className={\n 'font-display flex-1 text-[12px] font-semibold tracking-tight ' +\n (isActive\n ? 'text-primary'\n : 'text-foreground group-hover:text-primary transition-colors')\n }\n >\n {e.label}\n </span>\n <span className=\"text-muted-foreground font-mono text-[10px] tracking-wider uppercase\">\n {e.sub}\n </span>\n {isActive && (\n <Check className=\"text-primary h-3 w-3\" />\n )}\n </Link>\n </li>\n );\n })}\n </ul>\n <div className=\"border-t px-4 py-2 font-mono text-[10px] tracking-widest uppercase\">\n <Link\n href=\"https://docs.ochk.io\"\n onClick={() => setOpen(false)}\n className=\"text-muted-foreground hover:text-foreground inline-block transition-colors\"\n >\n docs.ochk.io →\n </Link>\n </div>\n </div>\n )}\n </div>\n );\n}\n","import type { ReactNode } from 'react';\n\n/**\n * AppShell — shared page chrome for every authenticated dashboard surface\n * across the OC family (vault, me, fleet, future). Lifted from oc-me-web's\n * `MeShell` and oc-vault-web's `VaultShell` — same eyebrow / title /\n * description / actions header band, no sidebar (sidebars are app-specific\n * and stay in the consuming app).\n *\n * Usage:\n * <AppShell eyebrow=\"§ vault\" title=\"your vault.\" description=\"…\">\n * ...\n * </AppShell>\n *\n * The component is stateless and dependency-free. Tailwind classes assume\n * the consuming site loads the family `globals.css` (which defines\n * `.container`, `.label-mono`, the dark-by-default palette, etc.).\n */\n\nexport interface AppShellProps {\n eyebrow?: ReactNode;\n title?: ReactNode;\n description?: ReactNode;\n /** Right-aligned action node rendered next to the title (e.g. CTA buttons). */\n headerActions?: ReactNode;\n children: ReactNode;\n className?: string;\n}\n\nexport function AppShell({\n eyebrow,\n title,\n description,\n headerActions,\n children,\n className,\n}: AppShellProps) {\n const hasHeader = Boolean(title);\n return (\n <div className={'container ' + (className ?? '')}>\n <div className=\"flex min-h-[calc(100vh-3rem)] flex-col\">\n <div className=\"flex min-w-0 flex-1 flex-col\">\n <div className=\"pt-6 md:pt-8\">\n {hasHeader && (\n <div className=\"flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between\">\n <div className=\"max-w-3xl\">\n {eyebrow && (\n <div className=\"label-mono text-primary mb-3\">\n {eyebrow}\n </div>\n )}\n <h1 className=\"font-display text-2xl font-bold tracking-tight sm:text-3xl\">\n {title}\n </h1>\n {description && (\n <p className=\"text-muted-foreground mt-3 max-w-[64ch] text-sm leading-relaxed\">\n {description}\n </p>\n )}\n </div>\n {headerActions && (\n <div className=\"flex shrink-0 items-center gap-2\">\n {headerActions}\n </div>\n )}\n </div>\n )}\n <div className={hasHeader ? 'mt-8 pb-12' : 'pb-12'}>{children}</div>\n </div>\n </div>\n </div>\n </div>\n );\n}\n","import type { ReactNode } from 'react';\n\nexport interface SectionHeaderProps {\n /** Plain section name — rendered after a \"§ \" glyph in label-mono. */\n label: string;\n /** Optional right-side string (count, \"most recent first\"). */\n meta?: ReactNode;\n tone?: 'primary' | 'muted' | 'warning' | 'success' | 'destructive';\n className?: string;\n}\n\nconst TONE_CLASS = {\n primary: 'text-primary',\n muted: 'text-muted-foreground',\n warning: 'text-warning',\n success: 'text-success',\n destructive: 'text-destructive',\n} as const;\n\n/**\n * SectionHeader — the canonical \"§ x\" section header used across every\n * /me, /vault, and /fleet dashboard surface. Lifted from oc-me-web's\n * `me/ui/SectionHeader` so the visual contract stays single-source.\n *\n * Pattern is `label-mono text-primary mb-3` with a \"§ \" glyph followed by\n * the label, plus an optional muted/uppercase right-side meta string.\n */\nexport function SectionHeader({\n label,\n meta,\n tone = 'primary',\n className = '',\n}: SectionHeaderProps) {\n return (\n <div className={`mb-3 flex items-baseline justify-between gap-2 ${className}`}>\n <div className=\"flex items-center gap-1.5\">\n <div className={`label-mono ${TONE_CLASS[tone]}`}>§ {label}</div>\n </div>\n {meta && (\n <span className=\"text-muted-foreground/70 font-mono text-[10px] tracking-widest uppercase\">\n {meta}\n </span>\n )}\n </div>\n );\n}\n","import Link from 'next/link';\nimport type { ReactNode } from 'react';\n\nexport interface EmptyStateCta {\n label: string;\n href: string;\n /** External links open in a new tab and get a ↗ glyph. */\n external?: boolean;\n}\n\nexport interface EmptyStateProps {\n /** Short heading — one mono-uppercased label like \"no entries yet\". */\n label: string;\n /** Body — short prose explaining what would appear here and how. */\n children: ReactNode;\n cta?: EmptyStateCta;\n secondary?: EmptyStateCta;\n tone?: 'info' | 'warning' | 'muted';\n className?: string;\n}\n\nconst TONE_CLASS = {\n info: 'border-primary/30 bg-primary/5',\n warning: 'border-warning/40 bg-warning/5',\n muted: 'border-border bg-muted/20',\n} as const;\n\nconst LABEL_TONE_CLASS = {\n info: 'text-primary',\n warning: 'text-warning',\n muted: 'text-muted-foreground',\n} as const;\n\n/**\n * EmptyState — the canonical empty-state card used across every /me,\n * /vault, and /fleet dashboard. Empty states should *teach*: explain what\n * would appear, and how to make it appear. Lifted from oc-me-web's\n * `me/ui/EmptyState`.\n */\nexport function EmptyState({\n label,\n children,\n cta,\n secondary,\n tone = 'info',\n className = '',\n}: EmptyStateProps) {\n return (\n <div className={`border p-5 md:p-6 ${TONE_CLASS[tone]} ${className}`}>\n <div className={`label-mono mb-2 ${LABEL_TONE_CLASS[tone]}`}>§ {label}</div>\n <div className=\"text-foreground/85 max-w-2xl text-sm leading-relaxed\">{children}</div>\n {(cta || secondary) && (\n <div className=\"mt-4 flex flex-wrap gap-3\">\n {cta && <CtaLink {...cta} variant=\"primary\" />}\n {secondary && <CtaLink {...secondary} variant=\"secondary\" />}\n </div>\n )}\n </div>\n );\n}\n\nfunction CtaLink({\n label,\n href,\n external,\n variant,\n}: EmptyStateCta & { variant: 'primary' | 'secondary' }) {\n const cls =\n variant === 'primary'\n ? 'bg-primary text-primary-foreground hover:bg-primary/90 inline-flex h-9 items-center justify-center rounded-md px-4 font-mono text-[11px] font-semibold tracking-widest uppercase'\n : 'text-muted-foreground hover:text-foreground border-input hover:bg-accent inline-flex h-9 items-center justify-center rounded-md border px-4 font-mono text-[11px] tracking-widest uppercase';\n const text = external ? `${label} ↗` : label;\n if (external) {\n return (\n <a href={href} target=\"_blank\" rel=\"noreferrer\" className={cls}>\n {text}\n </a>\n );\n }\n return (\n <Link href={href} className={cls}>\n {text}\n </Link>\n );\n}\n","import type { ReactNode } from 'react';\n\nexport interface StatItem {\n /** Short uppercased label rendered in mono. */\n label: string;\n /** Primary value · already formatted as a string. */\n value: string;\n /** Optional secondary line · USD conversion, \"last 30 days\", etc. */\n sub?: string;\n /** When true, value is rendered in primary tone (use for headline metric). */\n accent?: boolean;\n /** Optional tone for the value (overrides accent). */\n tone?: 'default' | 'primary' | 'success' | 'warning' | 'destructive' | 'muted';\n}\n\nexport interface StatGridProps {\n items: StatItem[];\n columns?: 1 | 2 | 3 | 4;\n className?: string;\n}\n\nconst TONE_CLASS = {\n default: '',\n primary: 'text-primary',\n success: 'text-success',\n warning: 'text-warning',\n destructive: 'text-destructive',\n muted: 'text-muted-foreground',\n} as const;\n\nconst COL_CLASS = {\n 1: '',\n 2: 'md:grid-cols-2',\n 3: 'md:grid-cols-3',\n 4: 'md:grid-cols-2 lg:grid-cols-4',\n} as const;\n\n/**\n * StatGrid — the canonical stats row used across family dashboards.\n * Lifted from oc-me-web's `me/ui/StatGrid`. Grid of equal-width tiles\n * separated by 1px borders. Always pre-format the value string —\n * the component does no number formatting.\n */\nexport function StatGrid({ items, columns = 3, className = '' }: StatGridProps) {\n return (\n <div className={`bg-border grid gap-px border ${COL_CLASS[columns]} ${className}`}>\n {items.map((it, i) => (\n <Tile key={`${it.label}-${i}`} item={it} />\n ))}\n </div>\n );\n}\n\nfunction Tile({ item }: { item: StatItem }) {\n const tone = item.tone ?? (item.accent ? 'primary' : 'default');\n return (\n <div className=\"bg-background p-5\">\n <div className=\"text-muted-foreground/80 font-mono text-[10px] tracking-widest uppercase\">\n {item.label}\n </div>\n <div\n className={`font-display mt-1 text-2xl font-bold tabular-nums tracking-tight ${TONE_CLASS[tone]}`}\n >\n {item.value}\n </div>\n {item.sub && (\n <div className=\"text-muted-foreground/70 mt-1 font-mono text-[10px] tracking-widest uppercase\">\n {item.sub}\n </div>\n )}\n </div>\n );\n}\n\nexport function StatTile({ children, ...item }: StatItem & { children?: ReactNode }) {\n return (\n <div>\n <Tile item={item} />\n {children}\n </div>\n );\n}\n"]}
package/dist/index.mjs CHANGED
@@ -172,7 +172,129 @@ function EcosystemSwitcher({
172
172
  )
173
173
  ] });
174
174
  }
175
+ function AppShell({
176
+ eyebrow,
177
+ title,
178
+ description,
179
+ headerActions,
180
+ children,
181
+ className
182
+ }) {
183
+ const hasHeader = Boolean(title);
184
+ return /* @__PURE__ */ jsx("div", { className: "container " + (className ?? ""), children: /* @__PURE__ */ jsx("div", { className: "flex min-h-[calc(100vh-3rem)] flex-col", children: /* @__PURE__ */ jsx("div", { className: "flex min-w-0 flex-1 flex-col", children: /* @__PURE__ */ jsxs("div", { className: "pt-6 md:pt-8", children: [
185
+ hasHeader && /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between", children: [
186
+ /* @__PURE__ */ jsxs("div", { className: "max-w-3xl", children: [
187
+ eyebrow && /* @__PURE__ */ jsx("div", { className: "label-mono text-primary mb-3", children: eyebrow }),
188
+ /* @__PURE__ */ jsx("h1", { className: "font-display text-2xl font-bold tracking-tight sm:text-3xl", children: title }),
189
+ description && /* @__PURE__ */ jsx("p", { className: "text-muted-foreground mt-3 max-w-[64ch] text-sm leading-relaxed", children: description })
190
+ ] }),
191
+ headerActions && /* @__PURE__ */ jsx("div", { className: "flex shrink-0 items-center gap-2", children: headerActions })
192
+ ] }),
193
+ /* @__PURE__ */ jsx("div", { className: hasHeader ? "mt-8 pb-12" : "pb-12", children })
194
+ ] }) }) }) });
195
+ }
196
+ var TONE_CLASS = {
197
+ primary: "text-primary",
198
+ muted: "text-muted-foreground",
199
+ warning: "text-warning",
200
+ success: "text-success",
201
+ destructive: "text-destructive"
202
+ };
203
+ function SectionHeader({
204
+ label,
205
+ meta,
206
+ tone = "primary",
207
+ className = ""
208
+ }) {
209
+ return /* @__PURE__ */ jsxs("div", { className: `mb-3 flex items-baseline justify-between gap-2 ${className}`, children: [
210
+ /* @__PURE__ */ jsx("div", { className: "flex items-center gap-1.5", children: /* @__PURE__ */ jsxs("div", { className: `label-mono ${TONE_CLASS[tone]}`, children: [
211
+ "\xA7 ",
212
+ label
213
+ ] }) }),
214
+ meta && /* @__PURE__ */ jsx("span", { className: "text-muted-foreground/70 font-mono text-[10px] tracking-widest uppercase", children: meta })
215
+ ] });
216
+ }
217
+ var TONE_CLASS2 = {
218
+ info: "border-primary/30 bg-primary/5",
219
+ warning: "border-warning/40 bg-warning/5",
220
+ muted: "border-border bg-muted/20"
221
+ };
222
+ var LABEL_TONE_CLASS = {
223
+ info: "text-primary",
224
+ warning: "text-warning",
225
+ muted: "text-muted-foreground"
226
+ };
227
+ function EmptyState({
228
+ label,
229
+ children,
230
+ cta,
231
+ secondary,
232
+ tone = "info",
233
+ className = ""
234
+ }) {
235
+ return /* @__PURE__ */ jsxs("div", { className: `border p-5 md:p-6 ${TONE_CLASS2[tone]} ${className}`, children: [
236
+ /* @__PURE__ */ jsxs("div", { className: `label-mono mb-2 ${LABEL_TONE_CLASS[tone]}`, children: [
237
+ "\xA7 ",
238
+ label
239
+ ] }),
240
+ /* @__PURE__ */ jsx("div", { className: "text-foreground/85 max-w-2xl text-sm leading-relaxed", children }),
241
+ (cta || secondary) && /* @__PURE__ */ jsxs("div", { className: "mt-4 flex flex-wrap gap-3", children: [
242
+ cta && /* @__PURE__ */ jsx(CtaLink, { ...cta, variant: "primary" }),
243
+ secondary && /* @__PURE__ */ jsx(CtaLink, { ...secondary, variant: "secondary" })
244
+ ] })
245
+ ] });
246
+ }
247
+ function CtaLink({
248
+ label,
249
+ href,
250
+ external,
251
+ variant
252
+ }) {
253
+ const cls = variant === "primary" ? "bg-primary text-primary-foreground hover:bg-primary/90 inline-flex h-9 items-center justify-center rounded-md px-4 font-mono text-[11px] font-semibold tracking-widest uppercase" : "text-muted-foreground hover:text-foreground border-input hover:bg-accent inline-flex h-9 items-center justify-center rounded-md border px-4 font-mono text-[11px] tracking-widest uppercase";
254
+ const text = external ? `${label} \u2197` : label;
255
+ if (external) {
256
+ return /* @__PURE__ */ jsx("a", { href, target: "_blank", rel: "noreferrer", className: cls, children: text });
257
+ }
258
+ return /* @__PURE__ */ jsx(Link, { href, className: cls, children: text });
259
+ }
260
+ var TONE_CLASS3 = {
261
+ default: "",
262
+ primary: "text-primary",
263
+ success: "text-success",
264
+ warning: "text-warning",
265
+ destructive: "text-destructive",
266
+ muted: "text-muted-foreground"
267
+ };
268
+ var COL_CLASS = {
269
+ 1: "",
270
+ 2: "md:grid-cols-2",
271
+ 3: "md:grid-cols-3",
272
+ 4: "md:grid-cols-2 lg:grid-cols-4"
273
+ };
274
+ function StatGrid({ items, columns = 3, className = "" }) {
275
+ return /* @__PURE__ */ jsx("div", { className: `bg-border grid gap-px border ${COL_CLASS[columns]} ${className}`, children: items.map((it, i) => /* @__PURE__ */ jsx(Tile, { item: it }, `${it.label}-${i}`)) });
276
+ }
277
+ function Tile({ item }) {
278
+ const tone = item.tone ?? (item.accent ? "primary" : "default");
279
+ return /* @__PURE__ */ jsxs("div", { className: "bg-background p-5", children: [
280
+ /* @__PURE__ */ jsx("div", { className: "text-muted-foreground/80 font-mono text-[10px] tracking-widest uppercase", children: item.label }),
281
+ /* @__PURE__ */ jsx(
282
+ "div",
283
+ {
284
+ className: `font-display mt-1 text-2xl font-bold tabular-nums tracking-tight ${TONE_CLASS3[tone]}`,
285
+ children: item.value
286
+ }
287
+ ),
288
+ item.sub && /* @__PURE__ */ jsx("div", { className: "text-muted-foreground/70 mt-1 font-mono text-[10px] tracking-widest uppercase", children: item.sub })
289
+ ] });
290
+ }
291
+ function StatTile({ children, ...item }) {
292
+ return /* @__PURE__ */ jsxs("div", { children: [
293
+ /* @__PURE__ */ jsx(Tile, { item }),
294
+ children
295
+ ] });
296
+ }
175
297
 
176
- export { EcosystemSwitcher };
298
+ export { AppShell, EcosystemSwitcher, EmptyState, SectionHeader, StatGrid, StatTile };
177
299
  //# sourceMappingURL=index.mjs.map
178
300
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/ecosystem-switcher.tsx"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["import { Boxes, Check, ChevronDown } from 'lucide-react';\nimport Link from 'next/link';\nimport { useEffect, useRef, useState } from 'react';\n\n/**\n * EcosystemSwitcher — cross-product dropdown for jumping between every\n * site in the OrangeCheck family. Drop one into every site's LayoutHeader\n * and mark the active site via the `current` prop.\n *\n * <EcosystemSwitcher current=\"lock\" />\n *\n * The component is dependency-self-contained: no Radix, no Headless UI,\n * just outside-click + Escape handling so it works identically in every\n * site without forcing a peer-dep upgrade. Every link stays in-tab — the\n * family is one app from the user's POV.\n */\n\nexport type EcosystemSlug =\n | 'home'\n | 'docs'\n | 'fleet'\n | 'me'\n | 'vault'\n | 'attest'\n | 'lock'\n | 'vote'\n | 'stamp'\n | 'agent'\n | 'pledge';\n\ninterface SwitcherEntry {\n slug: EcosystemSlug;\n href: string;\n label: string;\n sub: string;\n docsHref: string;\n}\n\nconst ENTRIES: SwitcherEntry[] = [\n {\n slug: 'home',\n href: 'https://ochk.io',\n label: 'orangecheck',\n sub: 'umbrella',\n docsHref: 'https://docs.ochk.io',\n },\n {\n slug: 'docs',\n href: 'https://docs.ochk.io',\n label: 'oc·docs',\n sub: 'unified docs',\n docsHref: 'https://docs.ochk.io',\n },\n {\n slug: 'fleet',\n href: 'https://fleet.ochk.io',\n label: 'oc·fleet',\n sub: 'managed — agent fleet',\n docsHref: 'https://docs.ochk.io/fleet',\n },\n {\n slug: 'me',\n href: 'https://me.ochk.io',\n label: 'oc·me',\n sub: 'earn — consumer identity',\n docsHref: 'https://docs.ochk.io/me',\n },\n {\n slug: 'vault',\n href: 'https://vault.ochk.io',\n label: 'oc·vault',\n sub: 'keep — encrypted secrets',\n docsHref: 'https://docs.ochk.io/vault',\n },\n {\n slug: 'attest',\n href: 'https://attest.ochk.io',\n label: 'oc·attest',\n sub: 'am — sybil resistance',\n docsHref: 'https://docs.ochk.io/attest',\n },\n {\n slug: 'lock',\n href: 'https://lock.ochk.io',\n label: 'oc·lock',\n sub: 'whisper — encryption',\n docsHref: 'https://docs.ochk.io/lock',\n },\n {\n slug: 'vote',\n href: 'https://vote.ochk.io',\n label: 'oc·vote',\n sub: 'decide — polls',\n docsHref: 'https://docs.ochk.io/vote',\n },\n {\n slug: 'stamp',\n href: 'https://stamp.ochk.io',\n label: 'oc·stamp',\n sub: 'declare — block-anchored',\n docsHref: 'https://docs.ochk.io/stamp',\n },\n {\n slug: 'agent',\n href: 'https://agent.ochk.io',\n label: 'oc·agent',\n sub: 'delegate — scoped auth',\n docsHref: 'https://docs.ochk.io/agent',\n },\n {\n slug: 'pledge',\n href: 'https://pledge.ochk.io',\n label: 'oc·pledge',\n sub: 'swear — bonded commitment',\n docsHref: 'https://docs.ochk.io/pledge',\n },\n];\n\nexport interface EcosystemSwitcherProps {\n current: EcosystemSlug;\n className?: string;\n}\n\nexport function EcosystemSwitcher({\n current,\n className,\n}: EcosystemSwitcherProps) {\n const [open, setOpen] = useState(false);\n const containerRef = useRef<HTMLDivElement | null>(null);\n\n // Outside-click + Escape close.\n useEffect(() => {\n if (!open) return;\n function onDoc(e: MouseEvent) {\n if (!containerRef.current) return;\n if (!containerRef.current.contains(e.target as Node)) setOpen(false);\n }\n function onKey(e: KeyboardEvent) {\n if (e.key === 'Escape') setOpen(false);\n }\n document.addEventListener('mousedown', onDoc);\n document.addEventListener('keydown', onKey);\n return () => {\n document.removeEventListener('mousedown', onDoc);\n document.removeEventListener('keydown', onKey);\n };\n }, [open]);\n\n return (\n <div ref={containerRef} className={'relative ' + (className ?? '')}>\n <button\n type=\"button\"\n aria-haspopup=\"menu\"\n aria-expanded={open}\n aria-label=\"Switch OrangeCheck product\"\n title=\"Switch product\"\n onClick={() => setOpen((v) => !v)}\n className={\n 'inline-flex items-center gap-1 px-2 py-1 transition-colors ' +\n (open\n ? 'text-foreground'\n : 'text-muted-foreground hover:text-foreground')\n }\n >\n <Boxes className=\"h-4 w-4\" />\n <ChevronDown\n className={\n 'h-3.5 w-3.5 transition-transform ' + (open ? 'rotate-180' : '')\n }\n />\n </button>\n\n {open && (\n <div\n role=\"menu\"\n aria-label=\"Switch OrangeCheck product\"\n className=\"bg-background absolute right-0 top-full z-[60] mt-2 w-72 border shadow-lg\"\n >\n <div className=\"label-mono text-primary border-b px-4 py-2\">\n § the family\n </div>\n <ul className=\"py-1\">\n {ENTRIES.map((e) => {\n const isActive = e.slug === current;\n return (\n <li key={e.slug}>\n <Link\n href={e.href}\n onClick={() => setOpen(false)}\n aria-current={isActive ? 'page' : undefined}\n className={\n 'group flex items-baseline gap-3 px-4 py-2 transition-colors ' +\n (isActive\n ? 'bg-primary/5'\n : 'hover:bg-muted')\n }\n >\n <span\n className={\n 'font-display flex-1 text-[12px] font-semibold tracking-tight ' +\n (isActive\n ? 'text-primary'\n : 'text-foreground group-hover:text-primary transition-colors')\n }\n >\n {e.label}\n </span>\n <span className=\"text-muted-foreground font-mono text-[10px] tracking-wider uppercase\">\n {e.sub}\n </span>\n {isActive && (\n <Check className=\"text-primary h-3 w-3\" />\n )}\n </Link>\n </li>\n );\n })}\n </ul>\n <div className=\"border-t px-4 py-2 font-mono text-[10px] tracking-widest uppercase\">\n <Link\n href=\"https://docs.ochk.io\"\n onClick={() => setOpen(false)}\n className=\"text-muted-foreground hover:text-foreground inline-block transition-colors\"\n >\n docs.ochk.io →\n </Link>\n </div>\n </div>\n )}\n </div>\n );\n}\n"]}
1
+ {"version":3,"sources":["../src/ecosystem-switcher.tsx","../src/app-shell.tsx","../src/section-header.tsx","../src/empty-state.tsx","../src/stat-grid.tsx"],"names":["jsx","jsxs","TONE_CLASS","Link"],"mappings":"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","file":"index.mjs","sourcesContent":["import { Boxes, Check, ChevronDown } from 'lucide-react';\nimport Link from 'next/link';\nimport { useEffect, useRef, useState } from 'react';\n\n/**\n * EcosystemSwitcher — cross-product dropdown for jumping between every\n * site in the OrangeCheck family. Drop one into every site's LayoutHeader\n * and mark the active site via the `current` prop.\n *\n * <EcosystemSwitcher current=\"lock\" />\n *\n * The component is dependency-self-contained: no Radix, no Headless UI,\n * just outside-click + Escape handling so it works identically in every\n * site without forcing a peer-dep upgrade. Every link stays in-tab — the\n * family is one app from the user's POV.\n */\n\nexport type EcosystemSlug =\n | 'home'\n | 'docs'\n | 'fleet'\n | 'me'\n | 'vault'\n | 'attest'\n | 'lock'\n | 'vote'\n | 'stamp'\n | 'agent'\n | 'pledge';\n\ninterface SwitcherEntry {\n slug: EcosystemSlug;\n href: string;\n label: string;\n sub: string;\n docsHref: string;\n}\n\nconst ENTRIES: SwitcherEntry[] = [\n {\n slug: 'home',\n href: 'https://ochk.io',\n label: 'orangecheck',\n sub: 'umbrella',\n docsHref: 'https://docs.ochk.io',\n },\n {\n slug: 'docs',\n href: 'https://docs.ochk.io',\n label: 'oc·docs',\n sub: 'unified docs',\n docsHref: 'https://docs.ochk.io',\n },\n {\n slug: 'fleet',\n href: 'https://fleet.ochk.io',\n label: 'oc·fleet',\n sub: 'managed — agent fleet',\n docsHref: 'https://docs.ochk.io/fleet',\n },\n {\n slug: 'me',\n href: 'https://me.ochk.io',\n label: 'oc·me',\n sub: 'earn — consumer identity',\n docsHref: 'https://docs.ochk.io/me',\n },\n {\n slug: 'vault',\n href: 'https://vault.ochk.io',\n label: 'oc·vault',\n sub: 'keep — encrypted secrets',\n docsHref: 'https://docs.ochk.io/vault',\n },\n {\n slug: 'attest',\n href: 'https://attest.ochk.io',\n label: 'oc·attest',\n sub: 'am — sybil resistance',\n docsHref: 'https://docs.ochk.io/attest',\n },\n {\n slug: 'lock',\n href: 'https://lock.ochk.io',\n label: 'oc·lock',\n sub: 'whisper — encryption',\n docsHref: 'https://docs.ochk.io/lock',\n },\n {\n slug: 'vote',\n href: 'https://vote.ochk.io',\n label: 'oc·vote',\n sub: 'decide — polls',\n docsHref: 'https://docs.ochk.io/vote',\n },\n {\n slug: 'stamp',\n href: 'https://stamp.ochk.io',\n label: 'oc·stamp',\n sub: 'declare — block-anchored',\n docsHref: 'https://docs.ochk.io/stamp',\n },\n {\n slug: 'agent',\n href: 'https://agent.ochk.io',\n label: 'oc·agent',\n sub: 'delegate — scoped auth',\n docsHref: 'https://docs.ochk.io/agent',\n },\n {\n slug: 'pledge',\n href: 'https://pledge.ochk.io',\n label: 'oc·pledge',\n sub: 'swear — bonded commitment',\n docsHref: 'https://docs.ochk.io/pledge',\n },\n];\n\nexport interface EcosystemSwitcherProps {\n current: EcosystemSlug;\n className?: string;\n}\n\nexport function EcosystemSwitcher({\n current,\n className,\n}: EcosystemSwitcherProps) {\n const [open, setOpen] = useState(false);\n const containerRef = useRef<HTMLDivElement | null>(null);\n\n // Outside-click + Escape close.\n useEffect(() => {\n if (!open) return;\n function onDoc(e: MouseEvent) {\n if (!containerRef.current) return;\n if (!containerRef.current.contains(e.target as Node)) setOpen(false);\n }\n function onKey(e: KeyboardEvent) {\n if (e.key === 'Escape') setOpen(false);\n }\n document.addEventListener('mousedown', onDoc);\n document.addEventListener('keydown', onKey);\n return () => {\n document.removeEventListener('mousedown', onDoc);\n document.removeEventListener('keydown', onKey);\n };\n }, [open]);\n\n return (\n <div ref={containerRef} className={'relative ' + (className ?? '')}>\n <button\n type=\"button\"\n aria-haspopup=\"menu\"\n aria-expanded={open}\n aria-label=\"Switch OrangeCheck product\"\n title=\"Switch product\"\n onClick={() => setOpen((v) => !v)}\n className={\n 'inline-flex items-center gap-1 px-2 py-1 transition-colors ' +\n (open\n ? 'text-foreground'\n : 'text-muted-foreground hover:text-foreground')\n }\n >\n <Boxes className=\"h-4 w-4\" />\n <ChevronDown\n className={\n 'h-3.5 w-3.5 transition-transform ' + (open ? 'rotate-180' : '')\n }\n />\n </button>\n\n {open && (\n <div\n role=\"menu\"\n aria-label=\"Switch OrangeCheck product\"\n className=\"bg-background absolute right-0 top-full z-[60] mt-2 w-72 border shadow-lg\"\n >\n <div className=\"label-mono text-primary border-b px-4 py-2\">\n § the family\n </div>\n <ul className=\"py-1\">\n {ENTRIES.map((e) => {\n const isActive = e.slug === current;\n return (\n <li key={e.slug}>\n <Link\n href={e.href}\n onClick={() => setOpen(false)}\n aria-current={isActive ? 'page' : undefined}\n className={\n 'group flex items-baseline gap-3 px-4 py-2 transition-colors ' +\n (isActive\n ? 'bg-primary/5'\n : 'hover:bg-muted')\n }\n >\n <span\n className={\n 'font-display flex-1 text-[12px] font-semibold tracking-tight ' +\n (isActive\n ? 'text-primary'\n : 'text-foreground group-hover:text-primary transition-colors')\n }\n >\n {e.label}\n </span>\n <span className=\"text-muted-foreground font-mono text-[10px] tracking-wider uppercase\">\n {e.sub}\n </span>\n {isActive && (\n <Check className=\"text-primary h-3 w-3\" />\n )}\n </Link>\n </li>\n );\n })}\n </ul>\n <div className=\"border-t px-4 py-2 font-mono text-[10px] tracking-widest uppercase\">\n <Link\n href=\"https://docs.ochk.io\"\n onClick={() => setOpen(false)}\n className=\"text-muted-foreground hover:text-foreground inline-block transition-colors\"\n >\n docs.ochk.io →\n </Link>\n </div>\n </div>\n )}\n </div>\n );\n}\n","import type { ReactNode } from 'react';\n\n/**\n * AppShell — shared page chrome for every authenticated dashboard surface\n * across the OC family (vault, me, fleet, future). Lifted from oc-me-web's\n * `MeShell` and oc-vault-web's `VaultShell` — same eyebrow / title /\n * description / actions header band, no sidebar (sidebars are app-specific\n * and stay in the consuming app).\n *\n * Usage:\n * <AppShell eyebrow=\"§ vault\" title=\"your vault.\" description=\"…\">\n * ...\n * </AppShell>\n *\n * The component is stateless and dependency-free. Tailwind classes assume\n * the consuming site loads the family `globals.css` (which defines\n * `.container`, `.label-mono`, the dark-by-default palette, etc.).\n */\n\nexport interface AppShellProps {\n eyebrow?: ReactNode;\n title?: ReactNode;\n description?: ReactNode;\n /** Right-aligned action node rendered next to the title (e.g. CTA buttons). */\n headerActions?: ReactNode;\n children: ReactNode;\n className?: string;\n}\n\nexport function AppShell({\n eyebrow,\n title,\n description,\n headerActions,\n children,\n className,\n}: AppShellProps) {\n const hasHeader = Boolean(title);\n return (\n <div className={'container ' + (className ?? '')}>\n <div className=\"flex min-h-[calc(100vh-3rem)] flex-col\">\n <div className=\"flex min-w-0 flex-1 flex-col\">\n <div className=\"pt-6 md:pt-8\">\n {hasHeader && (\n <div className=\"flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between\">\n <div className=\"max-w-3xl\">\n {eyebrow && (\n <div className=\"label-mono text-primary mb-3\">\n {eyebrow}\n </div>\n )}\n <h1 className=\"font-display text-2xl font-bold tracking-tight sm:text-3xl\">\n {title}\n </h1>\n {description && (\n <p className=\"text-muted-foreground mt-3 max-w-[64ch] text-sm leading-relaxed\">\n {description}\n </p>\n )}\n </div>\n {headerActions && (\n <div className=\"flex shrink-0 items-center gap-2\">\n {headerActions}\n </div>\n )}\n </div>\n )}\n <div className={hasHeader ? 'mt-8 pb-12' : 'pb-12'}>{children}</div>\n </div>\n </div>\n </div>\n </div>\n );\n}\n","import type { ReactNode } from 'react';\n\nexport interface SectionHeaderProps {\n /** Plain section name — rendered after a \"§ \" glyph in label-mono. */\n label: string;\n /** Optional right-side string (count, \"most recent first\"). */\n meta?: ReactNode;\n tone?: 'primary' | 'muted' | 'warning' | 'success' | 'destructive';\n className?: string;\n}\n\nconst TONE_CLASS = {\n primary: 'text-primary',\n muted: 'text-muted-foreground',\n warning: 'text-warning',\n success: 'text-success',\n destructive: 'text-destructive',\n} as const;\n\n/**\n * SectionHeader — the canonical \"§ x\" section header used across every\n * /me, /vault, and /fleet dashboard surface. Lifted from oc-me-web's\n * `me/ui/SectionHeader` so the visual contract stays single-source.\n *\n * Pattern is `label-mono text-primary mb-3` with a \"§ \" glyph followed by\n * the label, plus an optional muted/uppercase right-side meta string.\n */\nexport function SectionHeader({\n label,\n meta,\n tone = 'primary',\n className = '',\n}: SectionHeaderProps) {\n return (\n <div className={`mb-3 flex items-baseline justify-between gap-2 ${className}`}>\n <div className=\"flex items-center gap-1.5\">\n <div className={`label-mono ${TONE_CLASS[tone]}`}>§ {label}</div>\n </div>\n {meta && (\n <span className=\"text-muted-foreground/70 font-mono text-[10px] tracking-widest uppercase\">\n {meta}\n </span>\n )}\n </div>\n );\n}\n","import Link from 'next/link';\nimport type { ReactNode } from 'react';\n\nexport interface EmptyStateCta {\n label: string;\n href: string;\n /** External links open in a new tab and get a ↗ glyph. */\n external?: boolean;\n}\n\nexport interface EmptyStateProps {\n /** Short heading — one mono-uppercased label like \"no entries yet\". */\n label: string;\n /** Body — short prose explaining what would appear here and how. */\n children: ReactNode;\n cta?: EmptyStateCta;\n secondary?: EmptyStateCta;\n tone?: 'info' | 'warning' | 'muted';\n className?: string;\n}\n\nconst TONE_CLASS = {\n info: 'border-primary/30 bg-primary/5',\n warning: 'border-warning/40 bg-warning/5',\n muted: 'border-border bg-muted/20',\n} as const;\n\nconst LABEL_TONE_CLASS = {\n info: 'text-primary',\n warning: 'text-warning',\n muted: 'text-muted-foreground',\n} as const;\n\n/**\n * EmptyState — the canonical empty-state card used across every /me,\n * /vault, and /fleet dashboard. Empty states should *teach*: explain what\n * would appear, and how to make it appear. Lifted from oc-me-web's\n * `me/ui/EmptyState`.\n */\nexport function EmptyState({\n label,\n children,\n cta,\n secondary,\n tone = 'info',\n className = '',\n}: EmptyStateProps) {\n return (\n <div className={`border p-5 md:p-6 ${TONE_CLASS[tone]} ${className}`}>\n <div className={`label-mono mb-2 ${LABEL_TONE_CLASS[tone]}`}>§ {label}</div>\n <div className=\"text-foreground/85 max-w-2xl text-sm leading-relaxed\">{children}</div>\n {(cta || secondary) && (\n <div className=\"mt-4 flex flex-wrap gap-3\">\n {cta && <CtaLink {...cta} variant=\"primary\" />}\n {secondary && <CtaLink {...secondary} variant=\"secondary\" />}\n </div>\n )}\n </div>\n );\n}\n\nfunction CtaLink({\n label,\n href,\n external,\n variant,\n}: EmptyStateCta & { variant: 'primary' | 'secondary' }) {\n const cls =\n variant === 'primary'\n ? 'bg-primary text-primary-foreground hover:bg-primary/90 inline-flex h-9 items-center justify-center rounded-md px-4 font-mono text-[11px] font-semibold tracking-widest uppercase'\n : 'text-muted-foreground hover:text-foreground border-input hover:bg-accent inline-flex h-9 items-center justify-center rounded-md border px-4 font-mono text-[11px] tracking-widest uppercase';\n const text = external ? `${label} ↗` : label;\n if (external) {\n return (\n <a href={href} target=\"_blank\" rel=\"noreferrer\" className={cls}>\n {text}\n </a>\n );\n }\n return (\n <Link href={href} className={cls}>\n {text}\n </Link>\n );\n}\n","import type { ReactNode } from 'react';\n\nexport interface StatItem {\n /** Short uppercased label rendered in mono. */\n label: string;\n /** Primary value · already formatted as a string. */\n value: string;\n /** Optional secondary line · USD conversion, \"last 30 days\", etc. */\n sub?: string;\n /** When true, value is rendered in primary tone (use for headline metric). */\n accent?: boolean;\n /** Optional tone for the value (overrides accent). */\n tone?: 'default' | 'primary' | 'success' | 'warning' | 'destructive' | 'muted';\n}\n\nexport interface StatGridProps {\n items: StatItem[];\n columns?: 1 | 2 | 3 | 4;\n className?: string;\n}\n\nconst TONE_CLASS = {\n default: '',\n primary: 'text-primary',\n success: 'text-success',\n warning: 'text-warning',\n destructive: 'text-destructive',\n muted: 'text-muted-foreground',\n} as const;\n\nconst COL_CLASS = {\n 1: '',\n 2: 'md:grid-cols-2',\n 3: 'md:grid-cols-3',\n 4: 'md:grid-cols-2 lg:grid-cols-4',\n} as const;\n\n/**\n * StatGrid — the canonical stats row used across family dashboards.\n * Lifted from oc-me-web's `me/ui/StatGrid`. Grid of equal-width tiles\n * separated by 1px borders. Always pre-format the value string —\n * the component does no number formatting.\n */\nexport function StatGrid({ items, columns = 3, className = '' }: StatGridProps) {\n return (\n <div className={`bg-border grid gap-px border ${COL_CLASS[columns]} ${className}`}>\n {items.map((it, i) => (\n <Tile key={`${it.label}-${i}`} item={it} />\n ))}\n </div>\n );\n}\n\nfunction Tile({ item }: { item: StatItem }) {\n const tone = item.tone ?? (item.accent ? 'primary' : 'default');\n return (\n <div className=\"bg-background p-5\">\n <div className=\"text-muted-foreground/80 font-mono text-[10px] tracking-widest uppercase\">\n {item.label}\n </div>\n <div\n className={`font-display mt-1 text-2xl font-bold tabular-nums tracking-tight ${TONE_CLASS[tone]}`}\n >\n {item.value}\n </div>\n {item.sub && (\n <div className=\"text-muted-foreground/70 mt-1 font-mono text-[10px] tracking-widest uppercase\">\n {item.sub}\n </div>\n )}\n </div>\n );\n}\n\nexport function StatTile({ children, ...item }: StatItem & { children?: ReactNode }) {\n return (\n <div>\n <Tile item={item} />\n {children}\n </div>\n );\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@orangecheck/ui",
3
- "version": "0.3.0",
3
+ "version": "0.3.1",
4
4
  "description": "OrangeCheck family-internal UI for the .ochk.io sub-sites. Tailwind 4 + Next.js Pages Router. Not for third-party integration.",
5
5
  "keywords": [
6
6
  "orangecheck",