@orangecheck/design 0.6.1 → 0.7.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/chrome.d.mts +150 -0
- package/dist/chrome.d.ts +150 -0
- package/dist/chrome.js +1633 -0
- package/dist/chrome.js.map +1 -0
- package/dist/chrome.mjs +1616 -0
- package/dist/chrome.mjs.map +1 -0
- package/dist/components.d.mts +5 -1
- package/dist/components.d.ts +5 -1
- package/dist/components.js +1874 -7
- package/dist/components.js.map +1 -1
- package/dist/components.mjs +1835 -1
- package/dist/components.mjs.map +1 -1
- package/dist/composites.d.mts +88 -0
- package/dist/composites.d.ts +88 -0
- package/dist/composites.js +268 -0
- package/dist/composites.js.map +1 -0
- package/dist/composites.mjs +236 -0
- package/dist/composites.mjs.map +1 -0
- package/dist/index.d.mts +5 -2
- package/dist/index.d.ts +5 -2
- package/dist/index.js +1912 -133
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1888 -135
- package/dist/index.mjs.map +1 -1
- package/dist/primitives.d.mts +25 -2
- package/dist/primitives.d.ts +25 -2
- package/dist/primitives.js +95 -3
- package/dist/primitives.js.map +1 -1
- package/dist/primitives.mjs +90 -4
- package/dist/primitives.mjs.map +1 -1
- package/dist/styles.css +0 -1
- package/package.json +12 -2
package/dist/components.js
CHANGED
|
@@ -1,14 +1,1881 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var lucideReact = require('lucide-react');
|
|
4
|
+
var PopoverPrimitive = require('@radix-ui/react-popover');
|
|
5
|
+
var clsx = require('clsx');
|
|
6
|
+
var tailwindMerge = require('tailwind-merge');
|
|
7
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
8
|
+
var Link6 = require('next/link');
|
|
9
|
+
var react = require('react');
|
|
10
|
+
var router = require('next/router');
|
|
11
|
+
var authClient = require('@orangecheck/auth-client');
|
|
4
12
|
|
|
13
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
5
14
|
|
|
15
|
+
function _interopNamespace(e) {
|
|
16
|
+
if (e && e.__esModule) return e;
|
|
17
|
+
var n = Object.create(null);
|
|
18
|
+
if (e) {
|
|
19
|
+
Object.keys(e).forEach(function (k) {
|
|
20
|
+
if (k !== 'default') {
|
|
21
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
22
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
23
|
+
enumerable: true,
|
|
24
|
+
get: function () { return e[k]; }
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
n.default = e;
|
|
30
|
+
return Object.freeze(n);
|
|
31
|
+
}
|
|
6
32
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
33
|
+
var PopoverPrimitive__namespace = /*#__PURE__*/_interopNamespace(PopoverPrimitive);
|
|
34
|
+
var Link6__default = /*#__PURE__*/_interopDefault(Link6);
|
|
35
|
+
|
|
36
|
+
// src/composites/help-hint.tsx
|
|
37
|
+
function cn(...inputs) {
|
|
38
|
+
return tailwindMerge.twMerge(clsx.clsx(inputs));
|
|
39
|
+
}
|
|
40
|
+
function Popover({ ...props }) {
|
|
41
|
+
return /* @__PURE__ */ jsxRuntime.jsx(PopoverPrimitive__namespace.Root, { "data-slot": "popover", ...props });
|
|
42
|
+
}
|
|
43
|
+
function PopoverTrigger({ ...props }) {
|
|
44
|
+
return /* @__PURE__ */ jsxRuntime.jsx(PopoverPrimitive__namespace.Trigger, { "data-slot": "popover-trigger", ...props });
|
|
45
|
+
}
|
|
46
|
+
function PopoverContent({
|
|
47
|
+
className,
|
|
48
|
+
align = "center",
|
|
49
|
+
sideOffset = 4,
|
|
50
|
+
...props
|
|
51
|
+
}) {
|
|
52
|
+
return /* @__PURE__ */ jsxRuntime.jsx(PopoverPrimitive__namespace.Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
53
|
+
PopoverPrimitive__namespace.Content,
|
|
54
|
+
{
|
|
55
|
+
"data-slot": "popover-content",
|
|
56
|
+
align,
|
|
57
|
+
sideOffset,
|
|
58
|
+
className: cn(
|
|
59
|
+
"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-72 origin-(--radix-popover-content-transform-origin) rounded-md border p-4 shadow-md outline-hidden",
|
|
60
|
+
className
|
|
61
|
+
),
|
|
62
|
+
...props
|
|
63
|
+
}
|
|
64
|
+
) });
|
|
65
|
+
}
|
|
66
|
+
function HelpHint({
|
|
67
|
+
title,
|
|
68
|
+
children,
|
|
69
|
+
side = "bottom",
|
|
70
|
+
label = "more information",
|
|
71
|
+
className
|
|
72
|
+
}) {
|
|
73
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(Popover, { children: [
|
|
74
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
75
|
+
PopoverTrigger,
|
|
76
|
+
{
|
|
77
|
+
"aria-label": label,
|
|
78
|
+
className: cn(
|
|
79
|
+
"text-muted-foreground/60 hover:text-foreground inline-flex size-3.5 items-center justify-center align-middle transition-colors outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
80
|
+
className
|
|
81
|
+
),
|
|
82
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.HelpCircle, { className: "size-3.5", "aria-hidden": true })
|
|
83
|
+
}
|
|
84
|
+
),
|
|
85
|
+
/* @__PURE__ */ jsxRuntime.jsxs(PopoverContent, { side, className: "w-72 space-y-1.5", children: [
|
|
86
|
+
title && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "label-mono text-foreground text-[10px]", children: title }),
|
|
87
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-muted-foreground text-xs leading-relaxed", children })
|
|
88
|
+
] })
|
|
89
|
+
] });
|
|
90
|
+
}
|
|
91
|
+
var TONE_CLASS = {
|
|
92
|
+
primary: "text-primary",
|
|
93
|
+
muted: "text-muted-foreground",
|
|
94
|
+
warning: "text-warning",
|
|
95
|
+
success: "text-success",
|
|
96
|
+
destructive: "text-destructive"
|
|
97
|
+
};
|
|
98
|
+
function SectionHeader({
|
|
99
|
+
label,
|
|
100
|
+
meta,
|
|
101
|
+
hint,
|
|
102
|
+
tone = "primary",
|
|
103
|
+
className = ""
|
|
104
|
+
}) {
|
|
105
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `mb-3 flex items-baseline justify-between gap-2 ${className}`, children: [
|
|
106
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
107
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: `label-mono ${TONE_CLASS[tone]}`, children: [
|
|
108
|
+
"\xA7 ",
|
|
109
|
+
label
|
|
110
|
+
] }),
|
|
111
|
+
hint && /* @__PURE__ */ jsxRuntime.jsx(HelpHint, { title: hint.title, side: hint.side ?? "bottom", children: hint.body })
|
|
112
|
+
] }),
|
|
113
|
+
meta && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground/70 font-mono text-[10px] tracking-widest uppercase", children: meta })
|
|
114
|
+
] });
|
|
115
|
+
}
|
|
116
|
+
var TONE_CLASS2 = {
|
|
117
|
+
info: "border-primary/30 bg-primary/5",
|
|
118
|
+
warning: "border-warning/40 bg-warning/5",
|
|
119
|
+
muted: "border-border bg-muted/20"
|
|
120
|
+
};
|
|
121
|
+
var LABEL_TONE_CLASS = {
|
|
122
|
+
info: "text-primary",
|
|
123
|
+
warning: "text-warning",
|
|
124
|
+
muted: "text-muted-foreground"
|
|
125
|
+
};
|
|
126
|
+
function EmptyState({
|
|
127
|
+
label,
|
|
128
|
+
children,
|
|
129
|
+
cta,
|
|
130
|
+
secondary,
|
|
131
|
+
tone = "info",
|
|
132
|
+
className = ""
|
|
133
|
+
}) {
|
|
134
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `border p-5 md:p-6 ${TONE_CLASS2[tone]} ${className}`, children: [
|
|
135
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: `label-mono mb-2 ${LABEL_TONE_CLASS[tone]}`, children: [
|
|
136
|
+
"\xA7 ",
|
|
137
|
+
label
|
|
138
|
+
] }),
|
|
139
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-foreground/85 max-w-2xl text-sm leading-relaxed", children }),
|
|
140
|
+
(cta || secondary) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-4 flex flex-wrap gap-3", children: [
|
|
141
|
+
cta && /* @__PURE__ */ jsxRuntime.jsx(CtaLink, { ...cta, variant: "primary" }),
|
|
142
|
+
secondary && /* @__PURE__ */ jsxRuntime.jsx(CtaLink, { ...secondary, variant: "secondary" })
|
|
143
|
+
] })
|
|
144
|
+
] });
|
|
145
|
+
}
|
|
146
|
+
function CtaLink({
|
|
147
|
+
label,
|
|
148
|
+
href,
|
|
149
|
+
external,
|
|
150
|
+
variant
|
|
151
|
+
}) {
|
|
152
|
+
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";
|
|
153
|
+
const text = external ? `${label} \u2197` : label;
|
|
154
|
+
if (external) {
|
|
155
|
+
return /* @__PURE__ */ jsxRuntime.jsx("a", { href, target: "_blank", rel: "noreferrer", className: cls, children: text });
|
|
156
|
+
}
|
|
157
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Link6__default.default, { href, className: cls, children: text });
|
|
158
|
+
}
|
|
159
|
+
var TONE_CLASS3 = {
|
|
160
|
+
default: "",
|
|
161
|
+
primary: "text-primary",
|
|
162
|
+
success: "text-success",
|
|
163
|
+
warning: "text-warning",
|
|
164
|
+
destructive: "text-destructive",
|
|
165
|
+
muted: "text-muted-foreground"
|
|
166
|
+
};
|
|
167
|
+
var COL_CLASS = {
|
|
168
|
+
1: "",
|
|
169
|
+
2: "md:grid-cols-2",
|
|
170
|
+
3: "md:grid-cols-3",
|
|
171
|
+
4: "md:grid-cols-2 lg:grid-cols-4"
|
|
172
|
+
};
|
|
173
|
+
function StatGrid({ items, columns = 3, className = "" }) {
|
|
174
|
+
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}`)) });
|
|
175
|
+
}
|
|
176
|
+
function Tile({ item }) {
|
|
177
|
+
const tone = item.tone ?? (item.accent ? "primary" : "default");
|
|
178
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-background p-5", children: [
|
|
179
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-muted-foreground/80 font-mono text-[10px] tracking-widest uppercase", children: item.label }),
|
|
180
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
181
|
+
"div",
|
|
182
|
+
{
|
|
183
|
+
className: `font-display mt-1 text-2xl font-bold tabular-nums tracking-tight ${TONE_CLASS3[tone]}`,
|
|
184
|
+
children: item.value
|
|
185
|
+
}
|
|
186
|
+
),
|
|
187
|
+
item.sub && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-muted-foreground/70 mt-1 font-mono text-[10px] tracking-widest uppercase", children: item.sub })
|
|
188
|
+
] });
|
|
189
|
+
}
|
|
190
|
+
function StatTile({ children, ...item }) {
|
|
191
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
192
|
+
/* @__PURE__ */ jsxRuntime.jsx(Tile, { item }),
|
|
193
|
+
children
|
|
194
|
+
] });
|
|
195
|
+
}
|
|
196
|
+
var FRAME = {
|
|
197
|
+
info: "border-primary/30 bg-primary/5",
|
|
198
|
+
warning: "border-warning/40 bg-warning/5",
|
|
199
|
+
destructive: "border-destructive/40 bg-destructive/5",
|
|
200
|
+
success: "border-success/40 bg-success/5",
|
|
201
|
+
muted: "border-border bg-muted/20"
|
|
202
|
+
};
|
|
203
|
+
var LABEL = {
|
|
204
|
+
info: "text-primary",
|
|
205
|
+
warning: "text-warning",
|
|
206
|
+
destructive: "text-destructive",
|
|
207
|
+
success: "text-success",
|
|
208
|
+
muted: "text-muted-foreground"
|
|
209
|
+
};
|
|
210
|
+
function Callout({ tone = "info", label, icon, children, action, className }) {
|
|
211
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("border p-4 md:p-5", FRAME[tone], className), children: [
|
|
212
|
+
label && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("label-mono mb-2 flex items-center gap-1.5", LABEL[tone]), children: [
|
|
213
|
+
icon,
|
|
214
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
215
|
+
"\xA7 ",
|
|
216
|
+
label
|
|
217
|
+
] })
|
|
218
|
+
] }),
|
|
219
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-foreground/85 text-sm leading-relaxed", children: [
|
|
220
|
+
!label && icon ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("mr-2 inline-flex align-middle", LABEL[tone]), children: icon }) : null,
|
|
221
|
+
children
|
|
222
|
+
] }),
|
|
223
|
+
action && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-3 flex flex-wrap gap-3", children: action })
|
|
224
|
+
] });
|
|
225
|
+
}
|
|
226
|
+
function DefinitionList({ items, className }) {
|
|
227
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
228
|
+
"dl",
|
|
229
|
+
{
|
|
230
|
+
className: cn(
|
|
231
|
+
"grid gap-x-5 gap-y-2 text-sm sm:grid-cols-[auto_1fr] sm:items-baseline",
|
|
232
|
+
className
|
|
233
|
+
),
|
|
234
|
+
children: items.map((item, i) => /* @__PURE__ */ jsxRuntime.jsxs(react.Fragment, { children: [
|
|
235
|
+
/* @__PURE__ */ jsxRuntime.jsx("dt", { className: "label-mono text-muted-foreground text-[10px]", children: item.label }),
|
|
236
|
+
/* @__PURE__ */ jsxRuntime.jsx("dd", { className: "text-foreground font-mono text-xs break-all", children: item.value })
|
|
237
|
+
] }, i))
|
|
238
|
+
}
|
|
239
|
+
);
|
|
240
|
+
}
|
|
241
|
+
function DataRow({ children, meta, action, as, className }) {
|
|
242
|
+
const Tag = as ?? "div";
|
|
243
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
244
|
+
Tag,
|
|
245
|
+
{
|
|
246
|
+
className: cn(
|
|
247
|
+
"flex flex-col gap-1 py-3 sm:flex-row sm:items-baseline sm:justify-between sm:gap-4",
|
|
248
|
+
className
|
|
249
|
+
),
|
|
250
|
+
children: [
|
|
251
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-w-0 flex-1", children }),
|
|
252
|
+
(meta || action) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex shrink-0 items-center gap-3 sm:justify-end", children: [
|
|
253
|
+
meta && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground font-mono text-[11px] tracking-wide", children: meta }),
|
|
254
|
+
action
|
|
255
|
+
] })
|
|
256
|
+
]
|
|
257
|
+
}
|
|
258
|
+
);
|
|
259
|
+
}
|
|
260
|
+
var ENTRIES = [
|
|
261
|
+
{
|
|
262
|
+
slug: "home",
|
|
263
|
+
href: "https://ochk.io",
|
|
264
|
+
label: "orangecheck",
|
|
265
|
+
sub: "umbrella",
|
|
266
|
+
docsHref: "https://docs.ochk.io"
|
|
267
|
+
},
|
|
268
|
+
{
|
|
269
|
+
slug: "docs",
|
|
270
|
+
href: "https://docs.ochk.io",
|
|
271
|
+
label: "oc\xB7docs",
|
|
272
|
+
sub: "unified docs",
|
|
273
|
+
docsHref: "https://docs.ochk.io"
|
|
274
|
+
},
|
|
275
|
+
{
|
|
276
|
+
slug: "fleet",
|
|
277
|
+
href: "https://fleet.ochk.io",
|
|
278
|
+
label: "oc\xB7fleet",
|
|
279
|
+
sub: "managed \u2014 agent fleet",
|
|
280
|
+
docsHref: "https://docs.ochk.io/fleet"
|
|
281
|
+
},
|
|
282
|
+
{
|
|
283
|
+
slug: "me",
|
|
284
|
+
href: "https://me.ochk.io",
|
|
285
|
+
label: "oc\xB7me",
|
|
286
|
+
sub: "earn \u2014 consumer identity",
|
|
287
|
+
docsHref: "https://docs.ochk.io/me"
|
|
288
|
+
},
|
|
289
|
+
{
|
|
290
|
+
slug: "vault",
|
|
291
|
+
href: "https://vault.ochk.io",
|
|
292
|
+
label: "oc\xB7vault",
|
|
293
|
+
sub: "keep \u2014 encrypted secrets",
|
|
294
|
+
docsHref: "https://docs.ochk.io/vault"
|
|
295
|
+
},
|
|
296
|
+
{
|
|
297
|
+
slug: "attest",
|
|
298
|
+
href: "https://attest.ochk.io",
|
|
299
|
+
label: "oc\xB7attest",
|
|
300
|
+
sub: "am \u2014 sybil resistance",
|
|
301
|
+
docsHref: "https://docs.ochk.io/attest"
|
|
302
|
+
},
|
|
303
|
+
{
|
|
304
|
+
slug: "lock",
|
|
305
|
+
href: "https://lock.ochk.io",
|
|
306
|
+
label: "oc\xB7lock",
|
|
307
|
+
sub: "whisper \u2014 encryption",
|
|
308
|
+
docsHref: "https://docs.ochk.io/lock"
|
|
309
|
+
},
|
|
310
|
+
{
|
|
311
|
+
slug: "vote",
|
|
312
|
+
href: "https://vote.ochk.io",
|
|
313
|
+
label: "oc\xB7vote",
|
|
314
|
+
sub: "decide \u2014 polls",
|
|
315
|
+
docsHref: "https://docs.ochk.io/vote"
|
|
316
|
+
},
|
|
317
|
+
{
|
|
318
|
+
slug: "stamp",
|
|
319
|
+
href: "https://stamp.ochk.io",
|
|
320
|
+
label: "oc\xB7stamp",
|
|
321
|
+
sub: "declare \u2014 block-anchored",
|
|
322
|
+
docsHref: "https://docs.ochk.io/stamp"
|
|
323
|
+
},
|
|
324
|
+
{
|
|
325
|
+
slug: "agent",
|
|
326
|
+
href: "https://agent.ochk.io",
|
|
327
|
+
label: "oc\xB7agent",
|
|
328
|
+
sub: "delegate \u2014 scoped auth",
|
|
329
|
+
docsHref: "https://docs.ochk.io/agent"
|
|
330
|
+
},
|
|
331
|
+
{
|
|
332
|
+
slug: "pledge",
|
|
333
|
+
href: "https://pledge.ochk.io",
|
|
334
|
+
label: "oc\xB7pledge",
|
|
335
|
+
sub: "swear \u2014 bonded commitment",
|
|
336
|
+
docsHref: "https://docs.ochk.io/pledge"
|
|
337
|
+
}
|
|
338
|
+
];
|
|
339
|
+
var OWNER_ENTRIES = [
|
|
340
|
+
{
|
|
341
|
+
slug: "analytics",
|
|
342
|
+
href: "https://analytics.ochk.io",
|
|
343
|
+
label: "oc\xB7analytics",
|
|
344
|
+
sub: "owner cockpit",
|
|
345
|
+
docsHref: "https://analytics.ochk.io"
|
|
346
|
+
}
|
|
347
|
+
];
|
|
348
|
+
function EcosystemSwitcher({
|
|
349
|
+
current,
|
|
350
|
+
className,
|
|
351
|
+
showOwnerEntries = false
|
|
352
|
+
}) {
|
|
353
|
+
const [open, setOpen] = react.useState(false);
|
|
354
|
+
const containerRef = react.useRef(null);
|
|
355
|
+
react.useEffect(() => {
|
|
356
|
+
if (!open) return;
|
|
357
|
+
function onDoc(e) {
|
|
358
|
+
if (!containerRef.current) return;
|
|
359
|
+
if (!containerRef.current.contains(e.target)) setOpen(false);
|
|
360
|
+
}
|
|
361
|
+
function onKey(e) {
|
|
362
|
+
if (e.key === "Escape") setOpen(false);
|
|
363
|
+
}
|
|
364
|
+
document.addEventListener("mousedown", onDoc);
|
|
365
|
+
document.addEventListener("keydown", onKey);
|
|
366
|
+
return () => {
|
|
367
|
+
document.removeEventListener("mousedown", onDoc);
|
|
368
|
+
document.removeEventListener("keydown", onKey);
|
|
369
|
+
};
|
|
370
|
+
}, [open]);
|
|
371
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: containerRef, className: "relative " + (className ?? ""), children: [
|
|
372
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
373
|
+
"button",
|
|
374
|
+
{
|
|
375
|
+
type: "button",
|
|
376
|
+
"aria-haspopup": "menu",
|
|
377
|
+
"aria-expanded": open,
|
|
378
|
+
"aria-label": "Switch OrangeCheck product",
|
|
379
|
+
title: "Switch product",
|
|
380
|
+
onClick: () => setOpen((v) => !v),
|
|
381
|
+
className: "inline-flex items-center gap-1 px-2 py-1 transition-colors " + (open ? "text-foreground" : "text-muted-foreground hover:text-foreground"),
|
|
382
|
+
children: [
|
|
383
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Boxes, { className: "h-4 w-4" }),
|
|
384
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
385
|
+
lucideReact.ChevronDown,
|
|
386
|
+
{
|
|
387
|
+
className: "h-3.5 w-3.5 transition-transform " + (open ? "rotate-180" : "")
|
|
388
|
+
}
|
|
389
|
+
)
|
|
390
|
+
]
|
|
391
|
+
}
|
|
392
|
+
),
|
|
393
|
+
open && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
394
|
+
"div",
|
|
395
|
+
{
|
|
396
|
+
role: "menu",
|
|
397
|
+
"aria-label": "Switch OrangeCheck product",
|
|
398
|
+
className: "bg-background absolute right-0 top-full z-[60] mt-2 w-72 border shadow-lg",
|
|
399
|
+
children: [
|
|
400
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "label-mono text-primary border-b px-4 py-2", children: "\xA7 the family" }),
|
|
401
|
+
/* @__PURE__ */ jsxRuntime.jsx("ul", { className: "py-1", children: [...ENTRIES, ...showOwnerEntries ? OWNER_ENTRIES : []].map((e) => {
|
|
402
|
+
const isActive2 = e.slug === current;
|
|
403
|
+
return /* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
404
|
+
Link6__default.default,
|
|
405
|
+
{
|
|
406
|
+
href: e.href,
|
|
407
|
+
onClick: () => setOpen(false),
|
|
408
|
+
"aria-current": isActive2 ? "page" : void 0,
|
|
409
|
+
className: "group flex items-baseline gap-3 px-4 py-2 transition-colors " + (isActive2 ? "bg-primary/5" : "hover:bg-muted"),
|
|
410
|
+
children: [
|
|
411
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
412
|
+
"span",
|
|
413
|
+
{
|
|
414
|
+
className: "font-display flex-1 text-[12px] font-semibold tracking-tight " + (isActive2 ? "text-primary" : "text-foreground group-hover:text-primary transition-colors"),
|
|
415
|
+
children: e.label
|
|
416
|
+
}
|
|
417
|
+
),
|
|
418
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground font-mono text-[10px] tracking-wider uppercase", children: e.sub }),
|
|
419
|
+
isActive2 && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "text-primary h-3 w-3" })
|
|
420
|
+
]
|
|
421
|
+
}
|
|
422
|
+
) }, e.slug);
|
|
423
|
+
}) }),
|
|
424
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-t px-4 py-2 font-mono text-[10px] tracking-widest uppercase", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
425
|
+
Link6__default.default,
|
|
426
|
+
{
|
|
427
|
+
href: "https://docs.ochk.io",
|
|
428
|
+
onClick: () => setOpen(false),
|
|
429
|
+
className: "text-muted-foreground hover:text-foreground inline-block transition-colors",
|
|
430
|
+
children: "docs.ochk.io \u2192"
|
|
431
|
+
}
|
|
432
|
+
) })
|
|
433
|
+
]
|
|
434
|
+
}
|
|
435
|
+
)
|
|
436
|
+
] });
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
// src/chrome/family-properties.ts
|
|
440
|
+
var FAMILY_PROPERTIES = [
|
|
441
|
+
{
|
|
442
|
+
slug: "home",
|
|
443
|
+
origin: "https://ochk.io",
|
|
444
|
+
hostname: "ochk.io",
|
|
445
|
+
label: "orangecheck",
|
|
446
|
+
sub: "umbrella \xB7 sign-in",
|
|
447
|
+
docsHref: "https://docs.ochk.io",
|
|
448
|
+
category: "hub"
|
|
449
|
+
},
|
|
450
|
+
{
|
|
451
|
+
slug: "docs",
|
|
452
|
+
origin: "https://docs.ochk.io",
|
|
453
|
+
hostname: "docs.ochk.io",
|
|
454
|
+
label: "oc\xB7docs",
|
|
455
|
+
sub: "unified reference",
|
|
456
|
+
docsHref: "https://docs.ochk.io",
|
|
457
|
+
category: "hub"
|
|
458
|
+
},
|
|
459
|
+
{
|
|
460
|
+
slug: "me",
|
|
461
|
+
origin: "https://me.ochk.io",
|
|
462
|
+
hostname: "me.ochk.io",
|
|
463
|
+
label: "oc\xB7me",
|
|
464
|
+
sub: "earn \u2014 consumer identity",
|
|
465
|
+
docsHref: "https://docs.ochk.io/me",
|
|
466
|
+
category: "product"
|
|
467
|
+
},
|
|
468
|
+
{
|
|
469
|
+
slug: "vault",
|
|
470
|
+
origin: "https://vault.ochk.io",
|
|
471
|
+
hostname: "vault.ochk.io",
|
|
472
|
+
label: "oc\xB7vault",
|
|
473
|
+
sub: "keep \u2014 encrypted secrets",
|
|
474
|
+
docsHref: "https://docs.ochk.io/vault",
|
|
475
|
+
category: "product"
|
|
476
|
+
},
|
|
477
|
+
{
|
|
478
|
+
slug: "fleet",
|
|
479
|
+
origin: "https://fleet.ochk.io",
|
|
480
|
+
hostname: "fleet.ochk.io",
|
|
481
|
+
label: "oc\xB7fleet",
|
|
482
|
+
sub: "managed \u2014 agent fleet",
|
|
483
|
+
docsHref: "https://docs.ochk.io/fleet",
|
|
484
|
+
category: "product"
|
|
485
|
+
},
|
|
486
|
+
{
|
|
487
|
+
slug: "attest",
|
|
488
|
+
origin: "https://attest.ochk.io",
|
|
489
|
+
hostname: "attest.ochk.io",
|
|
490
|
+
label: "oc\xB7attest",
|
|
491
|
+
sub: "am \u2014 sybil resistance",
|
|
492
|
+
docsHref: "https://docs.ochk.io/attest",
|
|
493
|
+
category: "protocol"
|
|
494
|
+
},
|
|
495
|
+
{
|
|
496
|
+
slug: "lock",
|
|
497
|
+
origin: "https://lock.ochk.io",
|
|
498
|
+
hostname: "lock.ochk.io",
|
|
499
|
+
label: "oc\xB7lock",
|
|
500
|
+
sub: "whisper \u2014 encryption",
|
|
501
|
+
docsHref: "https://docs.ochk.io/lock",
|
|
502
|
+
category: "protocol"
|
|
503
|
+
},
|
|
504
|
+
{
|
|
505
|
+
slug: "vote",
|
|
506
|
+
origin: "https://vote.ochk.io",
|
|
507
|
+
hostname: "vote.ochk.io",
|
|
508
|
+
label: "oc\xB7vote",
|
|
509
|
+
sub: "decide \u2014 polls",
|
|
510
|
+
docsHref: "https://docs.ochk.io/vote",
|
|
511
|
+
category: "protocol"
|
|
512
|
+
},
|
|
513
|
+
{
|
|
514
|
+
slug: "stamp",
|
|
515
|
+
origin: "https://stamp.ochk.io",
|
|
516
|
+
hostname: "stamp.ochk.io",
|
|
517
|
+
label: "oc\xB7stamp",
|
|
518
|
+
sub: "declare \u2014 block-anchored",
|
|
519
|
+
docsHref: "https://docs.ochk.io/stamp",
|
|
520
|
+
category: "protocol"
|
|
521
|
+
},
|
|
522
|
+
{
|
|
523
|
+
slug: "agent",
|
|
524
|
+
origin: "https://agent.ochk.io",
|
|
525
|
+
hostname: "agent.ochk.io",
|
|
526
|
+
label: "oc\xB7agent",
|
|
527
|
+
sub: "delegate \u2014 scoped auth",
|
|
528
|
+
docsHref: "https://docs.ochk.io/agent",
|
|
529
|
+
category: "protocol"
|
|
530
|
+
},
|
|
531
|
+
{
|
|
532
|
+
slug: "pledge",
|
|
533
|
+
origin: "https://pledge.ochk.io",
|
|
534
|
+
hostname: "pledge.ochk.io",
|
|
535
|
+
label: "oc\xB7pledge",
|
|
536
|
+
sub: "swear \u2014 bonded commitment",
|
|
537
|
+
docsHref: "https://docs.ochk.io/pledge",
|
|
538
|
+
category: "protocol"
|
|
539
|
+
},
|
|
540
|
+
{
|
|
541
|
+
slug: "analytics",
|
|
542
|
+
origin: "https://analytics.ochk.io",
|
|
543
|
+
hostname: "analytics.ochk.io",
|
|
544
|
+
label: "oc\xB7analytics",
|
|
545
|
+
sub: "owner cockpit",
|
|
546
|
+
docsHref: "https://analytics.ochk.io",
|
|
547
|
+
category: "owner"
|
|
548
|
+
}
|
|
549
|
+
];
|
|
550
|
+
var SITE_STATE_LABEL = {
|
|
551
|
+
alpha: "alpha",
|
|
552
|
+
beta: "beta"
|
|
553
|
+
};
|
|
554
|
+
function findFamilyProperty(slug) {
|
|
555
|
+
return FAMILY_PROPERTIES.find((p) => p.slug === slug);
|
|
556
|
+
}
|
|
557
|
+
var SECTIONS = [
|
|
558
|
+
{ category: "hub", label: "hub" },
|
|
559
|
+
{ category: "product", label: "products" },
|
|
560
|
+
{ category: "protocol", label: "protocols" },
|
|
561
|
+
{ category: "owner", label: "owner" }
|
|
562
|
+
];
|
|
563
|
+
function CategoryChip({ category }) {
|
|
564
|
+
if (category === "hub") return null;
|
|
565
|
+
const label = category === "product" ? "product" : category === "protocol" ? "protocol" : "owner";
|
|
566
|
+
const tone = category === "product" ? "border-primary/25 bg-primary/10 text-primary" : category === "protocol" ? "border-muted-foreground/20 bg-muted/40 text-muted-foreground/85" : "border-warning/30 bg-warning/10 text-warning";
|
|
567
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
568
|
+
"span",
|
|
569
|
+
{
|
|
570
|
+
"aria-label": category === "product" ? "commercial product" : category === "protocol" ? "protocol reference" : "owner-only surface",
|
|
571
|
+
className: "ml-1 hidden rounded-sm border px-1.5 py-[1px] font-mono text-[9px] font-medium tracking-widest uppercase sm:inline-block " + tone,
|
|
572
|
+
"data-oc-category": category,
|
|
573
|
+
children: label
|
|
574
|
+
}
|
|
575
|
+
);
|
|
576
|
+
}
|
|
577
|
+
function SiteStateBadge({ state }) {
|
|
578
|
+
if (state === "live") return null;
|
|
579
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
580
|
+
"span",
|
|
581
|
+
{
|
|
582
|
+
"aria-label": `site lifecycle: ${state}`,
|
|
583
|
+
className: "text-muted-foreground/70 ml-1 hidden font-mono text-[9px] font-medium tracking-widest uppercase sm:inline-block",
|
|
584
|
+
"data-oc-site-state": state,
|
|
585
|
+
children: SITE_STATE_LABEL[state]
|
|
586
|
+
}
|
|
587
|
+
);
|
|
588
|
+
}
|
|
589
|
+
function MenuCategoryChip({ category }) {
|
|
590
|
+
if (category === "hub") return null;
|
|
591
|
+
const label = category === "product" ? "pro" : category === "protocol" ? "spec" : "own";
|
|
592
|
+
const tone = category === "product" ? "bg-primary/10 text-primary" : category === "protocol" ? "bg-muted/60 text-muted-foreground/80" : "bg-warning/15 text-warning";
|
|
593
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
594
|
+
"span",
|
|
595
|
+
{
|
|
596
|
+
"aria-hidden": true,
|
|
597
|
+
className: "inline-block shrink-0 rounded-sm px-1 py-[1px] font-mono text-[9px] font-medium tracking-widest uppercase " + tone,
|
|
598
|
+
children: label
|
|
599
|
+
}
|
|
600
|
+
);
|
|
601
|
+
}
|
|
602
|
+
function OcLogoDropdown({
|
|
603
|
+
current,
|
|
604
|
+
homeHref = "/",
|
|
605
|
+
siteState = "live",
|
|
606
|
+
children,
|
|
607
|
+
className,
|
|
608
|
+
triggerClassName,
|
|
609
|
+
popoverClassName,
|
|
610
|
+
showOwnerEntries = false
|
|
611
|
+
}) {
|
|
612
|
+
const [open, setOpen] = react.useState(false);
|
|
613
|
+
const containerRef = react.useRef(null);
|
|
614
|
+
const menuId = react.useId();
|
|
615
|
+
const router$1 = router.useRouter();
|
|
616
|
+
const currentCategory = findFamilyProperty(current)?.category ?? "hub";
|
|
617
|
+
function handleTriggerClick(e) {
|
|
618
|
+
if (e.detail >= 2) {
|
|
619
|
+
e.preventDefault();
|
|
620
|
+
setOpen(false);
|
|
621
|
+
void router$1.push(homeHref);
|
|
622
|
+
return;
|
|
623
|
+
}
|
|
624
|
+
setOpen((v) => !v);
|
|
625
|
+
}
|
|
626
|
+
react.useEffect(() => {
|
|
627
|
+
if (!open) return;
|
|
628
|
+
function onDoc(e) {
|
|
629
|
+
if (!containerRef.current) return;
|
|
630
|
+
if (!containerRef.current.contains(e.target)) setOpen(false);
|
|
631
|
+
}
|
|
632
|
+
function onKey(e) {
|
|
633
|
+
if (e.key === "Escape") setOpen(false);
|
|
634
|
+
}
|
|
635
|
+
document.addEventListener("mousedown", onDoc);
|
|
636
|
+
document.addEventListener("keydown", onKey);
|
|
637
|
+
return () => {
|
|
638
|
+
document.removeEventListener("mousedown", onDoc);
|
|
639
|
+
document.removeEventListener("keydown", onKey);
|
|
640
|
+
};
|
|
641
|
+
}, [open]);
|
|
642
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
643
|
+
"div",
|
|
644
|
+
{
|
|
645
|
+
ref: containerRef,
|
|
646
|
+
className: "relative inline-flex items-center " + (className ?? ""),
|
|
647
|
+
"data-oc-logo-dropdown": "",
|
|
648
|
+
"data-oc-current-category": currentCategory,
|
|
649
|
+
"data-oc-site-state": siteState,
|
|
650
|
+
children: [
|
|
651
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
652
|
+
"button",
|
|
653
|
+
{
|
|
654
|
+
type: "button",
|
|
655
|
+
"aria-haspopup": "menu",
|
|
656
|
+
"aria-expanded": open,
|
|
657
|
+
"aria-controls": menuId,
|
|
658
|
+
"aria-label": "OrangeCheck family \xB7 click to open property menu, double-click to go home",
|
|
659
|
+
title: "single-click \xB7 family menu \xB7 double-click \xB7 go home",
|
|
660
|
+
onClick: handleTriggerClick,
|
|
661
|
+
className: triggerClassName ?? "group hover:bg-accent/30 -mx-1.5 -my-1 flex min-h-[40px] items-center gap-2 rounded-sm px-1.5 py-1 transition-colors " + (open ? "bg-accent/20" : ""),
|
|
662
|
+
"data-oc-logo-dropdown-trigger": "",
|
|
663
|
+
"data-oc-logo-dropdown-open": open ? "true" : "false",
|
|
664
|
+
children: [
|
|
665
|
+
children,
|
|
666
|
+
/* @__PURE__ */ jsxRuntime.jsx(CategoryChip, { category: currentCategory }),
|
|
667
|
+
/* @__PURE__ */ jsxRuntime.jsx(SiteStateBadge, { state: siteState }),
|
|
668
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
669
|
+
lucideReact.ChevronDown,
|
|
670
|
+
{
|
|
671
|
+
"aria-hidden": true,
|
|
672
|
+
className: "text-muted-foreground/70 group-hover:text-foreground/80 h-3.5 w-3.5 shrink-0 transition-transform duration-200 " + (open ? "rotate-180" : "")
|
|
673
|
+
}
|
|
674
|
+
)
|
|
675
|
+
]
|
|
676
|
+
}
|
|
677
|
+
),
|
|
678
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
679
|
+
Link6__default.default,
|
|
680
|
+
{
|
|
681
|
+
href: homeHref,
|
|
682
|
+
"aria-label": "go to " + homeHref + " (this site's home)",
|
|
683
|
+
onClick: () => setOpen(false),
|
|
684
|
+
tabIndex: open ? 0 : -1,
|
|
685
|
+
className: "hover:text-primary group/home -ml-1 hidden items-center gap-1 rounded-sm px-1.5 py-1 font-mono text-[9px] tracking-widest uppercase transition-all duration-200 sm:inline-flex " + (open ? "pointer-events-auto translate-x-0 text-muted-foreground/70 opacity-100 hover:bg-accent/30" : "pointer-events-none -translate-x-1 opacity-0"),
|
|
686
|
+
"data-oc-logo-dropdown-home-hint": "",
|
|
687
|
+
children: [
|
|
688
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
689
|
+
lucideReact.CornerDownLeft,
|
|
690
|
+
{
|
|
691
|
+
"aria-hidden": true,
|
|
692
|
+
className: "h-3 w-3 group-hover/home:text-primary " + (open ? "motion-safe:animate-pulse" : "")
|
|
693
|
+
}
|
|
694
|
+
),
|
|
695
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-primary/70 group-hover/home:text-primary", children: "home" })
|
|
696
|
+
]
|
|
697
|
+
}
|
|
698
|
+
),
|
|
699
|
+
open && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
700
|
+
"div",
|
|
701
|
+
{
|
|
702
|
+
id: menuId,
|
|
703
|
+
role: "menu",
|
|
704
|
+
"aria-label": "OrangeCheck family",
|
|
705
|
+
className: popoverClassName ?? "bg-background absolute top-full left-0 z-[60] mt-2 w-[min(20rem,calc(100vw-1rem))] border shadow-lg",
|
|
706
|
+
"data-oc-logo-dropdown-popover": "",
|
|
707
|
+
children: [
|
|
708
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "label-mono text-primary border-b px-4 py-2", children: "\xA7 the orangecheck family" }),
|
|
709
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "max-h-[min(28rem,70vh)] overflow-y-auto py-1", role: "none", children: SECTIONS.map(({ category, label }) => {
|
|
710
|
+
if (category === "owner" && !showOwnerEntries) return null;
|
|
711
|
+
const sectionEntries = FAMILY_PROPERTIES.filter(
|
|
712
|
+
(e) => e.category === category
|
|
713
|
+
);
|
|
714
|
+
if (sectionEntries.length === 0) return null;
|
|
715
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { role: "none", "data-oc-section": category, children: [
|
|
716
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
717
|
+
"div",
|
|
718
|
+
{
|
|
719
|
+
role: "separator",
|
|
720
|
+
"aria-hidden": true,
|
|
721
|
+
className: "text-muted-foreground/60 px-4 pt-2.5 pb-1 font-mono text-[9px] font-medium tracking-widest uppercase " + (category === "hub" ? "" : "border-t mt-1"),
|
|
722
|
+
children: label
|
|
723
|
+
}
|
|
724
|
+
),
|
|
725
|
+
/* @__PURE__ */ jsxRuntime.jsx("ul", { role: "none", className: "pb-1", children: sectionEntries.map((e) => {
|
|
726
|
+
const isActive2 = e.slug === current;
|
|
727
|
+
const href = isActive2 ? homeHref : e.origin;
|
|
728
|
+
return /* @__PURE__ */ jsxRuntime.jsx("li", { role: "none", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
729
|
+
Link6__default.default,
|
|
730
|
+
{
|
|
731
|
+
href,
|
|
732
|
+
role: "menuitem",
|
|
733
|
+
onClick: () => setOpen(false),
|
|
734
|
+
"aria-current": isActive2 ? "page" : void 0,
|
|
735
|
+
className: "group flex items-center gap-2 px-4 py-2 transition-colors " + (isActive2 ? "bg-primary/8 border-primary -ml-px border-l-2" : "hover:bg-muted -ml-px border-l-2 border-transparent"),
|
|
736
|
+
"data-oc-logo-dropdown-item": isActive2 ? "current" : "sibling",
|
|
737
|
+
"data-oc-entry-category": e.category,
|
|
738
|
+
children: [
|
|
739
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex min-w-0 flex-1 flex-col leading-tight", children: [
|
|
740
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
741
|
+
"span",
|
|
742
|
+
{
|
|
743
|
+
className: "font-display text-[12px] font-semibold tracking-tight " + (isActive2 ? "text-primary" : "text-foreground group-hover:text-primary transition-colors"),
|
|
744
|
+
children: e.label
|
|
745
|
+
}
|
|
746
|
+
),
|
|
747
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground mt-0.5 font-mono text-[10px] tracking-wide", children: e.sub })
|
|
748
|
+
] }),
|
|
749
|
+
/* @__PURE__ */ jsxRuntime.jsx(MenuCategoryChip, { category: e.category }),
|
|
750
|
+
isActive2 ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-primary inline-flex shrink-0 items-center gap-1 font-mono text-[10px] tracking-widest uppercase", children: [
|
|
751
|
+
"home",
|
|
752
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "h-3 w-3" })
|
|
753
|
+
] }) : null
|
|
754
|
+
]
|
|
755
|
+
}
|
|
756
|
+
) }, e.slug);
|
|
757
|
+
}) })
|
|
758
|
+
] }, category);
|
|
759
|
+
}) }),
|
|
760
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-t px-4 py-2 font-mono text-[10px] tracking-widest uppercase", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
761
|
+
Link6__default.default,
|
|
762
|
+
{
|
|
763
|
+
href: "https://docs.ochk.io",
|
|
764
|
+
onClick: () => setOpen(false),
|
|
765
|
+
className: "text-muted-foreground hover:text-foreground inline-block transition-colors",
|
|
766
|
+
children: "docs.ochk.io \u2192"
|
|
767
|
+
}
|
|
768
|
+
) })
|
|
769
|
+
]
|
|
770
|
+
}
|
|
771
|
+
)
|
|
772
|
+
]
|
|
773
|
+
}
|
|
774
|
+
);
|
|
775
|
+
}
|
|
776
|
+
function obscureIdentity(value) {
|
|
777
|
+
if (value.length <= 12) {
|
|
778
|
+
return `${value.slice(0, 4)}\u2026${value.slice(-3)}`;
|
|
779
|
+
}
|
|
780
|
+
return `${value.slice(0, 6)}\u2026${value.slice(-4)}`;
|
|
781
|
+
}
|
|
782
|
+
var IDENTITY_KIND_LABEL = {
|
|
783
|
+
did: "did:oc",
|
|
784
|
+
btc: "bitcoin",
|
|
785
|
+
email: "email",
|
|
786
|
+
nostr: "nostr"
|
|
787
|
+
};
|
|
788
|
+
async function writeClipboard(text) {
|
|
789
|
+
try {
|
|
790
|
+
if (navigator.clipboard?.writeText) {
|
|
791
|
+
await navigator.clipboard.writeText(text);
|
|
792
|
+
return true;
|
|
793
|
+
}
|
|
794
|
+
} catch {
|
|
795
|
+
}
|
|
796
|
+
try {
|
|
797
|
+
const ta = document.createElement("textarea");
|
|
798
|
+
ta.value = text;
|
|
799
|
+
ta.setAttribute("readonly", "");
|
|
800
|
+
ta.style.position = "fixed";
|
|
801
|
+
ta.style.top = "-1000px";
|
|
802
|
+
ta.style.opacity = "0";
|
|
803
|
+
document.body.appendChild(ta);
|
|
804
|
+
ta.select();
|
|
805
|
+
const ok = document.execCommand("copy");
|
|
806
|
+
document.body.removeChild(ta);
|
|
807
|
+
return ok;
|
|
808
|
+
} catch {
|
|
809
|
+
return false;
|
|
810
|
+
}
|
|
811
|
+
}
|
|
812
|
+
function CopyableDid({ did }) {
|
|
813
|
+
const [copied, setCopied] = react.useState(false);
|
|
814
|
+
const timerRef = react.useRef(null);
|
|
815
|
+
react.useEffect(
|
|
816
|
+
() => () => {
|
|
817
|
+
if (timerRef.current) clearTimeout(timerRef.current);
|
|
818
|
+
},
|
|
819
|
+
[]
|
|
820
|
+
);
|
|
821
|
+
const onCopy = async () => {
|
|
822
|
+
const ok = await writeClipboard(did);
|
|
823
|
+
if (!ok) return;
|
|
824
|
+
setCopied(true);
|
|
825
|
+
if (timerRef.current) clearTimeout(timerRef.current);
|
|
826
|
+
timerRef.current = setTimeout(() => setCopied(false), 1600);
|
|
827
|
+
};
|
|
828
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
829
|
+
"button",
|
|
830
|
+
{
|
|
831
|
+
type: "button",
|
|
832
|
+
onClick: onCopy,
|
|
833
|
+
"aria-label": copied ? "OrangeCheck identity copied to clipboard" : `Copy OrangeCheck identity ${did} to clipboard`,
|
|
834
|
+
title: "Copy identity",
|
|
835
|
+
"data-oc-account-menu-copy-did": "",
|
|
836
|
+
"data-copied": copied ? "" : void 0,
|
|
837
|
+
className: "group/did hover:bg-accent focus-visible:ring-ring/60 -mx-1.5 mt-px flex w-[calc(100%+0.75rem)] items-start gap-1.5 rounded px-1.5 py-1 text-left transition-colors focus-visible:ring-2 focus-visible:outline-none",
|
|
838
|
+
children: [
|
|
839
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-foreground/90 min-w-0 flex-1 font-mono text-[11px] leading-tight break-all", children: did }),
|
|
840
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
841
|
+
"span",
|
|
842
|
+
{
|
|
843
|
+
className: "mt-px shrink-0 transition-colors " + (copied ? "text-primary" : "text-muted-foreground/50 group-hover/did:text-foreground/80"),
|
|
844
|
+
"aria-hidden": true,
|
|
845
|
+
children: copied ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "size-3.5" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Copy, { className: "size-3.5" })
|
|
846
|
+
}
|
|
847
|
+
),
|
|
848
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", "aria-live": "polite", children: copied ? "Copied to clipboard" : "" })
|
|
849
|
+
]
|
|
850
|
+
}
|
|
851
|
+
);
|
|
852
|
+
}
|
|
853
|
+
function PromoteRow({
|
|
854
|
+
kind,
|
|
855
|
+
value,
|
|
856
|
+
active,
|
|
857
|
+
busy,
|
|
858
|
+
disabled,
|
|
859
|
+
onPromote
|
|
860
|
+
}) {
|
|
861
|
+
const [copied, setCopied] = react.useState(false);
|
|
862
|
+
const timerRef = react.useRef(null);
|
|
863
|
+
react.useEffect(
|
|
864
|
+
() => () => {
|
|
865
|
+
if (timerRef.current) clearTimeout(timerRef.current);
|
|
866
|
+
},
|
|
867
|
+
[]
|
|
868
|
+
);
|
|
869
|
+
const onCopy = async () => {
|
|
870
|
+
const ok = await writeClipboard(value);
|
|
871
|
+
if (!ok) return;
|
|
872
|
+
setCopied(true);
|
|
873
|
+
if (timerRef.current) clearTimeout(timerRef.current);
|
|
874
|
+
timerRef.current = setTimeout(() => setCopied(false), 1600);
|
|
875
|
+
};
|
|
876
|
+
const kindLabel = IDENTITY_KIND_LABEL[kind];
|
|
877
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
878
|
+
"div",
|
|
879
|
+
{
|
|
880
|
+
className: "hover:bg-accent flex items-center gap-1 pr-2 transition-colors",
|
|
881
|
+
"data-oc-account-menu-promote-row": kind,
|
|
882
|
+
"data-active": active ? "" : void 0,
|
|
883
|
+
children: [
|
|
884
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
885
|
+
"button",
|
|
886
|
+
{
|
|
887
|
+
type: "button",
|
|
888
|
+
role: "menuitemradio",
|
|
889
|
+
"aria-checked": active,
|
|
890
|
+
"aria-label": active ? `Showing as ${kindLabel}` : `Show as ${kindLabel}`,
|
|
891
|
+
disabled: disabled || active,
|
|
892
|
+
onClick: onPromote,
|
|
893
|
+
"data-oc-account-menu-promote": kind,
|
|
894
|
+
className: "flex min-w-0 flex-1 items-center gap-2 py-2 pl-3 text-left font-mono text-[11px] tracking-wide disabled:cursor-default",
|
|
895
|
+
children: [
|
|
896
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
897
|
+
"span",
|
|
898
|
+
{
|
|
899
|
+
className: "flex size-3.5 shrink-0 items-center justify-center rounded-full border " + (active ? "border-primary" : "border-muted-foreground/40"),
|
|
900
|
+
"aria-hidden": true,
|
|
901
|
+
children: active ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "bg-primary size-1.5 rounded-full" }) : null
|
|
902
|
+
}
|
|
903
|
+
),
|
|
904
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-foreground/90 min-w-0 flex-1 truncate", children: obscureIdentity(value) })
|
|
905
|
+
]
|
|
906
|
+
}
|
|
907
|
+
),
|
|
908
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
909
|
+
"button",
|
|
910
|
+
{
|
|
911
|
+
type: "button",
|
|
912
|
+
onClick: () => void onCopy(),
|
|
913
|
+
"aria-label": copied ? `${kindLabel} copied to clipboard` : `Copy ${kindLabel} to clipboard`,
|
|
914
|
+
title: "Copy",
|
|
915
|
+
"data-oc-account-menu-promote-copy": kind,
|
|
916
|
+
"data-copied": copied ? "" : void 0,
|
|
917
|
+
className: "hover:bg-background/70 focus-visible:ring-ring/60 flex size-6 shrink-0 items-center justify-center rounded transition-colors focus-visible:ring-2 focus-visible:outline-none",
|
|
918
|
+
children: copied ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "text-primary size-3.5" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Copy, { className: "text-muted-foreground/50 size-3.5" })
|
|
919
|
+
}
|
|
920
|
+
),
|
|
921
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground/50 w-14 shrink-0 text-right text-[9px] tracking-widest uppercase", children: busy ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "ml-auto size-3 animate-spin" }) : kindLabel }),
|
|
922
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", "aria-live": "polite", children: copied ? "Copied to clipboard" : "" })
|
|
923
|
+
]
|
|
924
|
+
}
|
|
925
|
+
);
|
|
926
|
+
}
|
|
927
|
+
function IdentityPromoteSection({
|
|
928
|
+
didOc,
|
|
929
|
+
nostrNpub,
|
|
930
|
+
current,
|
|
931
|
+
open,
|
|
932
|
+
setDisplayIdentity
|
|
933
|
+
}) {
|
|
934
|
+
const [identities, setIdentities] = react.useState(null);
|
|
935
|
+
const [loadFailed, setLoadFailed] = react.useState(false);
|
|
936
|
+
const [promoting, setPromoting] = react.useState(null);
|
|
937
|
+
const [promoteErr, setPromoteErr] = react.useState(null);
|
|
938
|
+
const lastFetchKeyRef = react.useRef(null);
|
|
939
|
+
react.useEffect(() => {
|
|
940
|
+
if (!open) return;
|
|
941
|
+
if (lastFetchKeyRef.current === didOc) return;
|
|
942
|
+
lastFetchKeyRef.current = didOc;
|
|
943
|
+
let cancelled = false;
|
|
944
|
+
setIdentities(null);
|
|
945
|
+
setLoadFailed(false);
|
|
946
|
+
void authClient.fetchOcLinkedIdentities().then((rows) => {
|
|
947
|
+
if (!cancelled) setIdentities(rows);
|
|
948
|
+
}).catch(() => {
|
|
949
|
+
if (!cancelled) setLoadFailed(true);
|
|
950
|
+
});
|
|
951
|
+
return () => {
|
|
952
|
+
cancelled = true;
|
|
953
|
+
};
|
|
954
|
+
}, [open, didOc]);
|
|
955
|
+
if (identities === null && !loadFailed) return null;
|
|
956
|
+
const btc = identities?.find((i) => i.kind === "btc" && i.is_primary && i.value) ?? identities?.find((i) => i.kind === "btc" && i.value);
|
|
957
|
+
const email = identities?.find((i) => i.kind === "email" && i.is_primary && i.value) ?? identities?.find((i) => i.kind === "email" && i.value);
|
|
958
|
+
const options = [
|
|
959
|
+
{ kind: "did", value: didOc }
|
|
960
|
+
];
|
|
961
|
+
if (btc?.value) options.push({ kind: "btc", value: btc.value });
|
|
962
|
+
if (email?.value) options.push({ kind: "email", value: email.value });
|
|
963
|
+
if (nostrNpub) options.push({ kind: "nostr", value: nostrNpub });
|
|
964
|
+
if (options.length < 2) return null;
|
|
965
|
+
const promote = async (kind) => {
|
|
966
|
+
if (promoting || kind === current.kind) return;
|
|
967
|
+
setPromoting(kind);
|
|
968
|
+
setPromoteErr(null);
|
|
969
|
+
try {
|
|
970
|
+
await setDisplayIdentity(kind);
|
|
971
|
+
} catch (e) {
|
|
972
|
+
setPromoteErr(e instanceof Error ? e.message : "promotion failed");
|
|
973
|
+
} finally {
|
|
974
|
+
setPromoting(null);
|
|
975
|
+
}
|
|
976
|
+
};
|
|
977
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-border border-b p-1", "data-oc-account-menu-section": "show-as", children: [
|
|
978
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-muted-foreground/60 px-3 pt-2 pb-1 font-mono text-[10px] tracking-widest uppercase", children: "\xA7 show as" }),
|
|
979
|
+
options.map((opt) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
980
|
+
PromoteRow,
|
|
981
|
+
{
|
|
982
|
+
kind: opt.kind,
|
|
983
|
+
value: opt.value,
|
|
984
|
+
active: opt.kind === current.kind,
|
|
985
|
+
busy: promoting === opt.kind,
|
|
986
|
+
disabled: promoting !== null,
|
|
987
|
+
onPromote: () => void promote(opt.kind)
|
|
988
|
+
},
|
|
989
|
+
opt.kind
|
|
990
|
+
)),
|
|
991
|
+
promoteErr ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-destructive/80 px-3 pt-1 pb-2 font-mono text-[10px]", children: promoteErr }) : null
|
|
992
|
+
] });
|
|
993
|
+
}
|
|
994
|
+
function OcAccountMenu(props) {
|
|
995
|
+
const session = authClient.useOcSession();
|
|
996
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
997
|
+
OcAccountMenuView,
|
|
998
|
+
{
|
|
999
|
+
...props,
|
|
1000
|
+
session: {
|
|
1001
|
+
status: session.status,
|
|
1002
|
+
account: session.account ? {
|
|
1003
|
+
didOc: session.account.didOc,
|
|
1004
|
+
displayName: session.account.displayName ?? null,
|
|
1005
|
+
displayIdentity: session.account.displayIdentity,
|
|
1006
|
+
nostrNpub: session.account.nostrNpub ?? null
|
|
1007
|
+
} : null,
|
|
1008
|
+
signOut: session.signOut,
|
|
1009
|
+
refresh: session.refresh,
|
|
1010
|
+
setDisplayIdentity: session.setDisplayIdentity,
|
|
1011
|
+
// Multi-account · the connected variant always forwards
|
|
1012
|
+
// these from useOcSession(). The View variant accepts
|
|
1013
|
+
// them as optional so sites running their own auth
|
|
1014
|
+
// context (oc-www) can opt in incrementally.
|
|
1015
|
+
roster: session.roster,
|
|
1016
|
+
switchAccount: session.switchAccount,
|
|
1017
|
+
addAccountUrl: session.addAccountUrl
|
|
1018
|
+
}
|
|
1019
|
+
}
|
|
1020
|
+
);
|
|
1021
|
+
}
|
|
1022
|
+
function OcAccountMenuView({
|
|
1023
|
+
current,
|
|
1024
|
+
signInUrl = "/signin",
|
|
1025
|
+
signInLabel = "sign in",
|
|
1026
|
+
signOutRedirect = "/",
|
|
1027
|
+
menuItems,
|
|
1028
|
+
primaryNavLinks,
|
|
1029
|
+
secondaryNavLinks,
|
|
1030
|
+
showFamilyDashboard,
|
|
1031
|
+
build,
|
|
1032
|
+
siteState,
|
|
1033
|
+
className,
|
|
1034
|
+
triggerClassName,
|
|
1035
|
+
popoverClassName,
|
|
1036
|
+
session
|
|
1037
|
+
}) {
|
|
1038
|
+
const {
|
|
1039
|
+
status,
|
|
1040
|
+
account,
|
|
1041
|
+
signOut,
|
|
1042
|
+
refresh,
|
|
1043
|
+
setDisplayIdentity,
|
|
1044
|
+
roster,
|
|
1045
|
+
switchAccount,
|
|
1046
|
+
addAccountUrl
|
|
1047
|
+
} = session;
|
|
1048
|
+
const [hydrated, setHydrated] = react.useState(false);
|
|
1049
|
+
const [open, setOpen] = react.useState(false);
|
|
1050
|
+
const wrapRef = react.useRef(null);
|
|
1051
|
+
const property = findFamilyProperty(current);
|
|
1052
|
+
const hostname = property?.hostname ?? `${current}.ochk.io`;
|
|
1053
|
+
const isHome = current === "home";
|
|
1054
|
+
const familyDashboardEnabled = showFamilyDashboard ?? !isHome;
|
|
1055
|
+
react.useEffect(() => setHydrated(true), []);
|
|
1056
|
+
react.useEffect(() => {
|
|
1057
|
+
const onWake = () => {
|
|
1058
|
+
if (document.visibilityState === "visible") void refresh();
|
|
1059
|
+
};
|
|
1060
|
+
const onFocus = () => void refresh();
|
|
1061
|
+
document.addEventListener("visibilitychange", onWake);
|
|
1062
|
+
window.addEventListener("focus", onFocus);
|
|
1063
|
+
return () => {
|
|
1064
|
+
document.removeEventListener("visibilitychange", onWake);
|
|
1065
|
+
window.removeEventListener("focus", onFocus);
|
|
1066
|
+
};
|
|
1067
|
+
}, [refresh]);
|
|
1068
|
+
react.useEffect(() => {
|
|
1069
|
+
if (!open) return;
|
|
1070
|
+
const onClick = (e) => {
|
|
1071
|
+
if (wrapRef.current && !wrapRef.current.contains(e.target)) setOpen(false);
|
|
1072
|
+
};
|
|
1073
|
+
const onKey = (e) => {
|
|
1074
|
+
if (e.key === "Escape") setOpen(false);
|
|
1075
|
+
};
|
|
1076
|
+
document.addEventListener("mousedown", onClick);
|
|
1077
|
+
document.addEventListener("keydown", onKey);
|
|
1078
|
+
return () => {
|
|
1079
|
+
document.removeEventListener("mousedown", onClick);
|
|
1080
|
+
document.removeEventListener("keydown", onKey);
|
|
1081
|
+
};
|
|
1082
|
+
}, [open]);
|
|
1083
|
+
const signInTrigger = /* @__PURE__ */ jsxRuntime.jsx(
|
|
1084
|
+
"a",
|
|
1085
|
+
{
|
|
1086
|
+
href: signInUrl,
|
|
1087
|
+
"aria-label": signInLabel,
|
|
1088
|
+
"data-oc-account-menu-signin": "",
|
|
1089
|
+
className: triggerClassName ?? "border-input bg-background hover:bg-accent inline-flex h-8 items-center justify-center rounded-md border px-3 font-mono text-[11px] font-semibold tracking-widest uppercase transition-colors",
|
|
1090
|
+
children: signInLabel
|
|
1091
|
+
}
|
|
1092
|
+
);
|
|
1093
|
+
if (!hydrated || status === "loading") {
|
|
1094
|
+
return signInTrigger;
|
|
1095
|
+
}
|
|
1096
|
+
if (status !== "authenticated" || !account) {
|
|
1097
|
+
return signInTrigger;
|
|
1098
|
+
}
|
|
1099
|
+
const displayName = account.displayName ?? null;
|
|
1100
|
+
const label = displayName ?? obscureIdentity(account.displayIdentity.value);
|
|
1101
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1102
|
+
"div",
|
|
1103
|
+
{
|
|
1104
|
+
ref: wrapRef,
|
|
1105
|
+
className: "relative inline-block " + (className ?? ""),
|
|
1106
|
+
"data-oc-account-menu": "",
|
|
1107
|
+
children: [
|
|
1108
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1109
|
+
"button",
|
|
1110
|
+
{
|
|
1111
|
+
type: "button",
|
|
1112
|
+
onClick: () => setOpen((v) => !v),
|
|
1113
|
+
"aria-haspopup": "menu",
|
|
1114
|
+
"aria-expanded": open,
|
|
1115
|
+
"aria-label": `Signed in as ${account.didOc}. Open account menu.`,
|
|
1116
|
+
className: triggerClassName ?? "border-primary/40 bg-card hover:bg-accent inline-flex h-8 items-center gap-1.5 rounded-md border px-3 font-mono text-[11px] tracking-wide transition-colors",
|
|
1117
|
+
"data-oc-account-menu-trigger": "",
|
|
1118
|
+
children: [
|
|
1119
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "bg-primary inline-block size-1.5 rounded-full", "aria-hidden": true }),
|
|
1120
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-foreground", children: label }),
|
|
1121
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1122
|
+
"svg",
|
|
1123
|
+
{
|
|
1124
|
+
width: "9",
|
|
1125
|
+
height: "9",
|
|
1126
|
+
viewBox: "0 0 10 10",
|
|
1127
|
+
"aria-hidden": true,
|
|
1128
|
+
className: "opacity-60 transition-transform " + (open ? "rotate-180" : "rotate-0"),
|
|
1129
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1130
|
+
"path",
|
|
1131
|
+
{
|
|
1132
|
+
d: "M2 4 L5 7 L8 4",
|
|
1133
|
+
stroke: "currentColor",
|
|
1134
|
+
strokeWidth: "1.5",
|
|
1135
|
+
fill: "none",
|
|
1136
|
+
strokeLinecap: "round"
|
|
1137
|
+
}
|
|
1138
|
+
)
|
|
1139
|
+
}
|
|
1140
|
+
)
|
|
1141
|
+
]
|
|
1142
|
+
}
|
|
1143
|
+
),
|
|
1144
|
+
open && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1145
|
+
"div",
|
|
1146
|
+
{
|
|
1147
|
+
role: "menu",
|
|
1148
|
+
"aria-label": "Account menu",
|
|
1149
|
+
className: popoverClassName ?? "border-border bg-popover text-popover-foreground absolute top-[calc(100%+6px)] right-0 z-50 w-[min(20rem,calc(100vw-1rem))] border shadow-xl",
|
|
1150
|
+
"data-oc-account-menu-popover": "",
|
|
1151
|
+
children: [
|
|
1152
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-border border-b p-3", children: [
|
|
1153
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-primary mb-1 font-mono text-[10px] tracking-widest uppercase", children: [
|
|
1154
|
+
"\xA7 signed in \xB7 ",
|
|
1155
|
+
hostname
|
|
1156
|
+
] }),
|
|
1157
|
+
/* @__PURE__ */ jsxRuntime.jsx(CopyableDid, { did: account.didOc }),
|
|
1158
|
+
displayName ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-muted-foreground/80 mt-1 font-mono text-[10px] tracking-wide", children: displayName }) : null
|
|
1159
|
+
] }),
|
|
1160
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1161
|
+
IdentityPromoteSection,
|
|
1162
|
+
{
|
|
1163
|
+
didOc: account.didOc,
|
|
1164
|
+
nostrNpub: account.nostrNpub ?? null,
|
|
1165
|
+
current: account.displayIdentity,
|
|
1166
|
+
open,
|
|
1167
|
+
setDisplayIdentity
|
|
1168
|
+
}
|
|
1169
|
+
),
|
|
1170
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1171
|
+
AccountsSection,
|
|
1172
|
+
{
|
|
1173
|
+
roster: roster ?? [],
|
|
1174
|
+
switchAccount,
|
|
1175
|
+
addAccountUrl,
|
|
1176
|
+
signOut,
|
|
1177
|
+
onActionStart: () => setOpen(false)
|
|
1178
|
+
}
|
|
1179
|
+
),
|
|
1180
|
+
primaryNavLinks && primaryNavLinks.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1181
|
+
PopoverSection,
|
|
1182
|
+
{
|
|
1183
|
+
label: "navigate",
|
|
1184
|
+
items: primaryNavLinks,
|
|
1185
|
+
onItemClick: () => setOpen(false)
|
|
1186
|
+
}
|
|
1187
|
+
) : null,
|
|
1188
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-1", "data-oc-account-menu-section": "account", children: [
|
|
1189
|
+
primaryNavLinks && primaryNavLinks.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-muted-foreground/60 px-3 pb-1 pt-2 font-mono text-[10px] tracking-widest uppercase", children: "\xA7 account" }) : null,
|
|
1190
|
+
menuItems?.map((item) => {
|
|
1191
|
+
const onClick = () => setOpen(false);
|
|
1192
|
+
const cls = "hover:bg-accent flex items-center gap-2 px-3 py-2 font-mono text-[11px] tracking-wide transition-colors";
|
|
1193
|
+
const inner = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1194
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", "aria-hidden": true, children: "\u2192" }),
|
|
1195
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1", children: item.label }),
|
|
1196
|
+
item.external ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1197
|
+
"span",
|
|
1198
|
+
{
|
|
1199
|
+
className: "text-muted-foreground/70 text-[10px]",
|
|
1200
|
+
"aria-hidden": true,
|
|
1201
|
+
children: "\u2197"
|
|
1202
|
+
}
|
|
1203
|
+
) : null
|
|
1204
|
+
] });
|
|
1205
|
+
return item.external ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1206
|
+
"a",
|
|
1207
|
+
{
|
|
1208
|
+
href: item.href,
|
|
1209
|
+
target: "_blank",
|
|
1210
|
+
rel: "noreferrer",
|
|
1211
|
+
onClick,
|
|
1212
|
+
role: "menuitem",
|
|
1213
|
+
className: cls,
|
|
1214
|
+
"data-oc-account-menu-item": "",
|
|
1215
|
+
children: inner
|
|
1216
|
+
},
|
|
1217
|
+
item.href
|
|
1218
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
1219
|
+
Link6__default.default,
|
|
1220
|
+
{
|
|
1221
|
+
href: item.href,
|
|
1222
|
+
onClick,
|
|
1223
|
+
role: "menuitem",
|
|
1224
|
+
className: cls,
|
|
1225
|
+
"data-oc-account-menu-item": "",
|
|
1226
|
+
children: inner
|
|
1227
|
+
},
|
|
1228
|
+
item.href
|
|
1229
|
+
);
|
|
1230
|
+
}),
|
|
1231
|
+
familyDashboardEnabled ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1232
|
+
"a",
|
|
1233
|
+
{
|
|
1234
|
+
href: "https://ochk.io/dashboard",
|
|
1235
|
+
target: "_blank",
|
|
1236
|
+
rel: "noreferrer",
|
|
1237
|
+
onClick: () => setOpen(false),
|
|
1238
|
+
role: "menuitem",
|
|
1239
|
+
className: "hover:bg-accent flex items-center gap-2 px-3 py-2 font-mono text-[11px] tracking-wide transition-colors",
|
|
1240
|
+
"data-oc-account-menu-item": "",
|
|
1241
|
+
"data-oc-account-menu-family-dashboard": "",
|
|
1242
|
+
children: [
|
|
1243
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", "aria-hidden": true, children: "\u2192" }),
|
|
1244
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1", children: "family dashboard" }),
|
|
1245
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1246
|
+
"span",
|
|
1247
|
+
{
|
|
1248
|
+
className: "text-muted-foreground/70 text-[10px]",
|
|
1249
|
+
"aria-hidden": true,
|
|
1250
|
+
children: "\u2197"
|
|
1251
|
+
}
|
|
1252
|
+
)
|
|
1253
|
+
]
|
|
1254
|
+
}
|
|
1255
|
+
) : null,
|
|
1256
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1257
|
+
"button",
|
|
1258
|
+
{
|
|
1259
|
+
type: "button",
|
|
1260
|
+
role: "menuitem",
|
|
1261
|
+
onClick: () => {
|
|
1262
|
+
setOpen(false);
|
|
1263
|
+
void (async () => {
|
|
1264
|
+
await signOut();
|
|
1265
|
+
if (typeof window !== "undefined") {
|
|
1266
|
+
window.location.assign(signOutRedirect);
|
|
1267
|
+
}
|
|
1268
|
+
})();
|
|
1269
|
+
},
|
|
1270
|
+
className: "hover:bg-accent flex w-full items-center gap-2 px-3 py-2 text-left font-mono text-[11px] tracking-wide transition-colors",
|
|
1271
|
+
"data-oc-account-menu-item": "",
|
|
1272
|
+
"data-oc-account-menu-signout": "",
|
|
1273
|
+
children: [
|
|
1274
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", "aria-hidden": true, children: "\u2192" }),
|
|
1275
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1", children: "sign out" })
|
|
1276
|
+
]
|
|
1277
|
+
}
|
|
1278
|
+
)
|
|
1279
|
+
] }),
|
|
1280
|
+
secondaryNavLinks && secondaryNavLinks.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1281
|
+
PopoverSection,
|
|
1282
|
+
{
|
|
1283
|
+
label: "more",
|
|
1284
|
+
items: secondaryNavLinks,
|
|
1285
|
+
onItemClick: () => setOpen(false),
|
|
1286
|
+
bordered: true
|
|
1287
|
+
}
|
|
1288
|
+
) : null,
|
|
1289
|
+
build ? /* @__PURE__ */ jsxRuntime.jsx(BuildFooter, { hostname, build, state: siteState }) : null
|
|
1290
|
+
]
|
|
1291
|
+
}
|
|
1292
|
+
)
|
|
1293
|
+
]
|
|
1294
|
+
}
|
|
1295
|
+
);
|
|
1296
|
+
}
|
|
1297
|
+
function AccountsSection({
|
|
1298
|
+
roster,
|
|
1299
|
+
switchAccount,
|
|
1300
|
+
addAccountUrl,
|
|
1301
|
+
signOut,
|
|
1302
|
+
onActionStart
|
|
1303
|
+
}) {
|
|
1304
|
+
const [switching, setSwitching] = react.useState(null);
|
|
1305
|
+
const [err, setErr] = react.useState(null);
|
|
1306
|
+
if (!addAccountUrl) return null;
|
|
1307
|
+
const onSwitch = async (didOc) => {
|
|
1308
|
+
if (!switchAccount || switching) return;
|
|
1309
|
+
setSwitching(didOc);
|
|
1310
|
+
setErr(null);
|
|
1311
|
+
try {
|
|
1312
|
+
await switchAccount(didOc);
|
|
1313
|
+
} catch (e) {
|
|
1314
|
+
setErr(e instanceof Error ? e.message : "switch failed");
|
|
1315
|
+
} finally {
|
|
1316
|
+
setSwitching(null);
|
|
1317
|
+
}
|
|
1318
|
+
};
|
|
1319
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-border border-b p-1", "data-oc-account-menu-section": "accounts", children: [
|
|
1320
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-muted-foreground/60 px-3 pt-2 pb-1 font-mono text-[10px] tracking-widest uppercase", children: "\xA7 accounts" }),
|
|
1321
|
+
roster.map((peer) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
1322
|
+
SwitchRow,
|
|
1323
|
+
{
|
|
1324
|
+
peer,
|
|
1325
|
+
busy: switching === peer.didOc,
|
|
1326
|
+
disabled: switching !== null,
|
|
1327
|
+
onSwitch: () => void onSwitch(peer.didOc)
|
|
1328
|
+
},
|
|
1329
|
+
peer.didOc
|
|
1330
|
+
)),
|
|
1331
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1332
|
+
"a",
|
|
1333
|
+
{
|
|
1334
|
+
href: addAccountUrl(),
|
|
1335
|
+
onClick: () => onActionStart(),
|
|
1336
|
+
role: "menuitem",
|
|
1337
|
+
"data-oc-account-menu-add-account": "",
|
|
1338
|
+
className: "hover:bg-accent flex items-center gap-2 px-3 py-2 font-mono text-[11px] tracking-wide transition-colors",
|
|
1339
|
+
children: [
|
|
1340
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, { className: "text-muted-foreground size-3.5 shrink-0", "aria-hidden": true }),
|
|
1341
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1", children: roster.length === 0 ? "add another account" : "add another" })
|
|
1342
|
+
]
|
|
1343
|
+
}
|
|
1344
|
+
),
|
|
1345
|
+
roster.length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1346
|
+
"button",
|
|
1347
|
+
{
|
|
1348
|
+
type: "button",
|
|
1349
|
+
role: "menuitem",
|
|
1350
|
+
onClick: () => {
|
|
1351
|
+
onActionStart();
|
|
1352
|
+
void (async () => {
|
|
1353
|
+
try {
|
|
1354
|
+
await signOut({ scope: "current" });
|
|
1355
|
+
} catch {
|
|
1356
|
+
}
|
|
1357
|
+
})();
|
|
1358
|
+
},
|
|
1359
|
+
"data-oc-account-menu-leave-current": "",
|
|
1360
|
+
className: "hover:bg-accent flex w-full items-center gap-2 px-3 py-2 text-left font-mono text-[11px] tracking-wide transition-colors",
|
|
1361
|
+
children: [
|
|
1362
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", "aria-hidden": true, children: "\u2192" }),
|
|
1363
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1", children: "leave this account" })
|
|
1364
|
+
]
|
|
1365
|
+
}
|
|
1366
|
+
) : null,
|
|
1367
|
+
err ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-destructive/80 px-3 pt-1 pb-2 font-mono text-[10px]", children: err }) : null
|
|
1368
|
+
] });
|
|
1369
|
+
}
|
|
1370
|
+
function SwitchRow({
|
|
1371
|
+
peer,
|
|
1372
|
+
busy,
|
|
1373
|
+
disabled,
|
|
1374
|
+
onSwitch
|
|
1375
|
+
}) {
|
|
1376
|
+
const label = peer.displayName ?? obscureIdentity(peer.displayIdentity.value);
|
|
1377
|
+
const kindLabel = IDENTITY_KIND_LABEL[peer.displayIdentity.kind];
|
|
1378
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1379
|
+
"button",
|
|
1380
|
+
{
|
|
1381
|
+
type: "button",
|
|
1382
|
+
role: "menuitemradio",
|
|
1383
|
+
"aria-checked": false,
|
|
1384
|
+
"aria-label": `Switch to ${peer.didOc}`,
|
|
1385
|
+
disabled,
|
|
1386
|
+
onClick: onSwitch,
|
|
1387
|
+
"data-oc-account-menu-switch-row": "",
|
|
1388
|
+
className: "hover:bg-accent flex w-full items-center gap-2 px-3 py-2 text-left font-mono text-[11px] tracking-wide transition-colors disabled:cursor-default",
|
|
1389
|
+
children: [
|
|
1390
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1391
|
+
"span",
|
|
1392
|
+
{
|
|
1393
|
+
className: "border-muted-foreground/40 flex size-3.5 shrink-0 items-center justify-center rounded-full border",
|
|
1394
|
+
"aria-hidden": true
|
|
1395
|
+
}
|
|
1396
|
+
),
|
|
1397
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-foreground/90 min-w-0 flex-1 truncate", children: label }),
|
|
1398
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground/50 w-14 shrink-0 text-right text-[9px] tracking-widest uppercase", children: busy ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "ml-auto size-3 animate-spin" }) : kindLabel })
|
|
1399
|
+
]
|
|
1400
|
+
}
|
|
1401
|
+
);
|
|
1402
|
+
}
|
|
1403
|
+
function PopoverSection({
|
|
1404
|
+
label,
|
|
1405
|
+
items,
|
|
1406
|
+
onItemClick,
|
|
1407
|
+
bordered
|
|
1408
|
+
}) {
|
|
1409
|
+
const cls = "hover:bg-accent flex items-center gap-2 px-3 py-2 font-mono text-[11px] tracking-wide transition-colors";
|
|
1410
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1411
|
+
"div",
|
|
1412
|
+
{
|
|
1413
|
+
className: "p-1 " + (bordered ? "border-border border-t" : ""),
|
|
1414
|
+
"data-oc-account-menu-section": label,
|
|
1415
|
+
children: [
|
|
1416
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-muted-foreground/60 px-3 pt-2 pb-1 font-mono text-[10px] tracking-widest uppercase", children: [
|
|
1417
|
+
"\xA7 ",
|
|
1418
|
+
label
|
|
1419
|
+
] }),
|
|
1420
|
+
items.map((item) => {
|
|
1421
|
+
const inner = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1422
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", "aria-hidden": true, children: "\u2192" }),
|
|
1423
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1", children: item.label }),
|
|
1424
|
+
item.external ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1425
|
+
"span",
|
|
1426
|
+
{
|
|
1427
|
+
className: "text-muted-foreground/70 text-[10px]",
|
|
1428
|
+
"aria-hidden": true,
|
|
1429
|
+
children: "\u2197"
|
|
1430
|
+
}
|
|
1431
|
+
) : null
|
|
1432
|
+
] });
|
|
1433
|
+
return item.external ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1434
|
+
"a",
|
|
1435
|
+
{
|
|
1436
|
+
href: item.href,
|
|
1437
|
+
target: "_blank",
|
|
1438
|
+
rel: "noreferrer",
|
|
1439
|
+
onClick: onItemClick,
|
|
1440
|
+
role: "menuitem",
|
|
1441
|
+
className: cls,
|
|
1442
|
+
"data-oc-account-menu-item": "",
|
|
1443
|
+
children: inner
|
|
1444
|
+
},
|
|
1445
|
+
item.href
|
|
1446
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
1447
|
+
Link6__default.default,
|
|
1448
|
+
{
|
|
1449
|
+
href: item.href,
|
|
1450
|
+
onClick: onItemClick,
|
|
1451
|
+
role: "menuitem",
|
|
1452
|
+
className: cls,
|
|
1453
|
+
"data-oc-account-menu-item": "",
|
|
1454
|
+
children: inner
|
|
1455
|
+
},
|
|
1456
|
+
item.href
|
|
1457
|
+
);
|
|
1458
|
+
})
|
|
1459
|
+
]
|
|
1460
|
+
}
|
|
1461
|
+
);
|
|
1462
|
+
}
|
|
1463
|
+
function BuildFooter({
|
|
1464
|
+
hostname,
|
|
1465
|
+
build,
|
|
1466
|
+
state
|
|
1467
|
+
}) {
|
|
1468
|
+
const sha = build.sha;
|
|
1469
|
+
const showSha = !!sha && sha !== "dev";
|
|
1470
|
+
const commitUrl = showSha && build.repo ? `https://github.com/${build.repo}/commit/${sha}` : null;
|
|
1471
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1472
|
+
"div",
|
|
1473
|
+
{
|
|
1474
|
+
className: "text-muted-foreground/60 border-border border-t px-3 py-2 font-mono text-[9.5px] tracking-widest uppercase",
|
|
1475
|
+
"data-oc-account-menu-build": "",
|
|
1476
|
+
children: [
|
|
1477
|
+
hostname,
|
|
1478
|
+
state && state !== "live" ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1479
|
+
" \xB7 ",
|
|
1480
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground/80", children: state })
|
|
1481
|
+
] }) : null,
|
|
1482
|
+
" ",
|
|
1483
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-muted-foreground/80", children: [
|
|
1484
|
+
"v",
|
|
1485
|
+
build.version,
|
|
1486
|
+
showSha ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1487
|
+
" \xB7 ",
|
|
1488
|
+
commitUrl ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1489
|
+
"a",
|
|
1490
|
+
{
|
|
1491
|
+
href: commitUrl,
|
|
1492
|
+
target: "_blank",
|
|
1493
|
+
rel: "noreferrer",
|
|
1494
|
+
className: "hover:text-foreground/90 underline decoration-dotted underline-offset-2",
|
|
1495
|
+
children: sha
|
|
1496
|
+
}
|
|
1497
|
+
) : sha
|
|
1498
|
+
] }) : null
|
|
1499
|
+
] })
|
|
1500
|
+
]
|
|
1501
|
+
}
|
|
1502
|
+
);
|
|
1503
|
+
}
|
|
1504
|
+
function isActive(pathname, link) {
|
|
1505
|
+
if (link.external) return false;
|
|
1506
|
+
if (link.matchExact) return pathname === link.href;
|
|
1507
|
+
if (link.href === "/") return pathname === "/";
|
|
1508
|
+
return pathname === link.href || pathname.startsWith(link.href + "/");
|
|
1509
|
+
}
|
|
1510
|
+
function OcPrimaryNav({ activePath, links, className }) {
|
|
1511
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1512
|
+
"nav",
|
|
1513
|
+
{
|
|
1514
|
+
"aria-label": "primary",
|
|
1515
|
+
className: "flex min-w-0 items-center justify-start overflow-x-auto gap-0.5 sm:gap-1 whitespace-nowrap [scrollbar-width:none] [&::-webkit-scrollbar]:hidden " + (className ?? ""),
|
|
1516
|
+
"data-oc-primary-nav": "",
|
|
1517
|
+
children: links.map((link) => {
|
|
1518
|
+
const active = isActive(activePath, link);
|
|
1519
|
+
const className2 = "font-display relative shrink-0 px-2 py-1 sm:px-3 text-[11px] sm:text-[12px] font-semibold tracking-wider uppercase transition-colors " + (active ? 'text-primary after:bg-primary after:absolute after:inset-x-2 after:-bottom-[13px] after:h-px after:content-[""]' : "text-muted-foreground hover:text-foreground");
|
|
1520
|
+
const content = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1521
|
+
link.label,
|
|
1522
|
+
link.external ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1523
|
+
"span",
|
|
1524
|
+
{
|
|
1525
|
+
"aria-hidden": true,
|
|
1526
|
+
className: "text-muted-foreground/60 ml-1 text-[9px]",
|
|
1527
|
+
children: "\u2197"
|
|
1528
|
+
}
|
|
1529
|
+
) : null
|
|
1530
|
+
] });
|
|
1531
|
+
return link.external ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1532
|
+
"a",
|
|
1533
|
+
{
|
|
1534
|
+
href: link.href,
|
|
1535
|
+
target: "_blank",
|
|
1536
|
+
rel: "noreferrer",
|
|
1537
|
+
className: className2,
|
|
1538
|
+
"data-oc-primary-nav-item": "",
|
|
1539
|
+
children: content
|
|
1540
|
+
},
|
|
1541
|
+
link.href
|
|
1542
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
1543
|
+
Link6__default.default,
|
|
1544
|
+
{
|
|
1545
|
+
href: link.href,
|
|
1546
|
+
"aria-current": active ? "page" : void 0,
|
|
1547
|
+
className: className2,
|
|
1548
|
+
"data-oc-primary-nav-item": active ? "active" : "sibling",
|
|
1549
|
+
children: content
|
|
1550
|
+
},
|
|
1551
|
+
link.href
|
|
1552
|
+
);
|
|
1553
|
+
})
|
|
1554
|
+
}
|
|
1555
|
+
);
|
|
1556
|
+
}
|
|
1557
|
+
function OcDashboardShell({
|
|
1558
|
+
rootHref = "/dashboard",
|
|
1559
|
+
siteLabel,
|
|
1560
|
+
tools,
|
|
1561
|
+
active,
|
|
1562
|
+
eyebrow,
|
|
1563
|
+
title,
|
|
1564
|
+
description,
|
|
1565
|
+
children,
|
|
1566
|
+
className
|
|
1567
|
+
}) {
|
|
1568
|
+
const [drawerOpen, setDrawerOpen] = react.useState(false);
|
|
1569
|
+
react.useEffect(() => {
|
|
1570
|
+
if (!drawerOpen) return;
|
|
1571
|
+
function onKey(e) {
|
|
1572
|
+
if (e.key === "Escape") setDrawerOpen(false);
|
|
1573
|
+
}
|
|
1574
|
+
document.addEventListener("keydown", onKey);
|
|
1575
|
+
const prevOverflow = document.body.style.overflow;
|
|
1576
|
+
document.body.style.overflow = "hidden";
|
|
1577
|
+
return () => {
|
|
1578
|
+
document.removeEventListener("keydown", onKey);
|
|
1579
|
+
document.body.style.overflow = prevOverflow;
|
|
1580
|
+
};
|
|
1581
|
+
}, [drawerOpen]);
|
|
1582
|
+
const hasHeader = Boolean(title) || Boolean(eyebrow);
|
|
1583
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1584
|
+
"div",
|
|
1585
|
+
{
|
|
1586
|
+
className: "container " + (className ?? ""),
|
|
1587
|
+
"data-oc-dashboard-shell": "",
|
|
1588
|
+
children: [
|
|
1589
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-h-[calc(100vh-3rem)] flex-col md:flex-row md:gap-8", children: [
|
|
1590
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1591
|
+
Sidebar,
|
|
1592
|
+
{
|
|
1593
|
+
rootHref,
|
|
1594
|
+
siteLabel,
|
|
1595
|
+
tools,
|
|
1596
|
+
active,
|
|
1597
|
+
variant: "desktop"
|
|
1598
|
+
}
|
|
1599
|
+
),
|
|
1600
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-1 flex-col", children: [
|
|
1601
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-border flex items-center justify-between border-b py-3 md:hidden", children: [
|
|
1602
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1603
|
+
"button",
|
|
1604
|
+
{
|
|
1605
|
+
type: "button",
|
|
1606
|
+
onClick: () => setDrawerOpen(true),
|
|
1607
|
+
className: "text-muted-foreground hover:text-foreground inline-flex h-9 items-center gap-2 px-1 font-mono text-[11px] tracking-widest uppercase transition-colors",
|
|
1608
|
+
"aria-label": "open dashboard tools",
|
|
1609
|
+
"aria-expanded": drawerOpen,
|
|
1610
|
+
"data-oc-dashboard-mobile-trigger": "",
|
|
1611
|
+
children: [
|
|
1612
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[14px] leading-none", children: "\u2261" }),
|
|
1613
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "tools" })
|
|
1614
|
+
]
|
|
1615
|
+
}
|
|
1616
|
+
),
|
|
1617
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1618
|
+
Link6__default.default,
|
|
1619
|
+
{
|
|
1620
|
+
href: rootHref,
|
|
1621
|
+
className: "text-primary font-mono text-[11px] tracking-widest uppercase",
|
|
1622
|
+
children: "\xA7 dashboard"
|
|
1623
|
+
}
|
|
1624
|
+
)
|
|
1625
|
+
] }),
|
|
1626
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "pt-6 md:pt-3", children: [
|
|
1627
|
+
hasHeader && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "max-w-3xl", children: [
|
|
1628
|
+
eyebrow ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "label-mono text-primary mb-3 font-mono text-[10px] tracking-widest uppercase", children: eyebrow }) : null,
|
|
1629
|
+
title ? /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "font-display text-2xl font-bold tracking-tight sm:text-3xl", children: title }) : null,
|
|
1630
|
+
description ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-muted-foreground mt-3 max-w-[64ch] text-sm leading-relaxed", children: description }) : null
|
|
1631
|
+
] }),
|
|
1632
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: hasHeader ? "mt-8 pb-12" : "pb-12", children })
|
|
1633
|
+
] })
|
|
1634
|
+
] })
|
|
1635
|
+
] }),
|
|
1636
|
+
drawerOpen ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1637
|
+
"div",
|
|
1638
|
+
{
|
|
1639
|
+
className: "fixed inset-0 z-50 md:hidden",
|
|
1640
|
+
role: "dialog",
|
|
1641
|
+
"aria-modal": "true",
|
|
1642
|
+
"aria-label": "dashboard tools",
|
|
1643
|
+
"data-oc-dashboard-drawer": "",
|
|
1644
|
+
children: [
|
|
1645
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1646
|
+
"div",
|
|
1647
|
+
{
|
|
1648
|
+
className: "absolute inset-0 bg-background/80 backdrop-blur-sm",
|
|
1649
|
+
onClick: () => setDrawerOpen(false),
|
|
1650
|
+
"aria-hidden": true
|
|
1651
|
+
}
|
|
1652
|
+
),
|
|
1653
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-background absolute top-0 left-0 h-full w-[85vw] max-w-sm border-r shadow-xl", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1654
|
+
Sidebar,
|
|
1655
|
+
{
|
|
1656
|
+
rootHref,
|
|
1657
|
+
siteLabel,
|
|
1658
|
+
tools,
|
|
1659
|
+
active,
|
|
1660
|
+
variant: "drawer",
|
|
1661
|
+
onClose: () => setDrawerOpen(false)
|
|
1662
|
+
}
|
|
1663
|
+
) })
|
|
1664
|
+
]
|
|
1665
|
+
}
|
|
1666
|
+
) : null
|
|
1667
|
+
]
|
|
1668
|
+
}
|
|
1669
|
+
);
|
|
1670
|
+
}
|
|
1671
|
+
function Sidebar({
|
|
1672
|
+
rootHref,
|
|
1673
|
+
siteLabel,
|
|
1674
|
+
tools,
|
|
1675
|
+
active,
|
|
1676
|
+
variant,
|
|
1677
|
+
onClose
|
|
1678
|
+
}) {
|
|
1679
|
+
const isDrawer = variant === "drawer";
|
|
1680
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1681
|
+
"aside",
|
|
1682
|
+
{
|
|
1683
|
+
className: isDrawer ? "flex h-full w-full flex-col bg-card" : "hidden md:sticky md:top-4 md:flex md:h-[calc(100vh-2rem)] md:w-56 md:shrink-0 md:flex-col md:self-start md:overflow-y-auto md:rounded md:border md:bg-card/40 lg:w-60",
|
|
1684
|
+
"aria-label": "dashboard tools",
|
|
1685
|
+
"data-oc-dashboard-sidebar": variant,
|
|
1686
|
+
children: [
|
|
1687
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-b px-4 py-3", children: [
|
|
1688
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
1689
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1690
|
+
Link6__default.default,
|
|
1691
|
+
{
|
|
1692
|
+
href: rootHref,
|
|
1693
|
+
onClick: onClose,
|
|
1694
|
+
className: "hover:text-foreground font-display text-sm font-bold tracking-tight",
|
|
1695
|
+
children: "\xA7 dashboard"
|
|
1696
|
+
}
|
|
1697
|
+
),
|
|
1698
|
+
isDrawer ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1699
|
+
"button",
|
|
1700
|
+
{
|
|
1701
|
+
type: "button",
|
|
1702
|
+
onClick: onClose,
|
|
1703
|
+
className: "text-muted-foreground hover:text-foreground -mr-2 inline-flex h-8 w-8 items-center justify-center rounded font-mono text-lg",
|
|
1704
|
+
"aria-label": "close navigation",
|
|
1705
|
+
children: "\xD7"
|
|
1706
|
+
}
|
|
1707
|
+
) : null
|
|
1708
|
+
] }),
|
|
1709
|
+
siteLabel ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-muted-foreground/70 mt-1 font-mono text-[10px] tracking-widest uppercase", children: siteLabel }) : null
|
|
1710
|
+
] }),
|
|
1711
|
+
/* @__PURE__ */ jsxRuntime.jsxs("nav", { className: "flex-1 overflow-y-auto px-2 py-3", children: [
|
|
1712
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-muted-foreground/60 mb-1 px-3 font-mono text-[10px] tracking-widest uppercase", children: "\xA7 tools" }),
|
|
1713
|
+
/* @__PURE__ */ jsxRuntime.jsx("ul", { className: "space-y-0.5", children: tools.map((tool) => {
|
|
1714
|
+
const isActive2 = tool.id === active;
|
|
1715
|
+
const innerCls = "flex items-baseline gap-2 rounded px-3 py-1.5 text-[12.5px] transition-colors " + (isActive2 ? "bg-primary/10 text-primary font-semibold" : "text-muted-foreground hover:text-foreground hover:bg-muted/30");
|
|
1716
|
+
const content = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1717
|
+
tool.icon ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1718
|
+
"span",
|
|
1719
|
+
{
|
|
1720
|
+
className: "shrink-0 font-mono text-[11px] " + (isActive2 ? "text-primary" : "text-muted-foreground/70"),
|
|
1721
|
+
"aria-hidden": true,
|
|
1722
|
+
children: tool.icon
|
|
1723
|
+
}
|
|
1724
|
+
) : null,
|
|
1725
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex-1 leading-tight", children: [
|
|
1726
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: tool.label }),
|
|
1727
|
+
tool.tagline ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground/60 mt-0.5 block font-mono text-[10px] tracking-wide normal-case", children: tool.tagline }) : null
|
|
1728
|
+
] }),
|
|
1729
|
+
tool.external ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1730
|
+
"span",
|
|
1731
|
+
{
|
|
1732
|
+
className: "text-muted-foreground/60 text-[10px]",
|
|
1733
|
+
"aria-hidden": true,
|
|
1734
|
+
children: "\u2197"
|
|
1735
|
+
}
|
|
1736
|
+
) : null
|
|
1737
|
+
] });
|
|
1738
|
+
return /* @__PURE__ */ jsxRuntime.jsx("li", { children: tool.external ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1739
|
+
"a",
|
|
1740
|
+
{
|
|
1741
|
+
href: tool.href,
|
|
1742
|
+
target: "_blank",
|
|
1743
|
+
rel: "noreferrer",
|
|
1744
|
+
onClick: onClose,
|
|
1745
|
+
className: innerCls,
|
|
1746
|
+
"data-oc-dashboard-tool": isActive2 ? "active" : "sibling",
|
|
1747
|
+
children: content
|
|
1748
|
+
}
|
|
1749
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
1750
|
+
Link6__default.default,
|
|
1751
|
+
{
|
|
1752
|
+
href: tool.href,
|
|
1753
|
+
onClick: onClose,
|
|
1754
|
+
"aria-current": isActive2 ? "page" : void 0,
|
|
1755
|
+
className: innerCls,
|
|
1756
|
+
"data-oc-dashboard-tool": isActive2 ? "active" : "sibling",
|
|
1757
|
+
children: content
|
|
1758
|
+
}
|
|
1759
|
+
) }, tool.id);
|
|
1760
|
+
}) })
|
|
1761
|
+
] })
|
|
1762
|
+
]
|
|
1763
|
+
}
|
|
1764
|
+
);
|
|
1765
|
+
}
|
|
1766
|
+
function OcDashboardHub({ tools, className }) {
|
|
1767
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1768
|
+
"ul",
|
|
1769
|
+
{
|
|
1770
|
+
className: "grid gap-px border-t border-l sm:grid-cols-2 " + (className ?? ""),
|
|
1771
|
+
"data-oc-dashboard-hub": "",
|
|
1772
|
+
children: tools.map((tool) => {
|
|
1773
|
+
const content = /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex h-full flex-col gap-3 p-5 transition-colors", children: [
|
|
1774
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-baseline gap-3", children: [
|
|
1775
|
+
tool.icon ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1776
|
+
"span",
|
|
1777
|
+
{
|
|
1778
|
+
className: "text-primary font-mono text-[13px]",
|
|
1779
|
+
"aria-hidden": true,
|
|
1780
|
+
children: tool.icon
|
|
1781
|
+
}
|
|
1782
|
+
) : null,
|
|
1783
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-display text-foreground text-base font-bold tracking-tight", children: tool.label }),
|
|
1784
|
+
tool.external ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1785
|
+
"span",
|
|
1786
|
+
{
|
|
1787
|
+
className: "text-muted-foreground/60 ml-auto text-xs",
|
|
1788
|
+
"aria-hidden": true,
|
|
1789
|
+
children: "\u2197"
|
|
1790
|
+
}
|
|
1791
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
1792
|
+
"span",
|
|
1793
|
+
{
|
|
1794
|
+
className: "text-muted-foreground/60 ml-auto text-xs",
|
|
1795
|
+
"aria-hidden": true,
|
|
1796
|
+
children: "\u2192"
|
|
1797
|
+
}
|
|
1798
|
+
)
|
|
1799
|
+
] }),
|
|
1800
|
+
tool.tagline ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground text-sm leading-relaxed", children: tool.tagline }) : null
|
|
1801
|
+
] });
|
|
1802
|
+
const cls = "hover:bg-muted/30 group block border-r border-b transition-colors";
|
|
1803
|
+
return /* @__PURE__ */ jsxRuntime.jsx("li", { children: tool.external ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1804
|
+
"a",
|
|
1805
|
+
{
|
|
1806
|
+
href: tool.href,
|
|
1807
|
+
target: "_blank",
|
|
1808
|
+
rel: "noreferrer",
|
|
1809
|
+
className: cls,
|
|
1810
|
+
children: content
|
|
1811
|
+
}
|
|
1812
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(Link6__default.default, { href: tool.href, className: cls, children: content }) }, tool.id);
|
|
1813
|
+
})
|
|
1814
|
+
}
|
|
1815
|
+
);
|
|
1816
|
+
}
|
|
1817
|
+
function AppShell({
|
|
1818
|
+
eyebrow,
|
|
1819
|
+
title,
|
|
1820
|
+
description,
|
|
1821
|
+
headerActions,
|
|
1822
|
+
children,
|
|
1823
|
+
className
|
|
1824
|
+
}) {
|
|
1825
|
+
const hasHeader = Boolean(title);
|
|
1826
|
+
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: [
|
|
1827
|
+
hasHeader && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between", children: [
|
|
1828
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "max-w-3xl", children: [
|
|
1829
|
+
eyebrow && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "label-mono text-primary mb-3", children: eyebrow }),
|
|
1830
|
+
/* @__PURE__ */ jsxRuntime.jsx("h1", { className: "font-display text-2xl font-bold tracking-tight sm:text-3xl", children: title }),
|
|
1831
|
+
description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-muted-foreground mt-3 max-w-[64ch] text-sm leading-relaxed", children: description })
|
|
1832
|
+
] }),
|
|
1833
|
+
headerActions && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex shrink-0 items-center gap-2", children: headerActions })
|
|
1834
|
+
] }),
|
|
1835
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: hasHeader ? "mt-8 pb-12" : "pb-12", children })
|
|
1836
|
+
] }) }) }) });
|
|
1837
|
+
}
|
|
1838
|
+
var HIDE = {
|
|
1839
|
+
sm: "hidden sm:inline",
|
|
1840
|
+
md: "hidden md:inline",
|
|
1841
|
+
lg: "hidden lg:inline"
|
|
1842
|
+
};
|
|
1843
|
+
function LayoutSubHeader({
|
|
1844
|
+
product,
|
|
1845
|
+
status = "live \xB7 mainnet",
|
|
1846
|
+
tags = [],
|
|
1847
|
+
noHeartbeat = false,
|
|
1848
|
+
className
|
|
1849
|
+
}) {
|
|
1850
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("border-b", className), children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "container flex flex-wrap items-center justify-between gap-x-6 gap-y-1 py-2 font-mono text-[11px]", children: [
|
|
1851
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
|
|
1852
|
+
!noHeartbeat && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "bg-primary inline-block h-1.5 w-1.5 animate-pulse rounded-full" }),
|
|
1853
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground tracking-widest uppercase", children: status }),
|
|
1854
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-foreground", children: product })
|
|
1855
|
+
] }),
|
|
1856
|
+
tags.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-muted-foreground flex flex-wrap items-center gap-x-4 gap-y-1 tracking-widest uppercase", children: tags.map((tag, i) => /* @__PURE__ */ jsxRuntime.jsx("span", { className: tag.hideBelow ? HIDE[tag.hideBelow] : void 0, children: tag.label }, i)) })
|
|
1857
|
+
] }) });
|
|
1858
|
+
}
|
|
1859
|
+
|
|
1860
|
+
exports.AppShell = AppShell;
|
|
1861
|
+
exports.Callout = Callout;
|
|
1862
|
+
exports.DataRow = DataRow;
|
|
1863
|
+
exports.DefinitionList = DefinitionList;
|
|
1864
|
+
exports.EcosystemSwitcher = EcosystemSwitcher;
|
|
1865
|
+
exports.EmptyState = EmptyState;
|
|
1866
|
+
exports.FAMILY_PROPERTIES = FAMILY_PROPERTIES;
|
|
1867
|
+
exports.HelpHint = HelpHint;
|
|
1868
|
+
exports.LayoutSubHeader = LayoutSubHeader;
|
|
1869
|
+
exports.OcAccountMenu = OcAccountMenu;
|
|
1870
|
+
exports.OcAccountMenuView = OcAccountMenuView;
|
|
1871
|
+
exports.OcDashboardHub = OcDashboardHub;
|
|
1872
|
+
exports.OcDashboardShell = OcDashboardShell;
|
|
1873
|
+
exports.OcLogoDropdown = OcLogoDropdown;
|
|
1874
|
+
exports.OcPrimaryNav = OcPrimaryNav;
|
|
1875
|
+
exports.SITE_STATE_LABEL = SITE_STATE_LABEL;
|
|
1876
|
+
exports.SectionHeader = SectionHeader;
|
|
1877
|
+
exports.StatGrid = StatGrid;
|
|
1878
|
+
exports.StatTile = StatTile;
|
|
1879
|
+
exports.findFamilyProperty = findFamilyProperty;
|
|
13
1880
|
//# sourceMappingURL=components.js.map
|
|
14
1881
|
//# sourceMappingURL=components.js.map
|