@orangecheck/ui 0.8.2 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { Boxes, ChevronDown, Check, CornerDownLeft } from 'lucide-react';
1
+ import { Boxes, ChevronDown, Check, CornerDownLeft, Copy } from 'lucide-react';
2
2
  import Link5 from 'next/link';
3
3
  import { useState, useRef, useEffect, useId } from 'react';
4
4
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
@@ -85,9 +85,19 @@ var ENTRIES = [
85
85
  docsHref: "https://docs.ochk.io/pledge"
86
86
  }
87
87
  ];
88
+ var OWNER_ENTRIES = [
89
+ {
90
+ slug: "analytics",
91
+ href: "https://analytics.ochk.io",
92
+ label: "oc\xB7analytics",
93
+ sub: "owner cockpit",
94
+ docsHref: "https://analytics.ochk.io"
95
+ }
96
+ ];
88
97
  function EcosystemSwitcher({
89
98
  current,
90
- className
99
+ className,
100
+ showOwnerEntries = false
91
101
  }) {
92
102
  const [open, setOpen] = useState(false);
93
103
  const containerRef = useRef(null);
@@ -137,7 +147,7 @@ function EcosystemSwitcher({
137
147
  className: "bg-background absolute right-0 top-full z-[60] mt-2 w-72 border shadow-lg",
138
148
  children: [
139
149
  /* @__PURE__ */ jsx("div", { className: "label-mono text-primary border-b px-4 py-2", children: "\xA7 the family" }),
140
- /* @__PURE__ */ jsx("ul", { className: "py-1", children: ENTRIES.map((e) => {
150
+ /* @__PURE__ */ jsx("ul", { className: "py-1", children: [...ENTRIES, ...showOwnerEntries ? OWNER_ENTRIES : []].map((e) => {
141
151
  const isActive2 = e.slug === current;
142
152
  return /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsxs(
143
153
  Link5,
@@ -275,6 +285,15 @@ var FAMILY_PROPERTIES = [
275
285
  sub: "swear \u2014 bonded commitment",
276
286
  docsHref: "https://docs.ochk.io/pledge",
277
287
  category: "protocol"
288
+ },
289
+ {
290
+ slug: "analytics",
291
+ origin: "https://analytics.ochk.io",
292
+ hostname: "analytics.ochk.io",
293
+ label: "oc\xB7analytics",
294
+ sub: "owner cockpit",
295
+ docsHref: "https://analytics.ochk.io",
296
+ category: "owner"
278
297
  }
279
298
  ];
280
299
  var SITE_STATE_LABEL = {
@@ -287,18 +306,20 @@ function findFamilyProperty(slug) {
287
306
  var SECTIONS = [
288
307
  { category: "hub", label: "hub" },
289
308
  { category: "product", label: "products" },
290
- { category: "protocol", label: "protocols" }
309
+ { category: "protocol", label: "protocols" },
310
+ { category: "owner", label: "owner" }
291
311
  ];
292
312
  function CategoryChip({ category }) {
293
313
  if (category === "hub") return null;
294
- const isProduct = category === "product";
314
+ const label = category === "product" ? "product" : category === "protocol" ? "protocol" : "owner";
315
+ 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";
295
316
  return /* @__PURE__ */ jsx(
296
317
  "span",
297
318
  {
298
- "aria-label": isProduct ? "commercial product" : "protocol reference",
299
- className: "ml-1 hidden rounded-sm border px-1.5 py-[1px] font-mono text-[9px] font-medium tracking-widest uppercase sm:inline-block " + (isProduct ? "border-primary/25 bg-primary/10 text-primary" : "border-muted-foreground/20 bg-muted/40 text-muted-foreground/85"),
319
+ "aria-label": category === "product" ? "commercial product" : category === "protocol" ? "protocol reference" : "owner-only surface",
320
+ 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,
300
321
  "data-oc-category": category,
301
- children: isProduct ? "product" : "protocol"
322
+ children: label
302
323
  }
303
324
  );
304
325
  }
@@ -316,13 +337,14 @@ function SiteStateBadge({ state }) {
316
337
  }
317
338
  function MenuCategoryChip({ category }) {
318
339
  if (category === "hub") return null;
319
- const isProduct = category === "product";
340
+ const label = category === "product" ? "pro" : category === "protocol" ? "spec" : "own";
341
+ const tone = category === "product" ? "bg-primary/10 text-primary" : category === "protocol" ? "bg-muted/60 text-muted-foreground/80" : "bg-warning/15 text-warning";
320
342
  return /* @__PURE__ */ jsx(
321
343
  "span",
322
344
  {
323
345
  "aria-hidden": true,
324
- className: "inline-block shrink-0 rounded-sm px-1 py-[1px] font-mono text-[9px] font-medium tracking-widest uppercase " + (isProduct ? "bg-primary/10 text-primary" : "bg-muted/60 text-muted-foreground/80"),
325
- children: isProduct ? "pro" : "spec"
346
+ className: "inline-block shrink-0 rounded-sm px-1 py-[1px] font-mono text-[9px] font-medium tracking-widest uppercase " + tone,
347
+ children: label
326
348
  }
327
349
  );
328
350
  }
@@ -333,7 +355,8 @@ function OcLogoDropdown({
333
355
  children,
334
356
  className,
335
357
  triggerClassName,
336
- popoverClassName
358
+ popoverClassName,
359
+ showOwnerEntries = false
337
360
  }) {
338
361
  const [open, setOpen] = useState(false);
339
362
  const containerRef = useRef(null);
@@ -433,6 +456,7 @@ function OcLogoDropdown({
433
456
  children: [
434
457
  /* @__PURE__ */ jsx("div", { className: "label-mono text-primary border-b px-4 py-2", children: "\xA7 the orangecheck family" }),
435
458
  /* @__PURE__ */ jsx("div", { className: "max-h-[min(28rem,70vh)] overflow-y-auto py-1", role: "none", children: SECTIONS.map(({ category, label }) => {
459
+ if (category === "owner" && !showOwnerEntries) return null;
436
460
  const sectionEntries = FAMILY_PROPERTIES.filter(
437
461
  (e) => e.category === category
438
462
  );
@@ -502,6 +526,71 @@ function shortenDid(s) {
502
526
  if (s.length <= 14) return s;
503
527
  return `${s.slice(0, 7)}\u2026${s.slice(-5)}`;
504
528
  }
529
+ async function writeClipboard(text) {
530
+ try {
531
+ if (navigator.clipboard?.writeText) {
532
+ await navigator.clipboard.writeText(text);
533
+ return true;
534
+ }
535
+ } catch {
536
+ }
537
+ try {
538
+ const ta = document.createElement("textarea");
539
+ ta.value = text;
540
+ ta.setAttribute("readonly", "");
541
+ ta.style.position = "fixed";
542
+ ta.style.top = "-1000px";
543
+ ta.style.opacity = "0";
544
+ document.body.appendChild(ta);
545
+ ta.select();
546
+ const ok = document.execCommand("copy");
547
+ document.body.removeChild(ta);
548
+ return ok;
549
+ } catch {
550
+ return false;
551
+ }
552
+ }
553
+ function CopyableDid({ did }) {
554
+ const [copied, setCopied] = useState(false);
555
+ const timerRef = useRef(null);
556
+ useEffect(
557
+ () => () => {
558
+ if (timerRef.current) clearTimeout(timerRef.current);
559
+ },
560
+ []
561
+ );
562
+ const onCopy = async () => {
563
+ const ok = await writeClipboard(did);
564
+ if (!ok) return;
565
+ setCopied(true);
566
+ if (timerRef.current) clearTimeout(timerRef.current);
567
+ timerRef.current = setTimeout(() => setCopied(false), 1600);
568
+ };
569
+ return /* @__PURE__ */ jsxs(
570
+ "button",
571
+ {
572
+ type: "button",
573
+ onClick: onCopy,
574
+ "aria-label": copied ? "OrangeCheck identity copied to clipboard" : `Copy OrangeCheck identity ${did} to clipboard`,
575
+ title: "Copy identity",
576
+ "data-oc-account-menu-copy-did": "",
577
+ "data-copied": copied ? "" : void 0,
578
+ 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",
579
+ children: [
580
+ /* @__PURE__ */ jsx("span", { className: "text-foreground/90 min-w-0 flex-1 font-mono text-[11px] leading-tight break-all", children: did }),
581
+ /* @__PURE__ */ jsx(
582
+ "span",
583
+ {
584
+ className: "mt-px shrink-0 transition-colors " + (copied ? "text-primary" : "text-muted-foreground/50 group-hover/did:text-foreground/80"),
585
+ "aria-hidden": true,
586
+ children: copied ? /* @__PURE__ */ jsx(Check, { className: "size-3.5" }) : /* @__PURE__ */ jsx(Copy, { className: "size-3.5" })
587
+ }
588
+ ),
589
+ /* @__PURE__ */ jsx("span", { className: "sr-only", "aria-live": "polite", children: copied ? "Copied to clipboard" : "" })
590
+ ]
591
+ }
592
+ );
593
+ }
505
594
  function OcAccountMenu(props) {
506
595
  const session = useOcSession();
507
596
  return /* @__PURE__ */ jsx(
@@ -645,7 +734,7 @@ function OcAccountMenuView({
645
734
  "\xA7 signed in \xB7 ",
646
735
  hostname
647
736
  ] }),
648
- /* @__PURE__ */ jsx("div", { className: "text-foreground/90 font-mono text-[11px] leading-tight break-all", children: account.didOc }),
737
+ /* @__PURE__ */ jsx(CopyableDid, { did: account.didOc }),
649
738
  displayName ? /* @__PURE__ */ jsx("div", { className: "text-muted-foreground/80 mt-1 font-mono text-[10px] tracking-wide", children: displayName }) : null
650
739
  ] }),
651
740
  primaryNavLinks && primaryNavLinks.length > 0 ? /* @__PURE__ */ jsx(