framepexls-ui-lib 1.7.0 → 1.9.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.
Files changed (47) hide show
  1. package/dist/AuthTopbar.d.mts +49 -3
  2. package/dist/AuthTopbar.d.ts +49 -3
  3. package/dist/AuthTopbar.js +223 -91
  4. package/dist/AuthTopbar.mjs +223 -91
  5. package/dist/Badge.d.mts +1 -1
  6. package/dist/Badge.d.ts +1 -1
  7. package/dist/Badge.js +1 -0
  8. package/dist/Badge.mjs +1 -0
  9. package/dist/Carousel.d.mts +53 -0
  10. package/dist/Carousel.d.ts +53 -0
  11. package/dist/Carousel.js +428 -0
  12. package/dist/Carousel.mjs +394 -0
  13. package/dist/ImpersonationSwitcher.js +1 -1
  14. package/dist/ImpersonationSwitcher.mjs +1 -1
  15. package/dist/KpiCard.js +4 -0
  16. package/dist/KpiCard.mjs +4 -0
  17. package/dist/Login.d.mts +3 -1
  18. package/dist/Login.d.ts +3 -1
  19. package/dist/Login.js +192 -33
  20. package/dist/Login.mjs +192 -33
  21. package/dist/LoginCarousel.d.mts +7 -30
  22. package/dist/LoginCarousel.d.ts +7 -30
  23. package/dist/LoginCarousel.js +9 -307
  24. package/dist/LoginCarousel.mjs +6 -308
  25. package/dist/LoginGallery.d.mts +1 -0
  26. package/dist/LoginGallery.d.ts +1 -0
  27. package/dist/LoginGallery.js +2 -2
  28. package/dist/LoginGallery.mjs +2 -2
  29. package/dist/Map.js +103 -34
  30. package/dist/Map.mjs +103 -34
  31. package/dist/MediaTile.js +13 -2
  32. package/dist/MediaTile.mjs +13 -2
  33. package/dist/Select.js +1 -1
  34. package/dist/Select.mjs +1 -1
  35. package/dist/Sidebar.js +290 -142
  36. package/dist/Sidebar.mjs +290 -142
  37. package/dist/Steps.js +31 -19
  38. package/dist/Steps.mjs +31 -19
  39. package/dist/Tooltip.js +83 -72
  40. package/dist/Tooltip.mjs +83 -72
  41. package/dist/index.d.mts +2 -1
  42. package/dist/index.d.ts +2 -1
  43. package/dist/index.js +5 -0
  44. package/dist/index.mjs +7 -4
  45. package/dist/theme/FontSizeController.js +4 -0
  46. package/dist/theme/FontSizeController.mjs +4 -0
  47. package/package.json +1 -1
@@ -1,4 +1,5 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import React__default from 'react';
2
3
  import { ChatUser, ChatThread, ChatMessage, ChatPresenceUser } from './ChatCenter.mjs';
3
4
  import { LanguageOption } from './LanguageSwitcher.mjs';
4
5
  import { NotificationItem } from './NotificationsCenter.mjs';
@@ -6,9 +7,51 @@ import { OmniSearchItem, OmniSearchProvider } from './OmniSearch.mjs';
6
7
  import { TourStep } from './Tour.mjs';
7
8
  import { ImpersonationUser } from './ImpersonationSwitcher.mjs';
8
9
  import { SidebarUser } from './Sidebar.mjs';
9
- import 'react';
10
10
  import './Dialog.mjs';
11
11
 
