@orangecheck/design 0.16.0 → 0.17.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/chrome.js CHANGED
@@ -9,6 +9,7 @@ var Popover = require('@radix-ui/react-popover');
9
9
  var clsx = require('clsx');
10
10
  var tailwindMerge = require('tailwind-merge');
11
11
  var authClient = require('@orangecheck/auth-client');
12
+ var nextThemes = require('next-themes');
12
13
 
13
14
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
14
15
 
@@ -776,6 +777,74 @@ function OcLogoDropdown({
776
777
  }
777
778
  );
778
779
  }
780
+ var OcSkinContext = React.createContext(null);
781
+ function useOcSkin() {
782
+ const ctx = React.useContext(OcSkinContext);
783
+ if (!ctx) {
784
+ throw new Error("useOcSkin must be used within <OcThemeProvider>");
785
+ }
786
+ return ctx;
787
+ }
788
+ var MODES = [
789
+ { id: "light", label: "light", Icon: lucideReact.Sun },
790
+ { id: "dark", label: "dark", Icon: lucideReact.Moon },
791
+ { id: "system", label: "system", Icon: lucideReact.Monitor }
792
+ ];
793
+ function AppearanceControls({ className }) {
794
+ const { skin, setSkin, themes } = useOcSkin();
795
+ const { theme, setTheme } = nextThemes.useTheme();
796
+ const [mounted, setMounted] = React.useState(false);
797
+ React.useEffect(() => setMounted(true), []);
798
+ const activeMode = mounted ? theme ?? "system" : null;
799
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className, children: [
800
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "label-mono text-muted-foreground px-3 pt-3 pb-2", children: "mode" }),
801
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-3 gap-1 px-2 pb-2", children: MODES.map(({ id, label, Icon }) => {
802
+ const active = activeMode === id;
803
+ return /* @__PURE__ */ jsxRuntime.jsxs(
804
+ "button",
805
+ {
806
+ type: "button",
807
+ role: "menuitemradio",
808
+ "aria-checked": active,
809
+ onClick: () => setTheme(id),
810
+ className: cn(
811
+ "flex flex-col items-center gap-1 rounded-md border py-2 text-[11px] transition-colors",
812
+ active ? "border-primary text-foreground bg-accent" : "border-transparent text-muted-foreground hover:bg-accent hover:text-accent-foreground"
813
+ ),
814
+ children: [
815
+ /* @__PURE__ */ jsxRuntime.jsx(Icon, { className: "size-4", "aria-hidden": true }),
816
+ label
817
+ ]
818
+ },
819
+ id
820
+ );
821
+ }) }),
822
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "label-mono text-muted-foreground border-t px-3 pt-3 pb-1", children: "theme" }),
823
+ /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "pb-1", children: themes.map((t) => {
824
+ const active = t.id === skin;
825
+ return /* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsxs(
826
+ "button",
827
+ {
828
+ type: "button",
829
+ role: "menuitemradio",
830
+ "aria-checked": active,
831
+ onClick: () => setSkin(t.id),
832
+ className: cn(
833
+ "hover:bg-accent hover:text-accent-foreground flex w-full items-start gap-2 px-3 py-2 text-left transition-colors",
834
+ active && "text-foreground"
835
+ ),
836
+ children: [
837
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "mt-0.5 size-4 shrink-0", children: active && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "text-primary size-4", "aria-hidden": true }) }),
838
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "min-w-0", children: [
839
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "block text-sm font-medium", children: t.label }),
840
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground block text-xs leading-snug", children: t.description })
841
+ ] })
842
+ ]
843
+ }
844
+ ) }, t.id);
845
+ }) })
846
+ ] });
847
+ }
779
848
  function obscureIdentity(value) {
780
849
  if (value.length <= 12) {
781
850
  return `${value.slice(0, 4)}\u2026${value.slice(-3)}`;
@@ -1026,6 +1095,92 @@ function OcAccountMenu(props) {
1026
1095
  }
1027
1096
  );
1028
1097
  }
1098
+ function MobileMenu({
1099
+ primary,
1100
+ secondary
1101
+ }) {
1102
+ const [open, setOpen] = React.useState(false);
1103
+ const ref = React.useRef(null);
1104
+ React.useEffect(() => {
1105
+ if (!open) return;
1106
+ const onClick = (e) => {
1107
+ if (ref.current && !ref.current.contains(e.target)) setOpen(false);
1108
+ };
1109
+ const onKey = (e) => {
1110
+ if (e.key === "Escape") setOpen(false);
1111
+ };
1112
+ document.addEventListener("mousedown", onClick);
1113
+ document.addEventListener("keydown", onKey);
1114
+ return () => {
1115
+ document.removeEventListener("mousedown", onClick);
1116
+ document.removeEventListener("keydown", onKey);
1117
+ };
1118
+ }, [open]);
1119
+ const links = [...primary ?? [], ...secondary ?? []];
1120
+ const rowCls = "font-display flex items-center gap-2 px-3 py-2 text-[12px] font-semibold tracking-wider uppercase text-muted-foreground hover:text-foreground hover:bg-accent transition-colors";
1121
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref, className: "relative md:hidden", "data-oc-account-mobile-menu": "", children: [
1122
+ /* @__PURE__ */ jsxRuntime.jsx(
1123
+ "button",
1124
+ {
1125
+ type: "button",
1126
+ onClick: () => setOpen((v) => !v),
1127
+ "aria-haspopup": "menu",
1128
+ "aria-expanded": open,
1129
+ "aria-label": "menu",
1130
+ className: "border-input bg-background hover:bg-accent text-muted-foreground inline-flex size-8 items-center justify-center rounded-md border transition-colors",
1131
+ "data-oc-account-mobile-toggle": "",
1132
+ children: open ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "size-4", "aria-hidden": true }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Menu, { className: "size-4", "aria-hidden": true })
1133
+ }
1134
+ ),
1135
+ open && /* @__PURE__ */ jsxRuntime.jsxs(
1136
+ "div",
1137
+ {
1138
+ role: "menu",
1139
+ "aria-label": "menu",
1140
+ className: "border-border bg-popover text-popover-foreground absolute top-[calc(100%+6px)] right-0 z-50 w-[min(16rem,calc(100vw-1rem))] overflow-hidden border shadow-xl",
1141
+ "data-oc-account-mobile-popover": "",
1142
+ children: [
1143
+ links.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-b p-1", children: [
1144
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-muted-foreground/60 px-3 pt-2 pb-1 font-mono text-[10px] tracking-widest uppercase", children: "\xA7 navigate" }),
1145
+ links.map(
1146
+ (l) => l.external ? /* @__PURE__ */ jsxRuntime.jsxs(
1147
+ "a",
1148
+ {
1149
+ href: l.href,
1150
+ target: "_blank",
1151
+ rel: "noreferrer",
1152
+ role: "menuitem",
1153
+ onClick: () => setOpen(false),
1154
+ className: rowCls,
1155
+ children: [
1156
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", "aria-hidden": true, children: "\u2192" }),
1157
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1", children: l.label }),
1158
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground/70 text-[10px]", "aria-hidden": true, children: "\u2197" })
1159
+ ]
1160
+ },
1161
+ l.href
1162
+ ) : /* @__PURE__ */ jsxRuntime.jsxs(
1163
+ Link5__default.default,
1164
+ {
1165
+ href: l.href,
1166
+ role: "menuitem",
1167
+ onClick: () => setOpen(false),
1168
+ className: rowCls,
1169
+ children: [
1170
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", "aria-hidden": true, children: "\u2192" }),
1171
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1", children: l.label })
1172
+ ]
1173
+ },
1174
+ l.href
1175
+ )
1176
+ )
1177
+ ] }),
1178
+ /* @__PURE__ */ jsxRuntime.jsx(AppearanceControls, {})
1179
+ ]
1180
+ }
1181
+ )
1182
+ ] });
1183
+ }
1029
1184
  function OcAccountMenuView({
1030
1185
  current,
1031
1186
  signInUrl = "/signin",
@@ -1098,220 +1253,220 @@ function OcAccountMenuView({
1098
1253
  children: signInLabel
1099
1254
  }
1100
1255
  );
1256
+ const hasNav = (primaryNavLinks?.length ?? 0) + (secondaryNavLinks?.length ?? 0) > 0;
1257
+ const wrap = (identity) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex items-center gap-1", className), "data-oc-account-menu": "", children: [
1258
+ hasNav ? /* @__PURE__ */ jsxRuntime.jsx(MobileMenu, { primary: primaryNavLinks, secondary: secondaryNavLinks }) : null,
1259
+ identity
1260
+ ] });
1101
1261
  if (!hydrated || status === "loading") {
1102
- return signInTrigger;
1262
+ return wrap(signInTrigger);
1103
1263
  }
