@luxfi/ui 7.3.2 → 7.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (154) hide show
  1. package/dist/alert.cjs +2 -2
  2. package/dist/alert.js +1 -1
  3. package/dist/avatar.cjs +7 -6
  4. package/dist/avatar.js +7 -5
  5. package/dist/badge.cjs +36 -38
  6. package/dist/badge.js +31 -33
  7. package/dist/bank.cjs +13 -13
  8. package/dist/bank.d.cts +31 -24
  9. package/dist/bank.d.ts +31 -24
  10. package/dist/bank.js +1 -1
  11. package/dist/button.cjs +3 -3
  12. package/dist/button.js +1 -1
  13. package/dist/checkbox.cjs +4 -4
  14. package/dist/checkbox.d.cts +3 -2
  15. package/dist/checkbox.d.ts +3 -2
  16. package/dist/checkbox.js +5 -4
  17. package/dist/chrome.cjs +950 -0
  18. package/dist/chrome.d.cts +93 -0
  19. package/dist/chrome.d.ts +93 -0
  20. package/dist/chrome.js +921 -0
  21. package/dist/close-button.cjs +2 -2
  22. package/dist/close-button.js +1 -1
  23. package/dist/dialog.cjs +13 -14
  24. package/dist/dialog.d.cts +58 -5
  25. package/dist/dialog.d.ts +58 -5
  26. package/dist/dialog.js +1 -2
  27. package/dist/drawer.cjs +87 -21
  28. package/dist/drawer.js +85 -19
  29. package/dist/expiration-selector.cjs +3 -2
  30. package/dist/expiration-selector.js +3 -2
  31. package/dist/greeks-display.cjs +6 -6
  32. package/dist/greeks-display.js +6 -6
  33. package/dist/gui.cjs +13 -0
  34. package/dist/gui.d.cts +2 -0
  35. package/dist/gui.d.ts +2 -0
  36. package/dist/gui.js +2 -0
  37. package/dist/heading.cjs +4 -2
  38. package/dist/heading.js +4 -2
  39. package/dist/iam.cjs +206 -0
  40. package/dist/iam.d.cts +65 -0
  41. package/dist/iam.d.ts +65 -0
  42. package/dist/iam.js +201 -0
  43. package/dist/icon-button.cjs +2 -2
  44. package/dist/icon-button.js +1 -1
  45. package/dist/icons.cjs +13 -0
  46. package/dist/icons.d.cts +1 -0
  47. package/dist/icons.d.ts +1 -0
  48. package/dist/icons.js +2 -0
  49. package/dist/identity.cjs +420 -0
  50. package/dist/identity.d.cts +64 -0
  51. package/dist/identity.d.ts +64 -0
  52. package/dist/identity.js +398 -0
  53. package/dist/index.cjs +1699 -860
  54. package/dist/index.d.cts +12 -4
  55. package/dist/index.d.ts +12 -4
  56. package/dist/index.js +1618 -802
  57. package/dist/input.cjs +13 -3
  58. package/dist/input.d.cts +6 -0
  59. package/dist/input.d.ts +6 -0
  60. package/dist/input.js +13 -3
  61. package/dist/lux.config.cjs +77 -0
  62. package/dist/lux.config.d.cts +433 -0
  63. package/dist/lux.config.d.ts +433 -0
  64. package/dist/lux.config.js +69 -0
  65. package/dist/menu.cjs +4 -4
  66. package/dist/menu.js +4 -4
  67. package/dist/next.cjs +99 -0
  68. package/dist/next.d.cts +29 -0
  69. package/dist/next.d.ts +29 -0
  70. package/dist/next.js +96 -0
  71. package/dist/option-chain.cjs +1 -1
  72. package/dist/option-chain.js +1 -1
  73. package/dist/option-position.cjs +2 -1
  74. package/dist/option-position.js +2 -1
  75. package/dist/pnl-diagram.cjs +8 -6
  76. package/dist/pnl-diagram.js +8 -6
  77. package/dist/popover.cjs +8 -9
  78. package/dist/popover.js +1 -2
  79. package/dist/progress.cjs +7 -6
  80. package/dist/progress.js +7 -5
  81. package/dist/provider.cjs +199 -5
  82. package/dist/provider.d.cts +16 -3
  83. package/dist/provider.d.ts +16 -3
  84. package/dist/provider.js +195 -6
  85. package/dist/radio.cjs +9 -7
  86. package/dist/radio.js +10 -7
  87. package/dist/separator.cjs +3 -1
  88. package/dist/separator.js +3 -1
  89. package/dist/slider.cjs +28 -16
  90. package/dist/slider.js +28 -15
  91. package/dist/strategy-builder.cjs +2 -1
  92. package/dist/strategy-builder.js +2 -1
  93. package/dist/switch.cjs +11 -12
  94. package/dist/switch.js +12 -12
  95. package/dist/tag.cjs +38 -41
  96. package/dist/tag.js +31 -34
  97. package/dist/textarea.cjs +13 -3
  98. package/dist/textarea.d.cts +2 -0
  99. package/dist/textarea.d.ts +2 -0
  100. package/dist/textarea.js +13 -3
  101. package/dist/tooltip.cjs +31 -33
  102. package/dist/tooltip.js +25 -27
  103. package/dist/use-narrow.cjs +46 -0
  104. package/dist/use-narrow.d.cts +12 -0
  105. package/dist/use-narrow.d.ts +12 -0
  106. package/dist/use-narrow.js +20 -0
  107. package/dist/vite.cjs +40 -0
  108. package/dist/vite.d.cts +29 -0
  109. package/dist/vite.d.ts +29 -0
  110. package/dist/vite.js +38 -0
  111. package/dist/white-label.cjs +132 -0
  112. package/dist/white-label.d.cts +59 -0
  113. package/dist/white-label.d.ts +59 -0
  114. package/dist/white-label.js +124 -0
  115. package/package.json +95 -17
  116. package/src/avatar.tsx +22 -16
  117. package/src/bank.tsx +2 -2
  118. package/src/button.tsx +1 -1
  119. package/src/checkbox.tsx +15 -10
  120. package/src/chrome.tsx +459 -0
  121. package/src/close-button.tsx +1 -1
  122. package/src/dialog.tsx +1 -1
  123. package/src/drawer.tsx +83 -10
  124. package/src/expiration-selector.tsx +3 -2
  125. package/src/greeks-display.tsx +9 -6
  126. package/src/gui.ts +17 -0
  127. package/src/heading.tsx +12 -8
  128. package/src/iam.ts +170 -0
  129. package/src/icon-button.tsx +1 -1
  130. package/src/icons.ts +18 -0
  131. package/src/identity.tsx +318 -0
  132. package/src/index.ts +50 -1
  133. package/src/input.tsx +24 -4
  134. package/src/lux.config.ts +82 -0
  135. package/src/menu.tsx +4 -4
  136. package/src/next.ts +142 -0
  137. package/src/option-chain.tsx +1 -1
  138. package/src/option-position.tsx +2 -1
  139. package/src/pnl-diagram.tsx +11 -6
  140. package/src/popover.tsx +1 -1
  141. package/src/progress.tsx +15 -8
  142. package/src/provider.tsx +92 -12
  143. package/src/radio.tsx +15 -11
  144. package/src/separator.tsx +8 -3
  145. package/src/slider.tsx +35 -19
  146. package/src/strategy-builder.tsx +3 -2
  147. package/src/switch.tsx +17 -16
  148. package/src/textarea.tsx +18 -4
  149. package/src/tooltip.tsx +4 -23
  150. package/src/use-narrow.ts +40 -0
  151. package/src/vite.ts +78 -0
  152. package/src/white-label.ts +240 -0
  153. package/tokens.css +544 -319
  154. package/src/tokens.css +0 -438