12
+ type AuthTopbarAccountMenuItem = {
13
+ key?: string;
14
+ label: string;
15
+ href?: string;
16
+ icon?: React__default.ReactNode;
17
+ kbd?: string;
18
+ danger?: boolean;
19
+ onSelect?: () => void | Promise<void>;
20
+ };
21
+ type AuthTopbarAccountMenuEntry = {
22
+ kind: "separator";
23
+ key?: string;
24
+ } | ({
25
+ kind: "item";
26
+ } & AuthTopbarAccountMenuItem) | {
27
+ kind: "builtin";
28
+ key?: string;
29
+ id: "impersonation.open" | "impersonation.stop" | "passwords" | "invites" | "logout";
30
+ label?: string;
31
+ href?: string;
32
+ icon?: React__default.ReactNode;
33
+ kbd?: string;
34
+ danger?: boolean;
35
+ };
36
+ type AuthTopbarSettingsMenuItem = {
37
+ key?: string;
38
+ label: string;
39
+ href?: string;
40
+ icon?: React__default.ReactNode;
41
+ kbd?: string;
42
+ danger?: boolean;
43
+ onSelect?: () => void | Promise<void>;
44
+ };
45
+ type AuthTopbarSettingsMenuEntry = {
46
+ kind: "separator";
47
+ key?: string;
48
+ } | ({
49
+ kind: "item";
50
+ } & AuthTopbarSettingsMenuItem) | {
51
+ kind: "builtin";
52
+ key?: string;
53
+ id: "appearance" | "shortcuts" | "browserNotifications";
54
+ };
12
55
  type AuthTopbarBrowserNotifications = {
13
56
  enabled: boolean;
14
57
  supported: boolean;
@@ -26,6 +69,9 @@ type AuthTopbarProps = {
26
69
  passwordHref?: string;
27
70
  invitesHref?: string;
28
71
  pendingInvites?: number;
72
+ accountMenuEntries?: AuthTopbarAccountMenuEntry[];
73
+ settingsMenuEntries?: AuthTopbarSettingsMenuEntry[];
74
+ showSearchButton?: boolean;
29
75
  appearance?: {
30
76
  locales?: LanguageOption[];
31
77
  localePersistKey?: string;
@@ -71,6 +117,6 @@ type AuthTopbarProps = {
71
117
  }) => void | Promise<void>;
72
118
  };
73
119
  };
74
- declare function AuthTopbar({ title, subtitle, user, loading, loadingMinDurationMs, onLogout, onNavigate, passwordHref, invitesHref, pendingInvites, appearance, omniSearch, tour, browserNotifications, impersonation, notifications, chat, }: AuthTopbarProps): react_jsx_runtime.JSX.Element;
120
+ declare function AuthTopbar({ title, subtitle, user, loading, loadingMinDurationMs, onLogout, onNavigate, passwordHref, invitesHref, pendingInvites, accountMenuEntries, settingsMenuEntries, showSearchButton, appearance, omniSearch, tour, browserNotifications, impersonation, notifications, chat, }: AuthTopbarProps): react_jsx_runtime.JSX.Element;
75
121
 
76
- export { type AuthTopbarBrowserNotifications, type AuthTopbarProps, AuthTopbar as default };
122
+ export { type AuthTopbarAccountMenuEntry, type AuthTopbarAccountMenuItem, type AuthTopbarBrowserNotifications, type AuthTopbarProps, type AuthTopbarSettingsMenuEntry, type AuthTopbarSettingsMenuItem, AuthTopbar as default };
@@ -1,4 +1,5 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import React__default from 'react';
2
3
  import { ChatUser, ChatThread, ChatMessage, ChatPresenceUser } from './ChatCenter.js';
3
4
  import { LanguageOption } from './LanguageSwitcher.js';
4
5
  import { NotificationItem } from './NotificationsCenter.js';
@@ -6,9 +7,51 @@ import { OmniSearchItem, OmniSearchProvider } from './OmniSearch.js';
6
7
  import { TourStep } from './Tour.js';
7
8
  import { ImpersonationUser } from './ImpersonationSwitcher.js';
8
9
  import { SidebarUser } from './Sidebar.js';
9
- import 'react';
10
10
  import './Dialog.js';
11
11
 