1104
1264
  if (status !== "authenticated" || !account) {
1105
- return signInTrigger;
1265
+ return wrap(signInTrigger);
1106
1266
  }
1107
1267
  const displayName = account.displayName ?? null;
1108
1268
  const label = displayName ?? obscureIdentity(account.displayIdentity.value);
1109
- return /* @__PURE__ */ jsxRuntime.jsxs(
1110
- "div",
1111
- {
1112
- ref: wrapRef,
1113
- className: "relative inline-block " + (className ?? ""),
1114
- "data-oc-account-menu": "",
1115
- children: [
1116
- /* @__PURE__ */ jsxRuntime.jsxs(
1117
- "button",
1118
- {
1119
- type: "button",
1120
- onClick: () => setOpen((v) => !v),
1121
- "aria-haspopup": "menu",
1122
- "aria-expanded": open,
1123
- "aria-label": `Signed in as ${account.didOc}. Open account menu.`,
1124
- className: triggerClassName ?? "border-primary/40 bg-card hover:bg-accent inline-flex h-8 items-center gap-1.5 rounded-md border px-2 font-mono text-[11px] tracking-wide transition-colors sm:px-3",
1125
- "data-oc-account-menu-trigger": "",
1126
- children: [
1127
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "bg-primary inline-block size-1.5 shrink-0 rounded-full", "aria-hidden": true }),
1128
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-foreground hidden max-w-[16ch] truncate sm:inline", children: label }),
1129
- /* @__PURE__ */ jsxRuntime.jsx(
1130
- "svg",
1131
- {
1132
- width: "9",
1133
- height: "9",
1134
- viewBox: "0 0 10 10",
1135
- "aria-hidden": true,
1136
- className: "opacity-60 transition-transform " + (open ? "rotate-180" : "rotate-0"),
1137
- children: /* @__PURE__ */ jsxRuntime.jsx(
1138
- "path",
1139
- {
1140
- d: "M2 4 L5 7 L8 4",
1141
- stroke: "currentColor",
1142
- strokeWidth: "1.5",
1143
- fill: "none",
1144
- strokeLinecap: "round"
1145
- }
1146
- )
1147
- }
1148
- )
1149
- ]
1150
- }
1151
- ),
1152
- open && /* @__PURE__ */ jsxRuntime.jsxs(
1153
- "div",
1154
- {
1155
- role: "menu",
1156
- "aria-label": "Account menu",
1157
- 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",
1158
- "data-oc-account-menu-popover": "",
1159
- children: [
1160
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-border border-b p-3", children: [
1161
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-primary mb-1 font-mono text-[10px] tracking-widest uppercase", children: [
1162
- "\xA7 signed in \xB7 ",
1163
- hostname,
1164
- tabPinned ? /* @__PURE__ */ jsxRuntime.jsxs(
1269
+ return wrap(
1270
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: wrapRef, className: "relative inline-block", children: [
1271
+ /* @__PURE__ */ jsxRuntime.jsxs(
1272
+ "button",
1273
+ {
1274
+ type: "button",
1275
+ onClick: () => setOpen((v) => !v),
1276
+ "aria-haspopup": "menu",
1277
+ "aria-expanded": open,
1278
+ "aria-label": `Signed in as ${account.didOc}. Open account menu.`,
1279
+ className: triggerClassName ?? "border-primary/40 bg-card hover:bg-accent inline-flex h-8 items-center gap-1.5 rounded-md border px-2 font-mono text-[11px] tracking-wide transition-colors sm:px-3",
1280
+ "data-oc-account-menu-trigger": "",
1281
+ children: [
1282
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "bg-primary inline-block size-1.5 shrink-0 rounded-full", "aria-hidden": true }),
1283
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-foreground hidden max-w-[16ch] truncate sm:inline", children: label }),
1284
+ /* @__PURE__ */ jsxRuntime.jsx(
1285
+ "svg",
1286
+ {
1287
+ width: "9",
1288
+ height: "9",
1289
+ viewBox: "0 0 10 10",
1290
+ "aria-hidden": true,
1291
+ className: "opacity-60 transition-transform " + (open ? "rotate-180" : "rotate-0"),
1292
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1293
+ "path",
1294
+ {
1295
+ d: "M2 4 L5 7 L8 4",
1296
+ stroke: "currentColor",
1297
+ strokeWidth: "1.5",
1298
+ fill: "none",
1299
+ strokeLinecap: "round"
1300
+ }
1301
+ )
1302
+ }
1303
+ )
1304
+ ]
1305
+ }
1306
+ ),
1307
+ open && /* @__PURE__ */ jsxRuntime.jsxs(
1308
+ "div",
1309
+ {
1310
+ role: "menu",
1311
+ "aria-label": "Account menu",
1312
+ 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",
1313
+ "data-oc-account-menu-popover": "",
1314
+ children: [
1315
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-border border-b p-3", children: [
1316
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-primary mb-1 font-mono text-[10px] tracking-widest uppercase", children: [
1317
+ "\xA7 signed in \xB7 ",
1318
+ hostname,
1319
+ tabPinned ? /* @__PURE__ */ jsxRuntime.jsxs(
1320
+ "span",
1321
+ {
1322
+ className: "text-muted-foreground/70 normal-case",
1323
+ "data-oc-account-menu-tab-pin": "",
1324
+ title: "This tab keeps this account even if you switch accounts in another tab",
1325
+ children: [
1326
+ " ",
1327
+ "\xB7 this tab"
1328
+ ]
1329
+ }
1330
+ ) : null
1331
+ ] }),
1332
+ /* @__PURE__ */ jsxRuntime.jsx(CopyableDid, { did: account.didOc }),
1333
+ displayName ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-muted-foreground/80 mt-1 font-mono text-[10px] tracking-wide", children: displayName }) : null
1334
+ ] }),
1335
+ /* @__PURE__ */ jsxRuntime.jsx(
1336
+ IdentityPromoteSection,
1337
+ {
1338
+ didOc: account.didOc,
1339
+ nostrNpub: account.nostrNpub ?? null,
1340
+ current: account.displayIdentity,
1341
+ open,
1342
+ setDisplayIdentity
1343
+ }
1344
+ ),
1345
+ /* @__PURE__ */ jsxRuntime.jsx(
1346
+ AccountsSection,
1347
+ {
1348
+ roster: roster ?? [],
1349
+ switchAccount,
1350
+ addAccountUrl,
1351
+ signOut,
1352
+ onActionStart: () => setOpen(false)
1353
+ }
1354
+ ),
1355
+ primaryNavLinks && primaryNavLinks.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(
1356
+ PopoverSection,
1357
+ {
1358
+ label: "navigate",
1359
+ items: primaryNavLinks,
1360
+ onItemClick: () => setOpen(false),
1361
+ className: "hidden md:block"
1362
+ }
1363
+ ) : null,
1364
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-1", "data-oc-account-menu-section": "account", children: [
1365
+ menuItems?.map((item) => {
1366
+ const onClick = () => setOpen(false);
1367
+ const cls = "hover:bg-accent flex items-center gap-2 px-3 py-2 font-mono text-[11px] tracking-wide transition-colors";
1368
+ const inner = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1369
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", "aria-hidden": true, children: "\u2192" }),
1370
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1", children: item.label }),
1371
+ item.external ? /* @__PURE__ */ jsxRuntime.jsx(
1165
1372
  "span",
1166
1373
  {
1167
- className: "text-muted-foreground/70 normal-case",
1168
- "data-oc-account-menu-tab-pin": "",
1169
- title: "This tab keeps this account even if you switch accounts in another tab",
1170
- children: [
1171
- " ",
1172
- "\xB7 this tab"
1173
- ]
1374
+ className: "text-muted-foreground/70 text-[10px]",
1375
+ "aria-hidden": true,
1376
+ children: "\u2197"
1174
1377
  }
1175
1378
  ) : null
1176
- ] }),
1177
- /* @__PURE__ */ jsxRuntime.jsx(CopyableDid, { did: account.didOc }),
1178
- displayName ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-muted-foreground/80 mt-1 font-mono text-[10px] tracking-wide", children: displayName }) : null
1179
- ] }),
1180
- /* @__PURE__ */ jsxRuntime.jsx(
1181
- IdentityPromoteSection,
1182
- {
1183
- didOc: account.didOc,
1184
- nostrNpub: account.nostrNpub ?? null,
1185
- current: account.displayIdentity,
1186
- open,
1187
- setDisplayIdentity
1188
- }
1189
- ),
1190
- /* @__PURE__ */ jsxRuntime.jsx(
1191
- AccountsSection,
1192
- {
1193
- roster: roster ?? [],
1194
- switchAccount,
1195
- addAccountUrl,
1196
- signOut,
1197
- onActionStart: () => setOpen(false)
1198
- }
1199
- ),
1200
- primaryNavLinks && primaryNavLinks.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(
1201
- PopoverSection,
1202
- {
1203
- label: "navigate",
1204
- items: primaryNavLinks,
1205
- onItemClick: () => setOpen(false)
1206
- }
1207
- ) : null,
1208
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-1", "data-oc-account-menu-section": "account", children: [
1209
- 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,
1210
- menuItems?.map((item) => {
1211
- const onClick = () => setOpen(false);
1212
- const cls = "hover:bg-accent flex items-center gap-2 px-3 py-2 font-mono text-[11px] tracking-wide transition-colors";
1213
- const inner = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1214
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", "aria-hidden": true, children: "\u2192" }),
1215
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1", children: item.label }),
1216
- item.external ? /* @__PURE__ */ jsxRuntime.jsx(
1217
- "span",
1218
- {
1219
- className: "text-muted-foreground/70 text-[10px]",
1220
- "aria-hidden": true,
1221
- children: "\u2197"
1222
- }
1223
- ) : null
1224
- ] });
1225
- return item.external ? /* @__PURE__ */ jsxRuntime.jsx(
1226
- "a",
1227
- {
1228
- href: item.href,
1229
- target: "_blank",
1230
- rel: "noreferrer",
1231
- onClick,
1232
- role: "menuitem",
1233
- className: cls,
1234
- "data-oc-account-menu-item": "",
1235
- children: inner
1236
- },
1237
- item.href
1238
- ) : /* @__PURE__ */ jsxRuntime.jsx(
1239
- Link5__default.default,
1240
- {
1241
- href: item.href,
1242
- onClick,
1243
- role: "menuitem",
1244
- className: cls,
1245
- "data-oc-account-menu-item": "",
1246
- children: inner
1247
- },
1248
- item.href
1249
- );
1250
- }),
1251
- familyDashboardEnabled ? /* @__PURE__ */ jsxRuntime.jsxs(
1379
+ ] });
1380
+ return item.external ? /* @__PURE__ */ jsxRuntime.jsx(
1252
1381
  "a",
1253
1382
  {
1254
- href: "https://ochk.io/dashboard",
1383
+ href: item.href,
1255
1384
  target: "_blank",
1256
1385
  rel: "noreferrer",
1257
- onClick: () => setOpen(false),
1386
+ onClick,
1258
1387
  role: "menuitem",
1259
- className: "hover:bg-accent flex items-center gap-2 px-3 py-2 font-mono text-[11px] tracking-wide transition-colors",
1388
+ className: cls,
1260
1389
  "data-oc-account-menu-item": "",
1261
- "data-oc-account-menu-family-dashboard": "",
1262
- children: [
1263
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", "aria-hidden": true, children: "\u2192" }),
1264
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1", children: "family dashboard" }),
1265
- /* @__PURE__ */ jsxRuntime.jsx(
1266
- "span",
1267
- {
1268
- className: "text-muted-foreground/70 text-[10px]",
1269
- "aria-hidden": true,
1270
- children: "\u2197"
1271
- }
1272
- )
1273
- ]
1274
- }
1275
- ) : null,
1276
- /* @__PURE__ */ jsxRuntime.jsxs(
1277
- "button",
1390
+ children: inner
1391
+ },
1392
+ item.href
1393
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
1394
+ Link5__default.default,
1278
1395
  {
1279
- type: "button",
1396
+ href: item.href,
1397
+ onClick,
1280
1398
  role: "menuitem",
1281
- onClick: () => {
1282
- setOpen(false);
1283
- void (async () => {
1284
- await signOut();
1285
- if (typeof window !== "undefined") {
1286
- window.location.assign(signOutRedirect);
1287
- }
1288
- })();
1289
- },
1290
- 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",
1399
+ className: cls,
1291
1400
  "data-oc-account-menu-item": "",
1292
- "data-oc-account-menu-signout": "",
1293
- children: [
1294
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", "aria-hidden": true, children: "\u2192" }),
1295
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1", children: "sign out" })
1296
- ]
1297
- }
1298
- )
1299
- ] }),
1300
- secondaryNavLinks && secondaryNavLinks.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(
1301
- PopoverSection,
1401
+ children: inner
1402
+ },
1403
+ item.href
1404
+ );
1405
+ }),
1406
+ familyDashboardEnabled ? /* @__PURE__ */ jsxRuntime.jsxs(
1407
+ "a",
1302
1408
  {
1303
- label: "more",
1304
- items: secondaryNavLinks,
1305
- onItemClick: () => setOpen(false),
1306
- bordered: true
1409
+ href: "https://ochk.io/dashboard",
1410
+ target: "_blank",
1411
+ rel: "noreferrer",
1412
+ onClick: () => setOpen(false),
1413
+ role: "menuitem",
1414
+ className: "hover:bg-accent flex items-center gap-2 px-3 py-2 font-mono text-[11px] tracking-wide transition-colors",
1415
+ "data-oc-account-menu-item": "",
1416
+ "data-oc-account-menu-family-dashboard": "",
1417
+ children: [
1418
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", "aria-hidden": true, children: "\u2192" }),
1419
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1", children: "family dashboard" }),
1420
+ /* @__PURE__ */ jsxRuntime.jsx(
1421
+ "span",
1422
+ {
1423
+ className: "text-muted-foreground/70 text-[10px]",
1424
+ "aria-hidden": true,
1425
+ children: "\u2197"
1426
+ }
1427
+ )
1428
+ ]
1307
1429
  }
1308
1430
  ) : null,