@@ -0,0 +1,950 @@
1
+ "use client";
2
+ 'use strict';
3
+
4
+ var React6 = require('react');
5
+ var lucideReact = require('lucide-react');
6
+ var gui = require('@hanzo/gui');
7
+ var RadixDialog = require('@radix-ui/react-dialog');
8
+ var clsx = require('clsx');
9
+ var tailwindMerge = require('tailwind-merge');
10
+ var jsxRuntime = require('react/jsx-runtime');
11
+ var reactQuery = require('@tanstack/react-query');
12
+ var DropdownMenu = require('@radix-ui/react-dropdown-menu');
13
+
14
+ function _interopNamespace(e) {
15
+ if (e && e.__esModule) return e;
16
+ var n = Object.create(null);
17
+ if (e) {
18
+ Object.keys(e).forEach(function (k) {
19
+ if (k !== 'default') {
20
+ var d = Object.getOwnPropertyDescriptor(e, k);
21
+ Object.defineProperty(n, k, d.get ? d : {
22
+ enumerable: true,
23
+ get: function () { return e[k]; }
24
+ });
25
+ }
26
+ });
27
+ }
28
+ n.default = e;
29
+ return Object.freeze(n);
30
+ }
31
+
32
+ var React6__namespace = /*#__PURE__*/_interopNamespace(React6);
33
+ var RadixDialog__namespace = /*#__PURE__*/_interopNamespace(RadixDialog);
34
+ var DropdownMenu__namespace = /*#__PURE__*/_interopNamespace(DropdownMenu);
35
+
36
+ var NARROW_PX = 640;
37
+ function useBelow(px) {
38
+ const [below, setBelow] = React6__namespace.useState(false);
39
+ React6__namespace.useEffect(() => {
40
+ const mql = window.matchMedia(`(max-width: ${px - 1}px)`);
41
+ const apply = () => setBelow(mql.matches);
42
+ apply();
43
+ mql.addEventListener("change", apply);
44
+ return () => mql.removeEventListener("change", apply);
45
+ }, [px]);
46
+ return below;
47
+ }
48
+ var useIsNarrow = () => useBelow(NARROW_PX);
49
+ function cn(...inputs) {
50
+ return tailwindMerge.twMerge(clsx.clsx(inputs));
51
+ }
52
+ var CLOSE_ICON_PATH = "M9.44 8.035a.791.791 0 0 0 1.12 0l3.802-3.803a.791.791 0 0 1 1.119 0l.287.287a.79.79 0 0 1 0 1.119L11.965 9.44a.79.79 0 0 0 0 1.118l3.803 3.803a.791.791 0 0 1 0 1.119l-.287.287a.791.791 0 0 1-1.119 0l-3.803-3.803a.79.79 0 0 0-1.118 0l-3.803 3.803a.79.79 0 0 1-1.119 0l-.287-.287a.791.791 0 0 1 0-1.119l3.803-3.803a.791.791 0 0 0 0-1.118L4.232 5.638a.791.791 0 0 1 0-1.119l.287-.287a.791.791 0 0 1 1.119 0L9.44 8.035Z";
53
+ var CloseButtonFrame = gui.styled(gui.View, {
54
+ name: "LuxCloseButton",
55
+ render: /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", "aria-label": "Close" }),
56
+ role: "button",
57
+ cursor: "pointer",
58
+ display: "inline-flex",
59
+ alignItems: "center",
60
+ justifyContent: "center",
61
+ width: 20,
62
+ height: 20,
63
+ minWidth: 0,
64
+ flexShrink: 1,
65
+ padding: 0,
66
+ borderRadius: 4,
67
+ borderWidth: 0,
68
+ overflow: "hidden",
69
+ backgroundColor: "transparent",
70
+ hoverStyle: {
71
+ backgroundColor: "transparent"
72
+ },
73
+ variants: {
74
+ disabled: {
75
+ true: {
76
+ opacity: 0.4,
77
+ pointerEvents: "none"
78
+ }
79
+ }
80
+ }
81
+ });
82
+ var CLOSE_BUTTON_CLASSES = [
83
+ "text-[var(--closeButton-fg,currentColor)]",
84
+ "hover:text-[var(--hover-color,currentColor)]",
85
+ "disabled:opacity-40"
86
+ ].join(" ");
87
+ var CloseButton = React6__namespace.forwardRef(function CloseButton2(props, ref) {
88
+ const { variant: _variant, size: _size, className, children, ...rest } = props;
89
+ return /* @__PURE__ */ jsxRuntime.jsx(
90
+ CloseButtonFrame,
91
+ {
92
+ ref,
93
+ className: [CLOSE_BUTTON_CLASSES, className].filter(Boolean).join(" "),
94
+ ...rest,
95
+ children: children ?? /* @__PURE__ */ jsxRuntime.jsx(
96
+ "svg",
97
+ {
98
+ className: "size-5",
99
+ viewBox: "0 0 20 20",
100
+ fill: "none",
101
+ "aria-hidden": "true",
102
+ children: /* @__PURE__ */ jsxRuntime.jsx(
103
+ "path",
104
+ {
105
+ d: CLOSE_ICON_PATH,
106
+ fill: "currentColor"
107
+ }
108
+ )
109
+ }
110
+ )
111
+ }
112
+ );
113
+ });
114
+ var DrawerPlacementContext = React6__namespace.createContext("right");
115
+ var DrawerSizeContext = React6__namespace.createContext("md");
116
+ var DrawerStateContext = React6__namespace.createContext({
117
+ open: false,
118
+ setOpen: () => {
119
+ },
120
+ modal: true
121
+ });
122
+ var DrawerRoot = (props) => {
123
+ const {
124
+ children,
125
+ open,
126
+ defaultOpen,
127
+ onOpenChange,
128
+ placement = "right",
129
+ modal = true,
130
+ size = "md"
131
+ } = props;
132
+ const [uncontrolled, setUncontrolled] = React6__namespace.useState(defaultOpen ?? false);
133
+ const isControlled = open !== void 0;
134
+ const isOpen = isControlled ? open : uncontrolled;
135
+ const setOpen = React6__namespace.useCallback((nextOpen) => {
136
+ if (!isControlled) setUncontrolled(nextOpen);
137
+ onOpenChange?.({ open: nextOpen });
138
+ }, [isControlled, onOpenChange]);
139
+ const state = React6__namespace.useMemo(
140
+ () => ({ open: isOpen, setOpen, modal }),
141
+ [isOpen, setOpen, modal]
142
+ );
143
+ return /* @__PURE__ */ jsxRuntime.jsx(DrawerPlacementContext.Provider, { value: placement, children: /* @__PURE__ */ jsxRuntime.jsx(DrawerSizeContext.Provider, { value: size, children: /* @__PURE__ */ jsxRuntime.jsx(DrawerStateContext.Provider, { value: state, children: /* @__PURE__ */ jsxRuntime.jsx(
144
+ RadixDialog__namespace.Root,
145
+ {
146
+ open: isOpen,
147
+ onOpenChange: setOpen,
148
+ modal,
149
+ children
150
+ }
151
+ ) }) }) });
152
+ };
153
+ var PLACEMENT_CLASSES = {
154
+ right: [
155
+ "inset-y-0 right-0",
156
+ "data-[state=open]:animate-in data-[state=open]:slide-in-from-right",
157
+ "data-[state=closed]:animate-out data-[state=closed]:slide-out-to-right"
158
+ ].join(" "),
159
+ left: [
160
+ "inset-y-0 left-0",
161
+ "data-[state=open]:animate-in data-[state=open]:slide-in-from-left",
162
+ "data-[state=closed]:animate-out data-[state=closed]:slide-out-to-left"
163
+ ].join(" "),
164
+ top: [
165
+ "inset-x-0 top-0",
166
+ "data-[state=open]:animate-in data-[state=open]:slide-in-from-top",
167
+ "data-[state=closed]:animate-out data-[state=closed]:slide-out-to-top"
168
+ ].join(" "),
169
+ bottom: [
170
+ "inset-x-0 bottom-0",
171
+ "data-[state=open]:animate-in data-[state=open]:slide-in-from-bottom",
172
+ "data-[state=closed]:animate-out data-[state=closed]:slide-out-to-bottom"
173
+ ].join(" ")
174
+ };
175
+ var SIZE_CLASSES = {
176
+ right: { xs: "w-60", sm: "w-80", md: "w-96", lg: "w-[480px]", xl: "w-[640px]", full: "w-screen" },
177
+ left: { xs: "w-60", sm: "w-80", md: "w-96", lg: "w-[480px]", xl: "w-[640px]", full: "w-screen" },
178
+ top: { xs: "h-40", sm: "h-60", md: "h-80", lg: "h-96", xl: "h-[480px]", full: "h-screen" },
179
+ bottom: { xs: "h-40", sm: "h-60", md: "h-80", lg: "h-96", xl: "h-[480px]", full: "h-screen" }
180
+ };
181
+ var DrawerContent = React6__namespace.forwardRef(
182
+ function DrawerContent2(props, ref) {
183
+ const { children, portalled = true, portalRef, offset: _offset, backdrop = true, className, ...rest } = props;
184
+ const placement = React6__namespace.useContext(DrawerPlacementContext);
185
+ const size = React6__namespace.useContext(DrawerSizeContext);
186
+ const { open, setOpen, modal } = React6__namespace.useContext(DrawerStateContext);
187
+ const isNarrow = useIsNarrow();
188
+ if (isNarrow) {
189
+ return /* @__PURE__ */ jsxRuntime.jsxs(
190
+ gui.Sheet,
191
+ {
192
+ open,
193
+ onOpenChange: setOpen,
194
+ modal,
195
+ dismissOnSnapToBottom: true,
196
+ snapPointsMode: "percent",
197
+ snapPoints: [88],
198
+ transition: "medium",
199
+ children: [
200
+ backdrop && /* @__PURE__ */ jsxRuntime.jsx(
201
+ gui.Sheet.Overlay,
202
+ {
203
+ transition: "lazy",
204
+ enterStyle: { opacity: 0 },
205
+ exitStyle: { opacity: 0 },
206
+ className: "bg-black/50"
207
+ }
208
+ ),
209
+ /* @__PURE__ */ jsxRuntime.jsx(gui.Sheet.Handle, {}),
210
+ /* @__PURE__ */ jsxRuntime.jsx(
211
+ gui.Sheet.Frame,
212
+ {
213
+ unstyled: true,
214
+ className: cn(
215
+ "flex flex-col rounded-t-2xl bg-[var(--color-drawer-bg)] shadow-[var(--shadow-drawer)]",
216
+ className
217
+ ),
218
+ ...rest,
219
+ children
220
+ }
221
+ )
222
+ ]
223
+ }
224
+ );
225
+ }
226
+ const content = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
227
+ backdrop && /* @__PURE__ */ jsxRuntime.jsx(
228
+ RadixDialog__namespace.Overlay,
229
+ {
230
+ className: cn(
231
+ "fixed inset-0 z-50 bg-black/50",
232
+ "data-[state=open]:animate-in data-[state=open]:fade-in-0",
233
+ "data-[state=closed]:animate-out data-[state=closed]:fade-out-0"
234
+ )
235
+ }
236
+ ),
237
+ /* @__PURE__ */ jsxRuntime.jsx(
238
+ RadixDialog__namespace.Content,
239
+ {
240
+ ref,
241
+ className: cn(
242
+ "fixed z-50 flex flex-col bg-[var(--color-drawer-bg)] shadow-[var(--shadow-drawer)] duration-300",
243
+ PLACEMENT_CLASSES[placement] ?? PLACEMENT_CLASSES.right,
244
+ SIZE_CLASSES[placement]?.[size] ?? SIZE_CLASSES.right?.md,
245
+ className
246
+ ),
247
+ ...rest,
248
+ children
249
+ }
250
+ )
251
+ ] });
252
+ if (portalled) {
253
+ return /* @__PURE__ */ jsxRuntime.jsx(RadixDialog__namespace.Portal, { container: portalRef?.current ?? void 0, children: content });
254
+ }
255
+ return content;
256
+ }
257
+ );
258
+ React6__namespace.forwardRef(function DrawerCloseTrigger2(props, ref) {
259
+ return /* @__PURE__ */ jsxRuntime.jsx(RadixDialog__namespace.Close, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
260
+ CloseButton,
261
+ {
262
+ ref,
263
+ className: cn("absolute top-7 right-5", props.className),
264
+ ...props
265
+ }
266
+ ) });
267
+ });
268
+ var DrawerHeader = React6__namespace.forwardRef(
269
+ function DrawerHeader2({ className, ...props }, ref) {
270
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn("flex flex-col gap-1.5 p-6 pb-0", className), ...props });
271
+ }
272
+ );
273
+ var DrawerBody = React6__namespace.forwardRef(
274
+ function DrawerBody2({ className, ...props }, ref) {
275
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn("flex-1 overflow-auto p-6", className), ...props });
276
+ }
277
+ );
278
+ React6__namespace.forwardRef(
279
+ function DrawerFooter2({ className, ...props }, ref) {
280
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn("flex items-center justify-end gap-2 p-6 pt-0", className), ...props });
281
+ }
282
+ );
283
+ var DrawerTitle = RadixDialog__namespace.Title;
284
+
285
+ // src/white-label.ts
286
+ var LUX_BRAND = {
287
+ lux: "#7000FF",
288
+ zoo: "#6C5EFB",
289
+ hanzo: "#EA580C",
290
+ pars: "#1C3879"};
291
+ var PARS_GOLD = "#C8A45C";
292
+ var ORGS = {
293
+ lux: {
294
+ org: "lux",
295
+ name: "Lux",
296
+ domain: "lux.network",
297
+ iamDomain: "lux.id",
298
+ accent: LUX_BRAND.lux,
299
+ accentForeground: "#FFFFFF"
300
+ },
301
+ zoo: {
302
+ org: "zoo",
303
+ name: "Zoo",
304
+ domain: "zoo.ngo",
305
+ // Zoo's IdP is `id.zoo.network`, not a `zoo.id` apex — the one row in this
306
+ // table where the issuer is not `<org>.id`, and the one every hand-rolled
307
+ // per-app branding map got wrong.
308
+ iamDomain: "id.zoo.network",
309
+ accent: LUX_BRAND.zoo,
310
+ accentForeground: "#FFFFFF"
311
+ },
312
+ bootnode: {
313
+ org: "bootnode",
314
+ name: "Bootnode",
315
+ domain: "bootno.de",
316
+ iamDomain: "id.bootno.de",
317
+ accent: LUX_BRAND.lux,
318
+ accentForeground: "#FFFFFF"
319
+ },
320
+ hanzo: {
321
+ org: "hanzo",
322
+ name: "Hanzo",
323
+ domain: "hanzo.ai",
324
+ iamDomain: "hanzo.id",
325
+ accent: LUX_BRAND.hanzo,
326
+ accentForeground: "#FFFFFF"
327
+ },
328
+ pars: {
329
+ org: "pars",
330
+ name: "Pars",
331
+ domain: "pars.id",
332
+ iamDomain: "pars.id",
333
+ accent: LUX_BRAND.pars,
334
+ accentForeground: PARS_GOLD
335
+ }
336
+ };
337
+ var DOMAIN_ORG = [
338
+ ["lux.network", "lux"],
339
+ ["lux.cloud", "lux"],
340
+ ["lux.id", "lux"],
341
+ ["lux.finance", "lux"],
342
+ ["zoo.ngo", "zoo"],
343
+ ["zoo.network", "zoo"],
344
+ ["zoo.cloud", "zoo"],
345
+ ["zoo.id", "zoo"],
346
+ ["hanzo.ai", "hanzo"],
347
+ ["hanzo.cloud", "hanzo"],
348
+ ["hanzo.id", "hanzo"],
349
+ ["pars.id", "pars"],
350
+ ["parsdao.org", "pars"],
351
+ ["bootno.de", "bootnode", "platform"]
352
+ ];
353
+ var DEFAULT_ORG = "lux";
354
+ function normalizeHost(host) {
355
+ const noPort = host.trim().toLowerCase().split(":")[0] ?? "";
356
+ return noPort.replace(/\.$/, "");
357
+ }
358
+ function isUnder(host, domain) {
359
+ return host === domain || host.endsWith(`.${domain}`);
360
+ }
361
+ function matchDomain(host) {
362
+ let best;
363
+ for (const entry of DOMAIN_ORG) {
364
+ if (isUnder(host, entry[0]) && (!best || entry[0].length > best[0].length)) {
365
+ best = entry;
366
+ }
367
+ }
368
+ return best;
369
+ }
370
+ function appSlug(host, domain, apexApp) {
371
+ const sub = host === domain ? "" : host.slice(0, -(domain.length + 1));
372
+ const leftmost = sub.split(".")[0] ?? "";
373
+ if (leftmost && leftmost !== "www") return leftmost;
374
+ if (apexApp) return apexApp;
375
+ const label = domain.split(".")[0] ?? "";
376
+ const tld = domain.split(".").slice(1).join(".");
377
+ return tld.split(".")[0] || label;
378
+ }
379
+ function isLocal(host) {
380
+ return host === "localhost" || host.endsWith(".localhost") || host === "127.0.0.1" || host === "0.0.0.0" || host === "[::1]" || host.endsWith(".local");
381
+ }
382
+ function resolveWhiteLabel(host) {
383
+ const h = normalizeHost(host);
384
+ const match = h ? matchDomain(h) : void 0;
385
+ const org = match ? match[1] : DEFAULT_ORG;
386
+ const identity = ORGS[org];
387
+ const app = match ? appSlug(h, match[0], match[2]) : h && isLocal(h) ? "local" : "app";
388
+ return {
389
+ ...identity,
390
+ host: h,
391
+ app,
392
+ theme: `dark_${org}`,
393
+ issuer: `https://${identity.iamDomain}`,
394
+ clientId: `${org}-${app}`
395
+ };
396
+ }
397
+ new reactQuery.QueryClient({
398
+ defaultOptions: { queries: { refetchOnWindowFocus: false, retry: 1, staleTime: 3e4 } }
399
+ });
400
+ var WhiteLabelContext = React6__namespace.default.createContext(resolveWhiteLabel(""));
401
+ var useWhiteLabel = () => React6__namespace.default.useContext(WhiteLabelContext);
402
+ var IdentityContext = React6__namespace.createContext(null);
403
+ function useIdentity() {
404
+ const ctx = React6__namespace.useContext(IdentityContext);
405
+ const whiteLabel = useWhiteLabel();
406
+ const fallback = React6__namespace.useMemo(() => ({
407
+ status: "anonymous",
408
+ account: null,
409
+ orgs: [],
410
+ org: null,
411
+ projects: [],
412
+ project: null,
413
+ error: null,
414
+ whiteLabel,
415
+ setOrg: () => void 0,
416
+ setProject: () => void 0,
417
+ signIn: () => {
418
+ if (typeof window !== "undefined") window.location.assign("/login");
419
+ },
420
+ signOut: () => void 0,
421
+ reload: () => void 0
422
+ }), [whiteLabel]);
423
+ return ctx ?? fallback;
424
+ }
425
+ function parsePlacement(placement) {
426
+ if (!placement) {
427
+ return { side: "bottom", align: "start" };
428
+ }
429
+ const parts = placement.split("-");
430
+ const side = parts[0] ?? "bottom";
431
+ const alignPart = parts[1];
432
+ let align = "center";
433
+ if (alignPart === "start") {
434
+ align = "start";
435
+ } else if (alignPart === "end") {
436
+ align = "end";
437
+ }
438
+ return { side, align };
439
+ }
440
+ var PositioningContext = React6__namespace.createContext({
441
+ side: "bottom",
442
+ align: "start",
443
+ sideOffset: 4,
444
+ alignOffset: 0
445
+ });
446
+ var MenuRoot = (props) => {
447
+ const {
448
+ children,
449
+ open,
450
+ defaultOpen,
451
+ onOpenChange,
452
+ positioning,
453
+ modal = true,
454
+ // lazyMount / unmountOnExit have no direct Radix equivalent; Radix handles
455
+ // mount/unmount automatically.
456
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
457
+ lazyMount: _lazyMount,
458
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
459
+ unmountOnExit: _unmountOnExit
460
+ } = props;
461
+ const mergedPositioning = {
462
+ placement: "bottom-start",
463
+ ...positioning,
464
+ offset: {
465
+ mainAxis: 4,
466
+ ...positioning?.offset
467
+ }
468
+ };
469
+ const { side, align } = parsePlacement(mergedPositioning.placement);
470
+ const positioningValue = React6__namespace.useMemo(() => ({
471
+ side,
472
+ align,
473
+ sideOffset: mergedPositioning.offset?.mainAxis ?? 4,
474
+ alignOffset: mergedPositioning.offset?.crossAxis ?? 0
475
+ }), [side, align, mergedPositioning.offset?.mainAxis, mergedPositioning.offset?.crossAxis]);
476
+ const handleOpenChange = React6__namespace.useCallback((isOpen) => {
477
+ onOpenChange?.({ open: isOpen });
478
+ }, [onOpenChange]);
479
+ return /* @__PURE__ */ jsxRuntime.jsx(PositioningContext.Provider, { value: positioningValue, children: /* @__PURE__ */ jsxRuntime.jsx(
480
+ DropdownMenu__namespace.Root,
481
+ {
482
+ open,
483
+ defaultOpen,
484
+ onOpenChange: handleOpenChange,
485
+ modal,
486
+ children
487
+ }
488
+ ) });
489
+ };
490
+ var MenuTrigger = React6__namespace.forwardRef(function MenuTrigger2(props, ref) {
491
+ const { asChild = false, ...rest } = props;
492
+ return /* @__PURE__ */ jsxRuntime.jsx(DropdownMenu__namespace.Trigger, { asChild, ref, ...rest });
493
+ });
494
+ var MenuContent = React6__namespace.forwardRef(function MenuContent2(props, ref) {
495
+ const { portalled = true, portalRef, className, zIndex, minW, style, ...rest } = props;
496
+ const positioning = React6__namespace.useContext(PositioningContext);
497
+ const mergedStyle = {
498
+ ...style,
499
+ ...zIndex !== void 0 ? { zIndex: typeof zIndex === "string" ? `var(--z-index-${zIndex}, ${zIndex})` : zIndex } : {},
500
+ ...minW !== void 0 ? { minWidth: minW } : {}
501
+ };
502
+ const content = /* @__PURE__ */ jsxRuntime.jsx(
503
+ DropdownMenu__namespace.Content,
504
+ {
505
+ ref,
506
+ side: positioning.side,
507
+ align: positioning.align,
508
+ sideOffset: positioning.sideOffset,
509
+ alignOffset: positioning.alignOffset,
510
+ className: cn(
511
+ "z-50 min-w-[8rem] overflow-hidden rounded-lg p-1",
512
+ "border border-[var(--color-popover-border,var(--color-border-divider))]",
513
+ "bg-[var(--color-popover-bg,var(--color-dialog-bg))]",
514
+ "shadow-[0_4px_12px_var(--color-popover-shadow)]",
515
+ "outline-none",
516
+ "data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",
517
+ "data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
518
+ "data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2",
519
+ "data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
520
+ className
521
+ ),
522
+ style: Object.keys(mergedStyle).length > 0 ? mergedStyle : void 0,
523
+ ...rest
524
+ }
525
+ );
526
+ if (!portalled) {
527
+ return content;
528
+ }
529
+ return /* @__PURE__ */ jsxRuntime.jsx(DropdownMenu__namespace.Portal, { container: portalRef?.current ?? void 0, children: content });
530
+ });
531
+ var MenuItem = React6__namespace.forwardRef(function MenuItem2(props, ref) {
532
+ const { className, value: _value, asChild, closeOnSelect: _closeOnSelect, disabled, children, onClick, ...rest } = props;
533
+ return /* @__PURE__ */ jsxRuntime.jsx(
534
+ DropdownMenu__namespace.Item,
535
+ {
536
+ ref,
537
+ asChild,
538
+ disabled,
539
+ onClick,
540
+ className: cn(
541
+ "relative flex cursor-pointer select-none items-center gap-2 rounded-md px-2 py-1.5 text-sm",
542
+ "outline-none transition-colors",
543
+ "text-[var(--color-text-primary,inherit)]",
544
+ "data-[highlighted]:bg-[var(--color-popover-item-hover,rgba(0,0,0,0.04))]",
545
+ "data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
546
+ className
547
+ ),
548
+ ...rest,
549
+ children
550
+ }
551
+ );
552
+ });
553
+ React6__namespace.forwardRef(function MenuItemText2(props, ref) {
554
+ const { className, ...rest } = props;
555
+ return /* @__PURE__ */ jsxRuntime.jsx("span", { ref, className: cn("flex-1", className), ...rest });
556
+ });
557
+ React6__namespace.forwardRef(function MenuItemCommand2(props, ref) {
558
+ const { className, ...rest } = props;
559
+ return /* @__PURE__ */ jsxRuntime.jsx(
560
+ "span",
561
+ {
562
+ ref,
563
+ className: cn("ml-auto text-xs tracking-widest opacity-60", className),
564
+ ...rest
565
+ }
566
+ );
567
+ });
568
+ var MenuSeparator = React6__namespace.forwardRef(function MenuSeparator2(props, ref) {
569
+ const { className, ...rest } = props;
570
+ return /* @__PURE__ */ jsxRuntime.jsx(
571
+ DropdownMenu__namespace.Separator,
572
+ {
573
+ ref,
574
+ className: cn("-mx-1 my-1 h-px bg-[var(--color-border-divider)]", className),
575
+ ...rest
576
+ }
577
+ );
578
+ });
579
+ React6__namespace.forwardRef(function MenuItemGroup2(props, ref) {
580
+ const { title, children, className, ...rest } = props;
581
+ return /* @__PURE__ */ jsxRuntime.jsxs(DropdownMenu__namespace.Group, { ref, className, ...rest, children: [
582
+ title && /* @__PURE__ */ jsxRuntime.jsx(DropdownMenu__namespace.Label, { className: "px-2 py-1.5 text-xs font-semibold select-none opacity-60", children: title }),
583
+ children
584
+ ] });
585
+ });
586
+ React6__namespace.forwardRef(function MenuArrow2(props, ref) {
587
+ const { className, ...rest } = props;
588
+ return /* @__PURE__ */ jsxRuntime.jsx(
589
+ DropdownMenu__namespace.Arrow,
590
+ {
591
+ ref,
592
+ className: cn("fill-[var(--color-popover-bg,var(--color-dialog-bg))]", className),
593
+ ...rest
594
+ }
595
+ );
596
+ });
597
+ React6__namespace.forwardRef(function MenuCheckboxItem2(props, ref) {
598
+ const { className, children, checked, onCheckedChange, onClick, ...rest } = props;
599
+ return /* @__PURE__ */ jsxRuntime.jsxs(
600
+ DropdownMenu__namespace.CheckboxItem,
601
+ {
602
+ ref,
603
+ checked,
604
+ onCheckedChange,
605
+ onClick,
606
+ className: cn(
607
+ "relative flex cursor-pointer select-none items-center rounded-md py-1.5 pr-2 pl-8 text-sm",
608
+ "outline-none transition-colors",
609
+ "data-[highlighted]:bg-[var(--color-popover-item-hover,rgba(0,0,0,0.04))]",
610
+ "data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
611
+ className
612
+ ),
613
+ ...rest,
614
+ children: [
615
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(DropdownMenu__namespace.ItemIndicator, { children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "h-4 w-4" }) }) }),
616
+ children
617
+ ]
618
+ }
619
+ );
620
+ });
621
+ React6__namespace.forwardRef(function MenuRadioItemGroup2(props, ref) {
622
+ const { value, onValueChange, ...rest } = props;
623
+ return /* @__PURE__ */ jsxRuntime.jsx(
624
+ DropdownMenu__namespace.RadioGroup,
625
+ {
626
+ ref,
627
+ value,
628
+ onValueChange,
629
+ ...rest
630
+ }
631
+ );
632
+ });
633
+ React6__namespace.forwardRef(function MenuRadioItem2(props, ref) {
634
+ const { className, children, value, onClick, ...rest } = props;
635
+ const { value: _v, ...radixRest } = rest;
636
+ return /* @__PURE__ */ jsxRuntime.jsxs(
637
+ DropdownMenu__namespace.RadioItem,
638
+ {
639
+ ref,
640
+ value,
641
+ onClick,
642
+ className: cn(
643
+ "relative flex cursor-pointer select-none items-center rounded-md py-1.5 pr-2 pl-8 text-sm",
644
+ "outline-none transition-colors",
645
+ "data-[highlighted]:bg-[var(--color-popover-item-hover,rgba(0,0,0,0.04))]",
646
+ "data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
647
+ className
648
+ ),
649
+ children: [
650
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(DropdownMenu__namespace.ItemIndicator, { children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "h-4 w-4" }) }) }),
651
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children })
652
+ ]
653
+ }
654
+ );
655
+ });
656
+ React6__namespace.forwardRef(function MenuContextTrigger2(props, ref) {
657
+ const { asChild: _asChild, ...rest } = props;
658
+ return /* @__PURE__ */ jsxRuntime.jsx("span", { ref, ...rest });
659
+ });
660
+ React6__namespace.forwardRef(function MenuTriggerItem2(props, ref) {
661
+ const { startIcon, children, className, ...rest } = props;
662
+ return /* @__PURE__ */ jsxRuntime.jsx(DropdownMenu__namespace.Sub, { children: /* @__PURE__ */ jsxRuntime.jsxs(
663
+ DropdownMenu__namespace.SubTrigger,
664
+ {
665
+ ref,
666
+ className: cn(
667
+ "relative flex cursor-pointer select-none items-center gap-2 rounded-md px-2 py-1.5 text-sm",
668
+ "outline-none transition-colors",
669
+ "data-[highlighted]:bg-[var(--color-popover-item-hover,rgba(0,0,0,0.04))]",
670
+ className
671
+ ),
672
+ ...rest,
673
+ children: [
674
+ startIcon,
675
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1", children }),
676
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRight, { className: "h-4 w-4" })
677
+ ]
678
+ }
679
+ ) });
680
+ });
681
+ function initials(label) {
682
+ return label.split(/[\s._-]+/).filter(Boolean).map((w) => w[0]).join("").slice(0, 2).toUpperCase();
683
+ }
684
+ var Monogram = ({ label, logo }) => logo ? /* @__PURE__ */ jsxRuntime.jsx("img", { src: logo, alt: "", className: "h-5 w-5 shrink-0 rounded object-contain" }) : /* @__PURE__ */ jsxRuntime.jsx(
685
+ "span",
686
+ {
687
+ "aria-hidden": "true",
688
+ className: "flex h-5 w-5 shrink-0 items-center justify-center rounded bg-[rgba(127,127,127,0.22)] text-[10px] font-bold",
689
+ children: initials(label)
690
+ }
691
+ );
692
+ var Row = ({ item, onDone, menu }) => {
693
+ const body = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
694
+ item.icon,
695
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1 truncate", children: item.label }),
696
+ item.hint ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs opacity-60", children: item.hint }) : null,
697
+ item.selected ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { "aria-hidden": "true", className: "h-4 w-4 shrink-0" }) : null
698
+ ] });
699
+ const className = cn(
700
+ "flex w-full cursor-pointer select-none items-center gap-2.5 rounded-md px-2 py-2 text-left text-sm",
701
+ "hover:bg-[rgba(127,127,127,0.14)]",
702
+ item.danger && "text-[var(--color-text-error,#e5484d)]"
703
+ );
704
+ const activate = () => {
705
+ onDone();
706
+ item.onSelect?.();
707
+ };
708
+ const shared = {
709
+ "data-testid": `chrome-item-${item.id}`,
710
+ "aria-current": item.selected ? "true" : void 0,
711
+ className
712
+ };
713
+ const control = item.href ? /* @__PURE__ */ jsxRuntime.jsx("a", { href: item.href, ...shared, onClick: onDone, children: body }) : /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", ...shared, onClick: activate, children: body });
714
+ return menu ? /* @__PURE__ */ jsxRuntime.jsx(MenuItem, { value: item.id, asChild: true, children: control }) : control;
715
+ };
716
+ var Switcher = ({
717
+ title,
718
+ label,
719
+ icon,
720
+ items,
721
+ footer = [],
722
+ status = "ready",
723
+ empty = "Nothing here yet.",
724
+ onSignIn,
725
+ signInLabel = "Sign in",
726
+ error,
727
+ align = "start",
728
+ testId
729
+ }) => {
730
+ const [open, setOpen] = React6__namespace.useState(false);
731
+ const narrow = useIsNarrow();
732
+ const close = React6__namespace.useCallback(() => setOpen(false), []);
733
+ const message = status === "loading" ? "Loading\u2026" : status === "error" ? error ?? "Could not reach IAM." : status === "anonymous" ? null : items.length === 0 ? empty : null;
734
+ const rows = status === "anonymous" && onSignIn ? [{ id: "sign-in", label: signInLabel, icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.User, { "aria-hidden": "true", className: "h-4 w-4" }), onSelect: onSignIn }] : status === "ready" ? items : [];
735
+ const panel = (menu) => /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
736
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-2 pb-1 pt-1 text-[11px] font-semibold uppercase tracking-wide opacity-55", children: title }),
737
+ message ? /* @__PURE__ */ jsxRuntime.jsx("div", { "data-testid": "chrome-message", className: "px-2 py-2 text-sm opacity-70", children: message }) : null,
738
+ rows.map((item) => /* @__PURE__ */ jsxRuntime.jsx(Row, { item, onDone: close, menu }, item.id)),
739
+ footer.length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
740
+ menu ? /* @__PURE__ */ jsxRuntime.jsx(MenuSeparator, { className: "my-1 h-px bg-[var(--color-border-divider,rgba(127,127,127,0.25))]" }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "my-1 h-px bg-[var(--color-border-divider,rgba(127,127,127,0.25))]" }),
741
+ footer.map((item) => /* @__PURE__ */ jsxRuntime.jsx(Row, { item, onDone: close, menu }, item.id))
742
+ ] }) : null
743
+ ] });
744
+ const trigger = /* @__PURE__ */ jsxRuntime.jsxs(
745
+ "button",
746
+ {
747
+ type: "button",
748
+ "data-testid": testId,
749
+ "aria-label": title,
750
+ "aria-haspopup": "menu",
751
+ "aria-expanded": open,
752
+ className: cn(
753
+ "flex max-w-[14rem] items-center gap-2 rounded-md px-2 py-1.5 text-sm font-medium",
754
+ "hover:bg-[rgba(127,127,127,0.14)]"
755
+ ),
756
+ children: [
757
+ icon,
758
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: label }),
759
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronsUpDown, { "aria-hidden": "true", className: "h-3.5 w-3.5 shrink-0 opacity-60" })
760
+ ]
761
+ }
762
+ );
763
+ if (narrow) {
764
+ return /* @__PURE__ */ jsxRuntime.jsxs(DrawerRoot, { open, onOpenChange: (d) => setOpen(d.open), placement: "bottom", size: "md", children: [
765
+ React6__namespace.cloneElement(trigger, { onClick: () => setOpen(true) }),
766
+ /* @__PURE__ */ jsxRuntime.jsxs(DrawerContent, { "data-testid": testId ? `${testId}-panel` : void 0, children: [
767
+ /* @__PURE__ */ jsxRuntime.jsx(DrawerHeader, { children: /* @__PURE__ */ jsxRuntime.jsx(DrawerTitle, { children: title }) }),
768
+ /* @__PURE__ */ jsxRuntime.jsx(DrawerBody, { children: panel(false) })
769
+ ] })
770
+ ] });
771
+ }
772
+ return /* @__PURE__ */ jsxRuntime.jsxs(
773
+ MenuRoot,
774
+ {
775
+ open,
776
+ onOpenChange: (d) => setOpen(d.open),
777
+ positioning: { placement: align === "end" ? "bottom-end" : "bottom-start" },
778
+ children: [
779
+ /* @__PURE__ */ jsxRuntime.jsx(MenuTrigger, { asChild: true, children: trigger }),
780
+ /* @__PURE__ */ jsxRuntime.jsx(MenuContent, { minW: "16rem", "data-testid": testId ? `${testId}-panel` : void 0, children: panel(true) })
781
+ ]
782
+ }
783
+ );
784
+ };
785
+ var OrgSwitcher = () => {
786
+ const id = useIdentity();
787
+ return /* @__PURE__ */ jsxRuntime.jsx(
788
+ Switcher,
789
+ {
790
+ testId: "org-switcher",
791
+ title: "Organization",
792
+ label: id.org?.displayName || id.org?.name || id.whiteLabel.name,
793
+ icon: /* @__PURE__ */ jsxRuntime.jsx(Monogram, { label: id.org?.displayName || id.org?.name || id.whiteLabel.name, logo: id.org?.logo }),
794
+ status: id.status,
795
+ error: id.error,
796
+ empty: "No organizations for this account.",
797
+ onSignIn: id.signIn,
798
+ signInLabel: `Sign in with ${id.whiteLabel.iamDomain}`,
799
+ items: id.orgs.map((o) => ({
800
+ id: o.name,
801
+ label: o.displayName || o.name,
802
+ icon: /* @__PURE__ */ jsxRuntime.jsx(Monogram, { label: o.displayName || o.name, logo: o.logo }),
803
+ selected: o.name === id.org?.name,
804
+ onSelect: () => id.setOrg(o.name)
805
+ }))
806
+ }
807
+ );
808
+ };
809
+ var ProjectSwitcher = () => {
810
+ const id = useIdentity();
811
+ if (id.status === "ready" && id.projects.length === 0) return null;
812
+ return /* @__PURE__ */ jsxRuntime.jsx(
813
+ Switcher,
814
+ {
815
+ testId: "project-switcher",
816
+ title: "Project",
817
+ label: id.project?.displayName || id.project?.name || "Project",
818
+ icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Folder, { "aria-hidden": "true", className: "h-4 w-4 opacity-70" }),
819
+ status: id.status,
820
+ error: id.error,
821
+ empty: "No projects in this organization.",
822
+ onSignIn: id.signIn,
823
+ items: id.projects.map((p) => ({
824
+ id: p.name,
825
+ label: p.displayName || p.name,
826
+ icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Folder, { "aria-hidden": "true", className: "h-4 w-4 opacity-70" }),
827
+ selected: p.name === id.project?.name,
828
+ onSelect: () => id.setProject(p.name)
829
+ }))
830
+ }
831
+ );
832
+ };
833
+ var UserMenu = ({ items = [] }) => {
834
+ const id = useIdentity();
835
+ const who = id.account?.displayName || id.account?.email || id.account?.name || "Account";
836
+ return /* @__PURE__ */ jsxRuntime.jsx(
837
+ Switcher,
838
+ {
839
+ testId: "user-menu",
840
+ align: "end",
841
+ title: id.status === "ready" ? who : "Account",
842
+ label: id.status === "ready" ? who : "Sign in",
843
+ icon: id.status === "ready" ? /* @__PURE__ */ jsxRuntime.jsx(Monogram, { label: who, logo: id.account?.avatar }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.User, { "aria-hidden": "true", className: "h-4 w-4 opacity-70" }),
844
+ status: id.status,
845
+ error: id.error,
846
+ onSignIn: id.signIn,
847
+ signInLabel: `Sign in with ${id.whiteLabel.iamDomain}`,
848
+ items: [
849
+ { id: "account", label: id.account?.email || who, icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.User, { "aria-hidden": "true", className: "h-4 w-4 opacity-70" }) },
850
+ ...items
851
+ ],
852
+ footer: id.status === "ready" ? [{ id: "sign-out", label: "Sign out", danger: true, icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.LogOut, { "aria-hidden": "true", className: "h-4 w-4" }), onSelect: id.signOut }] : []
853
+ }
854
+ );
855
+ };
856
+ var SettingsMenu = ({ items = [], href = "/settings" }) => /* @__PURE__ */ jsxRuntime.jsx(
857
+ Switcher,
858
+ {
859
+ testId: "settings-menu",
860
+ align: "end",
861
+ title: "Settings",
862
+ label: "Settings",
863
+ icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Settings, { "aria-hidden": "true", className: "h-4 w-4 opacity-70" }),
864
+ items,
865
+ empty: "No settings on this surface.",
866
+ footer: [{ id: "all-settings", label: "All settings", href, icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Settings, { "aria-hidden": "true", className: "h-4 w-4 opacity-70" }) }]
867
+ }
868
+ );
869
+ var AppNav = ({
870
+ brand,
871
+ home = "/",
872
+ links = [],
873
+ org = true,
874
+ project = false,
875
+ settings,
876
+ userItems,
877
+ children
878
+ }) => {
879
+ const id = useIdentity();
880
+ const narrow = useIsNarrow();
881
+ const [menu, setMenu] = React6__namespace.useState(false);
882
+ return /* @__PURE__ */ jsxRuntime.jsx(
883
+ "header",
884
+ {
885
+ "data-testid": "app-nav",
886
+ className: "sticky top-0 z-50 border-b border-[var(--color-border-divider,rgba(127,127,127,0.25))] bg-[var(--color-bg-body,inherit)]",
887
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mx-auto flex h-14 max-w-7xl items-center gap-2 px-4", children: [
888
+ narrow && links.length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs(DrawerRoot, { open: menu, onOpenChange: (d) => setMenu(d.open), placement: "bottom", size: "md", children: [
889
+ /* @__PURE__ */ jsxRuntime.jsx(
890
+ "button",
891
+ {
892
+ type: "button",
893
+ "aria-label": "Menu",
894
+ "data-testid": "nav-menu",
895
+ className: "rounded-md p-2 hover:bg-[rgba(127,127,127,0.14)]",
896
+ onClick: () => setMenu(true),
897
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Menu, { "aria-hidden": "true", className: "h-5 w-5" })
898
+ }
899
+ ),
900
+ /* @__PURE__ */ jsxRuntime.jsxs(DrawerContent, { "data-testid": "nav-menu-panel", children: [
901
+ /* @__PURE__ */ jsxRuntime.jsx(DrawerHeader, { children: /* @__PURE__ */ jsxRuntime.jsx(DrawerTitle, { children: "Menu" }) }),
902
+ /* @__PURE__ */ jsxRuntime.jsx(DrawerBody, { children: links.map((l) => /* @__PURE__ */ jsxRuntime.jsx(
903
+ "a",
904
+ {
905
+ href: l.href,
906
+ onClick: () => setMenu(false),
907
+ "aria-current": l.active ? "page" : void 0,
908
+ className: "block rounded-md px-2 py-2.5 text-sm hover:bg-[rgba(127,127,127,0.14)]",
909
+ children: l.label
910
+ },
911
+ l.href
912
+ )) })
913
+ ] })
914
+ ] }) : null,
915
+ /* @__PURE__ */ jsxRuntime.jsx("a", { href: home, className: "flex items-center gap-2 font-semibold tracking-tight", children: brand ?? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
916
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Building2, { "aria-hidden": "true", className: "h-4 w-4 opacity-70" }),
917
+ id.whiteLabel.name
918
+ ] }) }),
919
+ org ? /* @__PURE__ */ jsxRuntime.jsx(OrgSwitcher, {}) : null,
920
+ project ? /* @__PURE__ */ jsxRuntime.jsx(ProjectSwitcher, {}) : null,
921
+ !narrow && links.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx("nav", { className: "flex items-center gap-1", children: links.map((l) => /* @__PURE__ */ jsxRuntime.jsx(
922
+ "a",
923
+ {
924
+ href: l.href,
925
+ "aria-current": l.active ? "page" : void 0,
926
+ className: cn(
927
+ "rounded-md px-3 py-1.5 text-sm font-medium",
928
+ l.active ? "bg-[rgba(127,127,127,0.14)]" : "opacity-75 hover:opacity-100"
929
+ ),
930
+ children: l.label
931
+ },
932
+ l.href
933
+ )) }) : null,
934
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-1 items-center justify-end gap-1", children: [
935
+ children,
936
+ settings ? /* @__PURE__ */ jsxRuntime.jsx(SettingsMenu, { items: settings }) : null,
937
+ /* @__PURE__ */ jsxRuntime.jsx(UserMenu, { items: userItems })
938
+ ] })
939
+ ] })
940
+ }
941
+ );
942
+ };
943
+
944
+ exports.AppNav = AppNav;
945
+ exports.OrgSwitcher = OrgSwitcher;
946
+ exports.ProjectSwitcher = ProjectSwitcher;
947
+ exports.SettingsMenu = SettingsMenu;
948
+ exports.Switcher = Switcher;
949
+ exports.UserMenu = UserMenu;
950
+ exports.initials = initials;