12
+ type AuthTopbarAccountMenuItem = {
13
+ key?: string;
14
+ label: string;
15
+ href?: string;
16
+ icon?: React__default.ReactNode;
17
+ kbd?: string;
18
+ danger?: boolean;
19
+ onSelect?: () => void | Promise<void>;
20
+ };
21
+ type AuthTopbarAccountMenuEntry = {
22
+ kind: "separator";
23
+ key?: string;
24
+ } | ({
25
+ kind: "item";
26
+ } & AuthTopbarAccountMenuItem) | {
27
+ kind: "builtin";
28
+ key?: string;
29
+ id: "impersonation.open" | "impersonation.stop" | "passwords" | "invites" | "logout";
30
+ label?: string;
31
+ href?: string;
32
+ icon?: React__default.ReactNode;
33
+ kbd?: string;
34
+ danger?: boolean;
35
+ };
36
+ type AuthTopbarSettingsMenuItem = {
37
+ key?: string;
38
+ label: string;
39
+ href?: string;
40
+ icon?: React__default.ReactNode;
41
+ kbd?: string;
42
+ danger?: boolean;
43
+ onSelect?: () => void | Promise<void>;
44
+ };
45
+ type AuthTopbarSettingsMenuEntry = {
46
+ kind: "separator";
47
+ key?: string;
48
+ } | ({
49
+ kind: "item";
50
+ } & AuthTopbarSettingsMenuItem) | {
51
+ kind: "builtin";
52
+ key?: string;
53
+ id: "appearance" | "shortcuts" | "browserNotifications";
54
+ };
12
55
  type AuthTopbarBrowserNotifications = {
13
56
  enabled: boolean;
14
57
  supported: boolean;
@@ -26,6 +69,9 @@ type AuthTopbarProps = {
26
69
  passwordHref?: string;
27
70
  invitesHref?: string;
28
71
  pendingInvites?: number;
72
+ accountMenuEntries?: AuthTopbarAccountMenuEntry[];
73
+ settingsMenuEntries?: AuthTopbarSettingsMenuEntry[];
74
+ showSearchButton?: boolean;
29
75
  appearance?: {
30
76
  locales?: LanguageOption[];
31
77
  localePersistKey?: string;
@@ -71,6 +117,6 @@ type AuthTopbarProps = {
71
117
  }) => void | Promise<void>;
72
118
  };
73
119
  };
74
- declare function AuthTopbar({ title, subtitle, user, loading, loadingMinDurationMs, onLogout, onNavigate, passwordHref, invitesHref, pendingInvites, appearance, omniSearch, tour, browserNotifications, impersonation, notifications, chat, }: AuthTopbarProps): react_jsx_runtime.JSX.Element;
120
+ declare function AuthTopbar({ title, subtitle, user, loading, loadingMinDurationMs, onLogout, onNavigate, passwordHref, invitesHref, pendingInvites, accountMenuEntries, settingsMenuEntries, showSearchButton, appearance, omniSearch, tour, browserNotifications, impersonation, notifications, chat, }: AuthTopbarProps): react_jsx_runtime.JSX.Element;
75
121
 