1309
- build ? /* @__PURE__ */ jsxRuntime.jsx(BuildFooter, { hostname, build, state: siteState }) : null
1310
- ]
1311
- }
1312
- )
1313
- ]
1314
- }
1431
+ /* @__PURE__ */ jsxRuntime.jsxs(
1432
+ "button",
1433
+ {
1434
+ type: "button",
1435
+ role: "menuitem",
1436
+ onClick: () => {
1437
+ setOpen(false);
1438
+ void (async () => {
1439
+ await signOut();
1440
+ if (typeof window !== "undefined") {
1441
+ window.location.assign(signOutRedirect);
1442
+ }
1443
+ })();
1444
+ },
1445
+ 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",
1446
+ "data-oc-account-menu-item": "",
1447
+ "data-oc-account-menu-signout": "",
1448
+ children: [
1449
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", "aria-hidden": true, children: "\u2192" }),
1450
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1", children: "sign out" })
1451
+ ]
1452
+ }
1453
+ )
1454
+ ] }),
1455
+ secondaryNavLinks && secondaryNavLinks.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(
1456
+ PopoverSection,
1457
+ {
1458
+ label: "more",
1459
+ items: secondaryNavLinks,
1460
+ onItemClick: () => setOpen(false),
1461
+ bordered: true,
1462
+ className: "hidden md:block"
1463
+ }
1464
+ ) : null,
1465
+ build ? /* @__PURE__ */ jsxRuntime.jsx(BuildFooter, { hostname, build, state: siteState }) : null
1466
+ ]
1467
+ }
1468
+ )
1469
+ ] })
1315
1470
  );