76
- export { type AuthTopbarBrowserNotifications, type AuthTopbarProps, AuthTopbar as default };
122
+ export { type AuthTopbarAccountMenuEntry, type AuthTopbarAccountMenuItem, type AuthTopbarBrowserNotifications, type AuthTopbarProps, type AuthTopbarSettingsMenuEntry, type AuthTopbarSettingsMenuItem, AuthTopbar as default };
@@ -61,6 +61,9 @@ function AuthTopbar({
61
61
  passwordHref = "/tablero/seguridad/contrasena",
62
62
  invitesHref = "/tablero/configuracion/invitaciones",
63
63
  pendingInvites = 0,
64
+ accountMenuEntries,
65
+ settingsMenuEntries,
66
+ showSearchButton = true,
64
67
  appearance,
65
68
  omniSearch,
66
69
  tour,
@@ -69,7 +72,7 @@ function AuthTopbar({
69
72
  notifications,
70
73
  chat
71
74
  }) {
72
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p;
75
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o;
73
76
  const toast = (0, import_Toast.useToast)();
74
77
  const showLoading = (0, import_skeleton.useMinVisible)(Boolean(loading), loadingMinDurationMs);
75
78
  const [tourOpen, setTourOpen] = import_react.default.useState(false);
@@ -102,6 +105,7 @@ function AuthTopbar({
102
105
  { locale: "es", label: "Espa\xF1ol", shortLabel: "ES", lang: "es" },
103
106
  { locale: "en", label: "English", shortLabel: "EN", lang: "en" }
104
107
  ];
108
+ const canSearch = Boolean(omniSearch);
105
109
  const notifEnabled = (_f = browserNotifications == null ? void 0 : browserNotifications.enabled) != null ? _f : false;
106
110
  const notifSupported = (_g = browserNotifications == null ? void 0 : browserNotifications.supported) != null ? _g : false;
107
111
  const notifPermission = (_h = browserNotifications == null ? void 0 : browserNotifications.permission) != null ? _h : "unsupported";
@@ -112,6 +116,214 @@ function AuthTopbar({
112
116
  },
113
117
  [onNavigate]
114
118
  );
119
+ const resolvedAccountEntries = import_react.default.useMemo(() => {
120
+ if (Array.isArray(accountMenuEntries) && accountMenuEntries.length > 0) return accountMenuEntries;
121
+ return [
122
+ { kind: "builtin", id: "impersonation.open" },
123
+ { kind: "builtin", id: "impersonation.stop" },
124
+ { kind: "builtin", id: "passwords" },
125
+ { kind: "builtin", id: "invites" },
126
+ { kind: "builtin", id: "logout" }
127
+ ];
128
+ }, [accountMenuEntries]);
129
+ const resolvedSettingsEntries = import_react.default.useMemo(() => {
130
+ if (settingsMenuEntries !== void 0) return settingsMenuEntries;
131
+ return [
132
+ { kind: "builtin", id: "appearance" },
133
+ { kind: "builtin", id: "shortcuts" },
134
+ { kind: "builtin", id: "browserNotifications" }
135
+ ];
136
+ }, [settingsMenuEntries]);
137
+ const renderSettingsEntry = import_react.default.useCallback(
138
+ (entry, idx) => {
139
+ var _a2, _b2, _c2, _d2, _e2;
140
+ if (entry.kind === "separator") return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_Dropdown.default.Separator, {}, (_a2 = entry.key) != null ? _a2 : `settings_sep_${idx}`);
141
+ if (entry.kind === "item") {
142
+ const key2 = (_c2 = (_b2 = entry.key) != null ? _b2 : entry.href) != null ? _c2 : entry.label;
143
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
144
+ import_Dropdown.default.Item,
145
+ {
146
+ onSelect: () => void (async () => {
147
+ if (entry.onSelect) return entry.onSelect();
148
+ if (entry.href && onNavigate) return onNavigate(entry.href);
149
+ })(),
150
+ icon: entry.icon,
151
+ kbd: entry.kbd,
152
+ danger: entry.danger,
153
+ children: entry.label
154
+ },
155
+ key2
156
+ );
157
+ }
158
+ const id = entry.id;
159
+ const key = (_d2 = entry.key) != null ? _d2 : id;
160
+ if (id === "appearance") {
161
+ const anyAppearance = showLanguage || showThemeToggle || showAccent || showFontSize;
162
+ if (!anyAppearance) return null;
163
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react.default.Fragment, { children: [
164
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_Dropdown.default.Label, { children: "Apariencia" }),
165
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "px-2.5 pb-2", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "grid gap-2 rounded-2xl border border-[var(--border)] bg-[var(--card)] p-2", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex flex-wrap items-center justify-between gap-2", children: [
166
+ showLanguage ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
167
+ import_LanguageSwitcher.default,
168
+ {
169
+ locales,
170
+ persistKey: (_e2 = appearance == null ? void 0 : appearance.localePersistKey) != null ? _e2 : "fx:locale",
171
+ label: "Idioma",
172
+ ariaLabel: "Cambiar idioma"
173
+ }
174
+ ) : null,
175
+ showThemeToggle ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ThemeToggle.default, { cycle: ["light", "dark"], labels: { light: "Claro", dark: "Oscuro" } }) : null,
176
+ showAccent ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
177
+ import_ThemeController.default,
178
+ {
179
+ showSystem: false,
180
+ showMode: false,
181
+ showAccent: true,
182
+ accentUi: "dropdown",
183
+ className: "border-0 bg-transparent shadow-none px-0 py-0",
184
+ labels: { accentGroup: "Color" }
185
+ }
186
+ ) : null,
187
+ showFontSize ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_FontSizeController.default, { labels: { trigger: "Fuente" } }) : null
188
+ ] }) }) })
189
+ ] }, key);
190
+ }
191
+ if (id === "shortcuts") {
192
+ const hasItems = canSearch || Boolean(tour);
193
+ if (!hasItems) return null;
194
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react.default.Fragment, { children: [
195
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_Dropdown.default.Separator, { className: "mt-0" }),
196
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_Dropdown.default.Label, { children: "Accesos" }),
197
+ canSearch ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_Dropdown.default.Item, { icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_iconos.MagnifyingGlassIcon, { className: "h-4 w-4", "aria-hidden": true }), kbd: "\u2318K", onSelect: () => setSearchOpen(true), children: "Buscar" }) : null,
198
+ tour ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
199
+ import_Dropdown.default.Item,
200
+ {
201
+ icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_iconos.CircleQuestionIcon, { className: "h-4 w-4", "aria-hidden": true }),
202
+ onSelect: () => {
203
+ setTourStep(0);
204
+ setTourOpen(true);
205
+ },
206
+ children: "Tour guiado"
207
+ }
208
+ ) : null
209
+ ] }, key);
210
+ }
211
+ if (id === "browserNotifications") {
212
+ if (!browserNotifications) return null;
213
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react.default.Fragment, { children: [
214
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_Dropdown.default.Separator, {}),
215
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_Dropdown.default.Label, { children: "Notificaciones" }),
216
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
217
+ import_Dropdown.default.Item,
218
+ {
219
+ icon: notifEnabled ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_iconos.BellIcon, { className: "h-4 w-4", "aria-hidden": true }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_iconos.BellSlashIcon, { className: "h-4 w-4", "aria-hidden": true }),
220
+ kbd: notifEnabled ? "ON" : "OFF",
221
+ onSelect: () => void browserNotifications.onToggle(),
222
+ children: "Notificaciones del navegador"
223
+ }
224
+ ),
225
+ !notifSupported ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "px-2.5 pb-2 text-xs text-[var(--muted)]", children: "Este navegador no soporta notificaciones." }) : notifPermission === "denied" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "px-2.5 pb-2 text-xs text-[var(--muted)]", children: "Permisos bloqueados en el navegador." }) : null
226
+ ] }, key);
227
+ }
228
+ return null;
229
+ },
230
+ [
231
+ appearance == null ? void 0 : appearance.localePersistKey,
232
+ browserNotifications,
233
+ canSearch,
234
+ locales,
235
+ notifEnabled,
236
+ notifPermission,
237
+ notifSupported,
238
+ onNavigate,
239
+ showAccent,
240
+ showFontSize,
241
+ showLanguage,
242
+ showThemeToggle,
243
+ tour
244
+ ]
245
+ );
246
+ const renderAccountEntry = import_react.default.useCallback(
247
+ (entry, idx) => {
248
+ var _a2, _b2, _c2, _d2, _e2, _f2, _g2, _h2, _i2, _j2, _k2, _l2, _m2, _n2, _o2, _p, _q, _r;
249
+ if (entry.kind === "separator") {
250
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_Dropdown.default.Separator, {}, (_a2 = entry.key) != null ? _a2 : `sep_${idx}`);
251
+ }
252
+ if (entry.kind === "item") {
253
+ const key2 = (_c2 = (_b2 = entry.key) != null ? _b2 : entry.href) != null ? _c2 : entry.label;
254
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
255
+ import_Dropdown.default.Item,
256
+ {
257
+ onSelect: () => void (async () => {
258
+ if (entry.onSelect) return entry.onSelect();
259
+ if (entry.href && onNavigate) return onNavigate(entry.href);
260
+ })(),
261
+ icon: entry.icon,
262
+ kbd: entry.kbd,
263
+ danger: entry.danger,
264
+ children: entry.label
265
+ },
266
+ key2
267
+ );
268
+ }
269
+ const id = entry.id;
270
+ const key = (_d2 = entry.key) != null ? _d2 : id;
271
+ if (id === "impersonation.open") {
272
+ if (!impersonation) return null;
273
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
274
+ import_Dropdown.default.Item,
275
+ {
276
+ onSelect: () => window.setTimeout(() => setImpersonationOpen(true), 0),
277
+ icon: (_e2 = entry.icon) != null ? _e2 : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_iconos.CircleUserIcon, { className: "h-4 w-4", "aria-hidden": true }),
278
+ children: (_f2 = entry.label) != null ? _f2 : "Impersonar usuario"
279
+ },
280
+ key
281
+ );
282
+ }
283
+ if (id === "impersonation.stop") {
284
+ if (!impersonated || !impersonation) return null;
285
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
286
+ import_Dropdown.default.Item,
287
+ {
288
+ onSelect: () => void impersonation.onChange(null),
289
+ icon: (_g2 = entry.icon) != null ? _g2 : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_iconos.CloseIcon, { className: "h-4 w-4", "aria-hidden": true }),
290
+ children: (_h2 = entry.label) != null ? _h2 : "Detener impersonaci\xF3n"
291
+ },
292
+ key
293
+ );
294
+ }
295
+ if (id === "passwords") {
296
+ if (!onNavigate) return null;
297
+ const href = (_i2 = entry.href) != null ? _i2 : passwordHref;
298
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_Dropdown.default.Item, { onSelect: () => onNavigate(href), icon: (_j2 = entry.icon) != null ? _j2 : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_iconos.LockIcon, { className: "h-4 w-4", "aria-hidden": true }), children: (_k2 = entry.label) != null ? _k2 : "Contrase\xF1as" }, key);
299
+ }
300
+ if (id === "invites") {
301
+ if (!onNavigate) return null;
302
+ const href = (_l2 = entry.href) != null ? _l2 : invitesHref;
303
+ const kbd = (_m2 = entry.kbd) != null ? _m2 : pendingInvites > 0 ? String(pendingInvites) : void 0;
304
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_Dropdown.default.Item, { onSelect: () => onNavigate(href), icon: (_n2 = entry.icon) != null ? _n2 : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_iconos.Sobre, { className: "h-4 w-4", "aria-hidden": true }), kbd, children: (_o2 = entry.label) != null ? _o2 : "Invitaciones" }, key);
305
+ }
306
+ if (id === "logout") {
307
+ if (!onLogout) return null;
308
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
309
+ import_Dropdown.default.Item,
310
+ {
311
+ danger: (_p = entry.danger) != null ? _p : true,
312
+ onSelect: () => void handleLogout(),
313
+ icon: (_q = entry.icon) != null ? _q : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_iconos.RightFromBracketIcon, { className: "h-4 w-4", "aria-hidden": true }),
314
+ children: (_r = entry.label) != null ? _r : "Cerrar sesi\xF3n"
315
+ },
316
+ key
317
+ );
318
+ }
319
+ return null;
320
+ },
321
+ [handleLogout, impersonated, impersonation, invitesHref, onLogout, onNavigate, passwordHref, pendingInvites]
322
+ );
323
+ const settingsNodes = import_react.default.useMemo(
324
+ () => resolvedSettingsEntries.map((e, idx) => renderSettingsEntry(e, idx)).filter(Boolean),
325
+ [renderSettingsEntry, resolvedSettingsEntries]
326
+ );
115
327
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
116
328
  "header",
117
329
  {
@@ -135,7 +347,7 @@ function AuthTopbar({
135
347
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "fx-skeleton", style: { width: 34, height: 34, borderRadius: 12 } }),
136
348
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "fx-skeleton", style: { width: 128, height: 34, borderRadius: 12 } })
137
349
  ] }) : null,
138
- !showLoading ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_Tooltip.default, { content: "Buscar (\u2318/Ctrl + K)", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ActionIconButton.default, { title: "Buscar", size: "sm", onClick: () => setSearchOpen(true), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_iconos.MagnifyingGlassIcon, { className: "h-4 w-4", "aria-hidden": true }) }) }) : null,
350
+ !showLoading ? canSearch && showSearchButton ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_Tooltip.default, { content: "Buscar (\u2318/Ctrl + K)", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ActionIconButton.default, { title: "Buscar", size: "sm", onClick: () => setSearchOpen(true), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_iconos.MagnifyingGlassIcon, { className: "h-4 w-4", "aria-hidden": true }) }) }) : null : null,
139
351
  !showLoading && tour ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
140
352
  import_Tour.default,
141
353
  {
@@ -170,63 +382,9 @@ function AuthTopbar({
170
382
  labels: { trigger: "Notificaciones", title: "Notificaciones", emptyTitle: "Sin notificaciones" }
171
383
  }
172
384
  ) : null,
173
- !showLoading ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_Dropdown.default, { align: "end", children: [
385
+ !showLoading && settingsNodes.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_Dropdown.default, { align: "end", children: [
174
386
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_Dropdown.default.Trigger, { className: "px-2 py-2", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_iconos.GearIcon, { className: "h-4 w-4", "aria-hidden": true }) }),
175
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_Dropdown.default.Content, { className: "w-[340px]", maxHeight: 520, children: [
176
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_Dropdown.default.Label, { children: "Apariencia" }),
177
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "px-2.5 pb-2", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "grid gap-2 rounded-2xl border border-[var(--border)] bg-[var(--card)] p-2", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex flex-wrap items-center justify-between gap-2", children: [
178
- showLanguage ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
179
- import_LanguageSwitcher.default,
180
- {
181
- locales,
182
- persistKey: (_l = appearance == null ? void 0 : appearance.localePersistKey) != null ? _l : "fx:locale",
183
- label: "Idioma",
184
- ariaLabel: "Cambiar idioma"
185
- }
186
- ) : null,
187
- showThemeToggle ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ThemeToggle.default, { cycle: ["light", "dark"], labels: { light: "Claro", dark: "Oscuro" } }) : null,
188
- showAccent ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
189
- import_ThemeController.default,
190
- {
191
- showSystem: false,
192
- showMode: false,
193
- showAccent: true,
194
- accentUi: "dropdown",
195
- className: "border-0 bg-transparent shadow-none px-0 py-0",
196
- labels: { accentGroup: "Color" }
197
- }
198
- ) : null,
199
- showFontSize ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_FontSizeController.default, { labels: { trigger: "Fuente" } }) : null
200
- ] }) }) }),
201
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_Dropdown.default.Separator, { className: "mt-0" }),
202
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_Dropdown.default.Label, { children: "Accesos" }),
203
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_Dropdown.default.Item, { icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_iconos.MagnifyingGlassIcon, { className: "h-4 w-4", "aria-hidden": true }), kbd: "\u2318K", onSelect: () => setSearchOpen(true), children: "Buscar" }),
204
- tour ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
205
- import_Dropdown.default.Item,
206
- {
207
- icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_iconos.CircleQuestionIcon, { className: "h-4 w-4", "aria-hidden": true }),
208
- onSelect: () => {
209
- setTourStep(0);
210
- setTourOpen(true);
211
- },
212
- children: "Tour guiado"
213
- }
214
- ) : null,
215
- browserNotifications ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
216
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_Dropdown.default.Separator, {}),
217
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_Dropdown.default.Label, { children: "Notificaciones" }),
218
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
219
- import_Dropdown.default.Item,
220
- {
221
- icon: notifEnabled ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_iconos.BellIcon, { className: "h-4 w-4", "aria-hidden": true }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_iconos.BellSlashIcon, { className: "h-4 w-4", "aria-hidden": true }),
222
- kbd: notifEnabled ? "ON" : "OFF",
223
- onSelect: () => void browserNotifications.onToggle(),
224
- children: "Notificaciones del navegador"
225
- }
226
- ),
227
- !notifSupported ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "px-2.5 pb-2 text-xs text-[var(--muted)]", children: "Este navegador no soporta notificaciones." }) : notifPermission === "denied" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "px-2.5 pb-2 text-xs text-[var(--muted)]", children: "Permisos bloqueados en el navegador." }) : null
228
- ] }) : null
229
- ] })
387
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_Dropdown.default.Content, { className: "w-[340px]", maxHeight: 520, children: settingsNodes })
230
388
  ] }) : null,