1316
1471
  }
1317
1472
  function AccountsSection({
@@ -1424,33 +1579,22 @@ function PopoverSection({
1424
1579
  label,
1425
1580
  items,
1426
1581
  onItemClick,
1427
- bordered
1582
+ bordered,
1583
+ className
1428
1584
  }) {
1429
1585
  const cls = "hover:bg-accent flex items-center gap-2 px-3 py-2 font-mono text-[11px] tracking-wide transition-colors";
1430
1586
  return /* @__PURE__ */ jsxRuntime.jsxs(
1431
1587
  "div",
1432
1588
  {
1433
- className: "p-1 " + (bordered ? "border-border border-t" : ""),
1589
+ className: cn("p-1", bordered && "border-border border-t", className),
1434
1590
  "data-oc-account-menu-section": label,
1435
1591
  children: [
1436
1592
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-muted-foreground/60 px-3 pt-2 pb-1 font-mono text-[10px] tracking-widest uppercase", children: [
1437
1593
  "\xA7 ",
1438
1594
  label
1439
1595
  ] }),
1440
- items.map((item) => {
1441
- const inner = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1442
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", "aria-hidden": true, children: "\u2192" }),
1443
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1", children: item.label }),
1444
- item.external ? /* @__PURE__ */ jsxRuntime.jsx(
1445
- "span",
1446
- {
1447
- className: "text-muted-foreground/70 text-[10px]",
1448
- "aria-hidden": true,
1449
- children: "\u2197"
1450
- }
1451
- ) : null
1452
- ] });
1453
- return item.external ? /* @__PURE__ */ jsxRuntime.jsx(
1596
+ items.map(
1597
+ (item) => item.external ? /* @__PURE__ */ jsxRuntime.jsxs(
1454
1598
  "a",
1455
1599
  {
1456
1600
  href: item.href,
@@ -1460,10 +1604,14 @@ function PopoverSection({
1460
1604
  role: "menuitem",
1461
1605
  className: cls,
1462
1606
  "data-oc-account-menu-item": "",
1463
- children: inner
1607
+ children: [
1608
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", "aria-hidden": true, children: "\u2192" }),
1609
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1", children: item.label }),
1610
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground/70 text-[10px]", "aria-hidden": true, children: "\u2197" })
1611
+ ]
1464
1612
  },
1465
1613
  item.href
1466
- ) : /* @__PURE__ */ jsxRuntime.jsx(
1614
+ ) : /* @__PURE__ */ jsxRuntime.jsxs(
1467
1615
  Link5__default.default,
1468
1616
  {
1469
1617
  href: item.href,
@@ -1471,11 +1619,14 @@ function PopoverSection({
1471
1619
  role: "menuitem",
1472
1620
  className: cls,
1473
1621
  "data-oc-account-menu-item": "",
1474
- children: inner
1622
+ children: [
1623
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", "aria-hidden": true, children: "\u2192" }),
1624
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1", children: item.label })
1625
+ ]
1475
1626
  },
1476
1627
  item.href
1477
- );
1478
- })
1628
+ )
1629
+ )
1479
1630
  ]
1480
1631
  }
1481
1632
  );
@@ -1527,146 +1678,54 @@ function isActive(pathname, link) {
1527
1678
  if (link.href === "/") return pathname === "/";
1528
1679
  return pathname === link.href || pathname.startsWith(link.href + "/");
1529
1680
  }
1530
- function ExternalGlyph() {
1531
- return /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, className: "text-muted-foreground/60 ml-1 text-[9px]", children: "\u2197" });
1532
- }
1533
1681
  function OcPrimaryNav({
1534
1682
  activePath,
1535
1683
  links,
1536
1684
  className
1537
1685
  }) {
1538
- const [open, setOpen] = React.useState(false);
1539
- const ref = React.useRef(null);
1540
- const menuId = React.useId();
1541
- React.useEffect(() => {
1542
- setOpen(false);
1543
- }, [activePath]);
1544
- React.useEffect(() => {
1545
- if (!open) return;
1546
- const onClick = (e) => {
1547
- if (ref.current && !ref.current.contains(e.target)) setOpen(false);
1548
- };
1549
- const onKey = (e) => {
1550
- if (e.key === "Escape") setOpen(false);
1551
- };
1552
- document.addEventListener("mousedown", onClick);
1553
- document.addEventListener("keydown", onKey);
1554
- return () => {
1555
- document.removeEventListener("mousedown", onClick);
1556
- document.removeEventListener("keydown", onKey);
1557
- };
1558
- }, [open]);
1559
- const inlineClass = (active) => "font-display shrink-0 px-2 py-1 sm:px-3 text-[11px] sm:text-[12px] font-semibold tracking-wider uppercase transition-colors " + (active ? "text-primary" : "text-muted-foreground hover:text-foreground");
1560
- const rowClass = (active) => "font-display flex items-center gap-2 px-3 py-2 text-[12px] font-semibold tracking-wider uppercase transition-colors " + (active ? "text-primary" : "text-muted-foreground hover:text-foreground hover:bg-accent");
1561
- function renderInline(link) {
1562
- const active = isActive(activePath, link);
1563
- const inner = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1564
- link.label,
1565
- link.external ? /* @__PURE__ */ jsxRuntime.jsx(ExternalGlyph, {}) : null
1566
- ] });
1567
- return link.external ? /* @__PURE__ */ jsxRuntime.jsx(
1568
- "a",
1569
- {
1570
- href: link.href,
1571
- target: "_blank",
1572
- rel: "noreferrer",
1573
- className: inlineClass(false),
1574
- "data-oc-primary-nav-item": "",
1575
- children: inner
1576
- },
1577
- link.href
1578
- ) : /* @__PURE__ */ jsxRuntime.jsx(
1579
- Link5__default.default,
1580
- {
1581
- href: link.href,
1582
- "aria-current": active ? "page" : void 0,
1583
- className: inlineClass(active),
1584
- "data-oc-primary-nav-item": active ? "active" : "sibling",
1585
- children: inner
1586
- },
1587
- link.href
1588
- );
1589
- }
1590
- function renderRow(link) {
1591
- const active = isActive(activePath, link);
1592
- const inner = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1593
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", "aria-hidden": true, children: "\u2192" }),
1594
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1", children: link.label }),
1595
- link.external ? /* @__PURE__ */ jsxRuntime.jsx(ExternalGlyph, {}) : null
1596
- ] });
1597
- return link.external ? /* @__PURE__ */ jsxRuntime.jsx(
1598
- "a",
1599
- {
1600
- href: link.href,
1601
- target: "_blank",
1602
- rel: "noreferrer",
1603
- role: "menuitem",
1604
- onClick: () => setOpen(false),
1605
- className: rowClass(false),
1606
- "data-oc-primary-nav-item": "",
1607
- children: inner
1608
- },
1609
- link.href
1610
- ) : /* @__PURE__ */ jsxRuntime.jsx(
1611
- Link5__default.default,
1612
- {
1613
- href: link.href,
1614
- role: "menuitem",
1615
- "aria-current": active ? "page" : void 0,
1616
- onClick: () => setOpen(false),
1617
- className: rowClass(active),
1618
- "data-oc-primary-nav-item": active ? "active" : "sibling",
1619
- children: inner
1620
- },
1621
- link.href
1622
- );
1623
- }
1624
- return /* @__PURE__ */ jsxRuntime.jsxs(
1625
- "div",
1686
+ return /* @__PURE__ */ jsxRuntime.jsx(
1687
+ "nav",
1626
1688
  {
1627
- ref,
1628
- className: "relative flex items-center justify-center " + (className ?? ""),
1689
+ "aria-label": "primary",
1690
+ className: "hidden items-center gap-0.5 sm:gap-1 md:flex " + (className ?? ""),
1629
1691
  "data-oc-primary-nav": "",
1630
- children: [
1631
- /* @__PURE__ */ jsxRuntime.jsx(
1632
- "nav",
1633
- {
1634
- "aria-label": "primary",
1635
- className: "hidden items-center gap-0.5 sm:gap-1 md:flex",
1636
- children: links.map(renderInline)
1637
- }
1638
- ),
1639
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "md:hidden", children: [
1640
- /* @__PURE__ */ jsxRuntime.jsx(
1641
- "button",
1692
+ children: links.map((link) => {
1693
+ const active = isActive(activePath, link);
1694
+ const cls = "font-display shrink-0 px-2 py-1 sm:px-3 text-[11px] sm:text-[12px] font-semibold tracking-wider uppercase transition-colors " + (active ? "text-primary" : "text-muted-foreground hover:text-foreground");
1695
+ const content = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1696
+ link.label,
1697
+ link.external ? /* @__PURE__ */ jsxRuntime.jsx(
1698
+ "span",
1642
1699
  {
1643
- type: "button",
1644
- onClick: () => setOpen((v) => !v),
1645
- "aria-haspopup": "menu",
1646
- "aria-expanded": open,
1647
- "aria-controls": menuId,
1648
- "aria-label": "site navigation",
1649
- className: "border-input bg-background hover:bg-accent text-muted-foreground inline-flex size-8 items-center justify-center rounded-md border transition-colors",
1650
- "data-oc-primary-nav-toggle": "",
1651
- children: open ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "size-4", "aria-hidden": true }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Menu, { className: "size-4", "aria-hidden": true })
1700
+ "aria-hidden": true,
1701
+ className: "text-muted-foreground/60 ml-1 text-[9px]",
1702
+ children: "\u2197"
1652
1703
  }
1653
- ),
1654
- open && /* @__PURE__ */ jsxRuntime.jsxs(
1655
- "div",
1656
- {
1657
- id: menuId,
1658
- role: "menu",
1659
- "aria-label": "primary",
1660
- className: "border-border bg-popover text-popover-foreground absolute top-[calc(100%+8px)] left-1/2 z-50 w-[min(15rem,calc(100vw-1rem))] -translate-x-1/2 border p-1 shadow-xl",
1661
- "data-oc-primary-nav-popover": "",
1662
- children: [
1663
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-muted-foreground/60 px-3 pt-2 pb-1 font-mono text-[10px] tracking-widest uppercase", children: "\xA7 navigate" }),
1664
- links.map(renderRow)
1665
- ]
1666
- }
1667
- )
1668
- ] })
1669
- ]
1704
+ ) : null
1705
+ ] });
1706
+ return link.external ? /* @__PURE__ */ jsxRuntime.jsx(
1707
+ "a",
1708
+ {
1709
+ href: link.href,
1710
+ target: "_blank",
1711
+ rel: "noreferrer",
1712
+ className: cls,
1713
+ "data-oc-primary-nav-item": "",
1714
+ children: content
1715
+ },
1716
+ link.href
1717
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
1718
+ Link5__default.default,
1719
+ {
1720
+ href: link.href,
1721
+ "aria-current": active ? "page" : void 0,
1722
+ className: cls,
1723
+ "data-oc-primary-nav-item": active ? "active" : "sibling",
1724
+ children: content
1725
+ },
1726
+ link.href
1727
+ );
1728
+ })
1670
1729
  }
1671
1730
  );
1672
1731
  }