231
389
  !showLoading && user ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_Dropdown.default, { align: "end", children: [
232
390
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_Dropdown.default.Trigger, { className: "min-w-0 max-w-[220px] justify-between text-left", children: [
@@ -236,7 +394,7 @@ function AuthTopbar({
236
394
  import_AvatarSquare.default,
237
395
  {
238
396
  size: 28,
239
- src: (_m = user.avatarUrl) != null ? _m : void 0,
397
+ src: (_l = user.avatarUrl) != null ? _l : void 0,
240
398
  alt: user.name,
241
399
  initials: user.name.split(/\s+/).slice(0, 2).map((s) => s[0]).join("").toUpperCase(),
242
400
  radiusClass: "rounded-xl",
@@ -263,33 +421,7 @@ function AuthTopbar({
263
421
  ] }) : null
264
422
  ] }) }),
265
423
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_Dropdown.default.Separator, { className: "mt-0" }),
266
- impersonation ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
267
- import_Dropdown.default.Item,
268
- {
269
- onSelect: () => window.setTimeout(() => setImpersonationOpen(true), 0),
270
- icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_iconos.CircleUserIcon, { className: "h-4 w-4", "aria-hidden": true }),
271
- children: "Impersonar usuario\u2026"
272
- }
273
- ) : null,
274
- impersonated && impersonation ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
275
- import_Dropdown.default.Item,
276
- {
277
- onSelect: () => void impersonation.onChange(null),
278
- icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_iconos.CloseIcon, { className: "h-4 w-4", "aria-hidden": true }),
279
- children: "Detener impersonaci\xF3n"
280
- }
281
- ) : null,
282
- onNavigate ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_Dropdown.default.Item, { onSelect: () => onNavigate(passwordHref), icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_iconos.LockIcon, { className: "h-4 w-4", "aria-hidden": true }), children: "Contrase\xF1as" }) : null,
283
- onNavigate ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
284
- import_Dropdown.default.Item,
285
- {
286
- onSelect: () => onNavigate(invitesHref),
287
- kbd: pendingInvites > 0 ? String(pendingInvites) : void 0,
288
- icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_iconos.Sobre, { className: "h-4 w-4", "aria-hidden": true }),
289
- children: "Invitaciones"
290
- }
291
- ) : null,
292
- onLogout ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_Dropdown.default.Item, { danger: true, onSelect: () => void handleLogout(), icon: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_iconos.RightFromBracketIcon, { className: "h-4 w-4", "aria-hidden": true }), children: "Cerrar sesi\xF3n" }) : null
424
+ resolvedAccountEntries.map((e, idx) => renderAccountEntry(e, idx)).filter(Boolean)
293
425
  ] })
294
426
  ] }) : null,
295
427
  !showLoading && impersonation ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
@@ -304,17 +436,17 @@ function AuthTopbar({
304
436
  ) : null
305
437
  ] })
306
438
  ] }),
307
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
439
+ canSearch ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
308
440
  import_OmniSearch.default,
309
441
  {
310
442
  open: searchOpen,
311
443
  onOpenChange: setSearchOpen,
312
- hotkey: (_n = omniSearch == null ? void 0 : omniSearch.hotkey) != null ? _n : true,
313
- items: (_o = omniSearch == null ? void 0 : omniSearch.items) != null ? _o : [],
314
- providers: (_p = omniSearch == null ? void 0 : omniSearch.providers) != null ? _p : [],
444
+ hotkey: (_m = omniSearch == null ? void 0 : omniSearch.hotkey) != null ? _m : true,
445
+ items: (_n = omniSearch == null ? void 0 : omniSearch.items) != null ? _n : [],
446
+ providers: (_o = omniSearch == null ? void 0 : omniSearch.providers) != null ? _o : [],
315
447
  onNavigate: onOmniNavigate
316
448
  }
317
- )
449
+ ) : null
318
450
  ]
319
451
  }
320
452
  );