@almadar/ui 4.22.4 → 4.24.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.
@@ -18144,6 +18144,7 @@ var init_DashboardLayout = __esm({
18144
18144
  init_Typography();
18145
18145
  init_Icon();
18146
18146
  init_useAuthContext();
18147
+ init_useEventBus();
18147
18148
  init_useTranslate();
18148
18149
  DashboardLayout = ({
18149
18150
  appName = "{{APP_TITLE}}",
@@ -18151,11 +18152,29 @@ var init_DashboardLayout = __esm({
18151
18152
  navItems = [],
18152
18153
  user: userProp,
18153
18154
  headerActions,
18154
- showSearch = true,
18155
+ showSearch = false,
18156
+ searchEvent,
18157
+ onSearchSubmit,
18158
+ notifications,
18159
+ notificationClickEvent,
18160
+ onNotificationClick,
18161
+ showThemeToggle = true,
18155
18162
  sidebarFooter,
18156
18163
  onSignOut: onSignOutProp,
18157
18164
  children
18158
18165
  }) => {
18166
+ const eventBus = useEventBus();
18167
+ const searchEnabled = showSearch || Boolean(searchEvent) || Boolean(onSearchSubmit);
18168
+ const notificationsEnabled = Array.isArray(notifications);
18169
+ const unreadCount = notificationsEnabled ? notifications.filter((n) => n.read !== true).length : 0;
18170
+ const handleSearchSubmit = (value) => {
18171
+ if (searchEvent) eventBus.emit(`UI:${searchEvent}`, { value });
18172
+ if (onSearchSubmit) onSearchSubmit(value);
18173
+ };
18174
+ const handleNotificationClick = () => {
18175
+ if (notificationClickEvent) eventBus.emit(`UI:${notificationClickEvent}`, {});
18176
+ if (onNotificationClick) onNotificationClick();
18177
+ };
18159
18178
  const [sidebarOpen, setSidebarOpen] = React113.useState(false);
18160
18179
  const [userMenuOpen, setUserMenuOpen] = React113.useState(false);
18161
18180
  const location = reactRouterDom.useLocation();
@@ -18236,17 +18255,7 @@ var init_DashboardLayout = __esm({
18236
18255
  ))
18237
18256
  }
18238
18257
  ),
18239
- sidebarFooter || /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "p-4 border-t border-border dark:border-border", children: /* @__PURE__ */ jsxRuntime.jsxs(
18240
- reactRouterDom.Link,
18241
- {
18242
- to: "/settings",
18243
- className: "flex items-center gap-3 px-3 py-2 text-sm text-muted-foreground dark:text-muted-foreground rounded-lg hover:bg-muted dark:hover:bg-muted",
18244
- children: [
18245
- /* @__PURE__ */ jsxRuntime.jsx(LucideIcons.Settings, { className: "h-5 w-5" }),
18246
- t("common.settings")
18247
- ]
18248
- }
18249
- ) })
18258
+ sidebarFooter && /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "p-4 border-t border-border dark:border-border", children: sidebarFooter })
18250
18259
  ]
18251
18260
  }
18252
18261
  ),
@@ -18273,32 +18282,40 @@ var init_DashboardLayout = __esm({
18273
18282
  children: /* @__PURE__ */ jsxRuntime.jsx(LucideIcons.Menu, { className: "h-5 w-5" })
18274
18283
  }
18275
18284
  ),
18276
- showSearch && /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "hidden sm:block flex-1 max-w-md", children: /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "relative", children: [
18285
+ searchEnabled && /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "hidden sm:block flex-1 max-w-md", children: /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "relative", children: [
18277
18286
  /* @__PURE__ */ jsxRuntime.jsx(LucideIcons.Search, { className: "absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground dark:text-muted-foreground" }),
18278
18287
  /* @__PURE__ */ jsxRuntime.jsx(
18279
18288
  Input,
18280
18289
  {
18281
18290
  type: "search",
18282
18291
  placeholder: t("common.search"),
18283
- className: "pl-10 w-full"
18292
+ className: "pl-10 w-full",
18293
+ onKeyDown: (e) => {
18294
+ if (e.key === "Enter") {
18295
+ handleSearchSubmit(e.target.value);
18296
+ }
18297
+ }
18284
18298
  }
18285
18299
  )
18286
18300
  ] }) }),
18287
18301
  /* @__PURE__ */ jsxRuntime.jsxs(HStack, { align: "center", gap: "xs", children: [
18288
18302
  headerActions,
18289
- /* @__PURE__ */ jsxRuntime.jsx(ThemeToggle, {}),
18290
- /* @__PURE__ */ jsxRuntime.jsxs(
18303
+ showThemeToggle && /* @__PURE__ */ jsxRuntime.jsx(ThemeToggle, {}),
18304
+ notificationsEnabled && /* @__PURE__ */ jsxRuntime.jsxs(
18291
18305
  Button,
18292
18306
  {
18293
18307
  variant: "ghost",
18294
18308
  className: "relative p-2 rounded-full hover:bg-muted dark:hover:bg-muted",
18309
+ onClick: handleNotificationClick,
18310
+ "aria-label": t("common.notifications"),
18295
18311
  children: [
18296
18312
  /* @__PURE__ */ jsxRuntime.jsx(LucideIcons.Bell, { className: "h-5 w-5 text-muted-foreground dark:text-muted-foreground" }),
18297
- /* @__PURE__ */ jsxRuntime.jsx(
18313
+ unreadCount > 0 && /* @__PURE__ */ jsxRuntime.jsx(
18298
18314
  Box,
18299
18315
  {
18300
18316
  as: "span",
18301
- className: "absolute top-1 right-1 w-2 h-2 bg-error rounded-full"
18317
+ className: "absolute -top-0.5 -right-0.5 min-w-[18px] h-[18px] px-1 bg-error rounded-full text-[10px] font-semibold text-white flex items-center justify-center",
18318
+ children: unreadCount > 99 ? "99+" : unreadCount
18302
18319
  }
18303
18320
  )
18304
18321
  ]
@@ -18363,17 +18380,6 @@ var init_DashboardLayout = __esm({
18363
18380
  }
18364
18381
  )
18365
18382
  ] }),
18366
- /* @__PURE__ */ jsxRuntime.jsxs(
18367
- reactRouterDom.Link,
18368
- {
18369
- to: "/settings",
18370
- className: "flex items-center gap-2 px-4 py-2 text-sm text-foreground dark:text-foreground hover:bg-muted dark:hover:bg-muted",
18371
- children: [
18372
- /* @__PURE__ */ jsxRuntime.jsx(LucideIcons.Settings, { className: "h-4 w-4" }),
18373
- t("common.settings")
18374
- ]
18375
- }
18376
- ),
18377
18383
  /* @__PURE__ */ jsxRuntime.jsxs(
18378
18384
  Button,
18379
18385
  {
@@ -39525,6 +39531,7 @@ function prepareSchemaForPreview(input) {
39525
39531
  // runtime/OrbPreview.tsx
39526
39532
  init_logger();
39527
39533
  var xOrbitalLog2 = createLogger("almadar:runtime:cross-orbital");
39534
+ var navLog = createLogger("almadar:runtime:navigation");
39528
39535
  function normalizeChild(child) {
39529
39536
  if (typeof child === "string") return child;
39530
39537
  if (child === null || typeof child !== "object" || Array.isArray(child)) {
@@ -39600,6 +39607,19 @@ function TraitInitializer({ traits: traits2, orbitalNames, onNavigate, onLocalFa
39600
39607
  }, [bridge.connected, bridge.sendEvent, orbitalNames, uiSlots, onNavigate, embeddedTraits]);
39601
39608
  const opts = orbitalNames ? { onEventProcessed, navigate: onNavigate, traitConfigsByName, orbitalsByTrait, embeddedTraits } : { navigate: onNavigate, persistence, traitConfigsByName, orbitalsByTrait, embeddedTraits };
39602
39609
  const { sendEvent } = useTraitStateMachine(traits2, uiSlots, opts);
39610
+ const prevTraitNamesRef = React113.useRef("");
39611
+ React113.useEffect(() => {
39612
+ const traitNames = traits2.map((b) => b.trait?.name ?? "").filter(Boolean).sort().join(",");
39613
+ if (prevTraitNamesRef.current && prevTraitNamesRef.current !== traitNames) {
39614
+ navLog.info("page:trait-set-changed", {
39615
+ from: prevTraitNamesRef.current,
39616
+ to: traitNames,
39617
+ action: "clearAll-slots"
39618
+ });
39619
+ uiSlots.clearAll();
39620
+ }
39621
+ prevTraitNamesRef.current = traitNames;
39622
+ }, [traits2, uiSlots]);
39603
39623
  const initSentRef = React113.useRef(false);
39604
39624
  React113.useEffect(() => {
39605
39625
  if (!orbitalNames?.length) {
@@ -39614,6 +39634,10 @@ function TraitInitializer({ traits: traits2, orbitalNames, onNavigate, onLocalFa
39614
39634
  }, 5e3);
39615
39635
  return () => clearTimeout(fallback);
39616
39636
  }, [traits2, orbitalNames, sendEvent, onLocalFallback]);
39637
+ const orbitalsKey = (orbitalNames ?? []).slice().sort().join(",");
39638
+ React113.useEffect(() => {
39639
+ initSentRef.current = false;
39640
+ }, [orbitalsKey]);
39617
39641
  React113.useEffect(() => {
39618
39642
  if (!bridge.connected || !orbitalNames?.length || initSentRef.current) return;
39619
39643
  initSentRef.current = true;
@@ -39854,8 +39878,19 @@ function OrbPreview({
39854
39878
  }, [initialPageName, currentPage]);
39855
39879
  const handleNavigate = React113.useCallback((path) => {
39856
39880
  const match = pages.find(({ page }) => page.path === path);
39881
+ navLog.info("handleNavigate", {
39882
+ path,
39883
+ matched: match?.page.name ?? null,
39884
+ availablePaths: pages.map((p2) => p2.page.path)
39885
+ });
39857
39886
  if (match) {
39858
39887
  setCurrentPage(match.page.name);
39888
+ if (typeof window !== "undefined") {
39889
+ const url = new URL(window.location.href);
39890
+ url.searchParams.set("page", path);
39891
+ window.history.pushState({}, "", url.toString());
39892
+ window.dispatchEvent(new PopStateEvent("popstate"));
39893
+ }
39859
39894
  }
39860
39895
  }, [pages]);
39861
39896
  if (!parseResult.ok) {
@@ -39867,18 +39902,30 @@ function OrbPreview({
39867
39902
  const containerRef = React113.useRef(null);
39868
39903
  React113.useEffect(() => {
39869
39904
  const el = containerRef.current;
39870
- if (!el || pages.length <= 1) return;
39905
+ if (!el) return;
39906
+ if (pages.length <= 1) {
39907
+ navLog.info("interceptor:skipped", { reason: "single-page schema", pageCount: pages.length });
39908
+ return;
39909
+ }
39871
39910
  const handler = (e) => {
39872
39911
  const anchor = e.target.closest("a");
39873
39912
  if (!anchor) return;
39874
39913
  const href = anchor.getAttribute("href") ?? anchor.getAttribute("to") ?? "";
39875
- if (!href || href.startsWith("http") || href.startsWith("mailto:") || href.startsWith("#")) return;
39914
+ navLog.info("click:intercepted", {
39915
+ href,
39916
+ anchorText: anchor.textContent?.trim().slice(0, 40)
39917
+ });
39918
+ if (!href || href.startsWith("http") || href.startsWith("mailto:") || href.startsWith("#")) {
39919
+ navLog.info("click:skipped", { href, reason: "external/empty/hash" });
39920
+ return;
39921
+ }
39876
39922
  e.preventDefault();
39877
39923
  e.stopPropagation();
39878
39924
  e.stopImmediatePropagation();
39879
39925
  handleNavigate(href);
39880
39926
  };
39881
39927
  el.addEventListener("click", handler, true);
39928
+ navLog.info("interceptor:installed", { pageCount: pages.length, paths: pages.map((p2) => p2.page.path) });
39882
39929
  return () => el.removeEventListener("click", handler, true);
39883
39930
  }, [pages, handleNavigate]);
39884
39931
  return /* @__PURE__ */ jsxRuntime.jsxs(
@@ -5,7 +5,7 @@ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
5
5
  import { clsx } from 'clsx';
6
6
  import { twMerge } from 'tailwind-merge';
7
7
  import * as LucideIcons from 'lucide-react';
8
- import { X, AlertTriangle, Info, AlertCircle, CheckCircle, Loader2, List, Printer, ChevronRight, ChevronLeft, Check, Copy, Code, FileText, WrapText, Trash2, Settings, Menu as Menu$1, Search, Bell, ChevronDown, LogOut, ZoomOut, ZoomIn, Download, FileQuestion, Inbox, XCircle, Filter, Plus, Pause, Play, RotateCcw, Package, Calendar, Pencil, Eye, MoreHorizontal, Image as Image$1, Upload, Minus, ArrowLeft, HelpCircle, ChevronUp, Eraser, Star, TrendingUp, TrendingDown, ArrowUp, ArrowDown, MoreVertical, Sun, Moon, Circle, Clock, CheckCircle2, ArrowRight, FileWarning, SkipForward, Bug, Send, Wrench, User, Tag, DollarSign, Zap, Sword, Move, Heart, Shield } from 'lucide-react';
8
+ import { X, AlertTriangle, Info, AlertCircle, CheckCircle, Loader2, List, Printer, ChevronRight, ChevronLeft, Check, Copy, Code, FileText, WrapText, Trash2, Menu as Menu$1, Search, Bell, ChevronDown, LogOut, ZoomOut, ZoomIn, Download, FileQuestion, Inbox, XCircle, Filter, Plus, Pause, Play, RotateCcw, Package, Calendar, Pencil, Eye, MoreHorizontal, Image as Image$1, Upload, Minus, ArrowLeft, HelpCircle, ChevronUp, Eraser, Star, TrendingUp, TrendingDown, ArrowUp, ArrowDown, MoreVertical, Sun, Moon, Circle, Clock, CheckCircle2, ArrowRight, FileWarning, SkipForward, Bug, Send, Wrench, User, Tag, DollarSign, Zap, Sword, Move, Heart, Shield } from 'lucide-react';
9
9
  import { evaluate, createMinimalContext } from '@almadar/evaluator';
10
10
  import { useUISlots, UISlotProvider } from '@almadar/ui/context';
11
11
  import { getPatternDefinition, getComponentForPattern as getComponentForPattern$1 } from '@almadar/patterns';
@@ -18099,6 +18099,7 @@ var init_DashboardLayout = __esm({
18099
18099
  init_Typography();
18100
18100
  init_Icon();
18101
18101
  init_useAuthContext();
18102
+ init_useEventBus();
18102
18103
  init_useTranslate();
18103
18104
  DashboardLayout = ({
18104
18105
  appName = "{{APP_TITLE}}",
@@ -18106,11 +18107,29 @@ var init_DashboardLayout = __esm({
18106
18107
  navItems = [],
18107
18108
  user: userProp,
18108
18109
  headerActions,
18109
- showSearch = true,
18110
+ showSearch = false,
18111
+ searchEvent,
18112
+ onSearchSubmit,
18113
+ notifications,
18114
+ notificationClickEvent,
18115
+ onNotificationClick,
18116
+ showThemeToggle = true,
18110
18117
  sidebarFooter,
18111
18118
  onSignOut: onSignOutProp,
18112
18119
  children
18113
18120
  }) => {
18121
+ const eventBus = useEventBus();
18122
+ const searchEnabled = showSearch || Boolean(searchEvent) || Boolean(onSearchSubmit);
18123
+ const notificationsEnabled = Array.isArray(notifications);
18124
+ const unreadCount = notificationsEnabled ? notifications.filter((n) => n.read !== true).length : 0;
18125
+ const handleSearchSubmit = (value) => {
18126
+ if (searchEvent) eventBus.emit(`UI:${searchEvent}`, { value });
18127
+ if (onSearchSubmit) onSearchSubmit(value);
18128
+ };
18129
+ const handleNotificationClick = () => {
18130
+ if (notificationClickEvent) eventBus.emit(`UI:${notificationClickEvent}`, {});
18131
+ if (onNotificationClick) onNotificationClick();
18132
+ };
18114
18133
  const [sidebarOpen, setSidebarOpen] = useState(false);
18115
18134
  const [userMenuOpen, setUserMenuOpen] = useState(false);
18116
18135
  const location = useLocation();
@@ -18191,17 +18210,7 @@ var init_DashboardLayout = __esm({
18191
18210
  ))
18192
18211
  }
18193
18212
  ),
18194
- sidebarFooter || /* @__PURE__ */ jsx(Box, { className: "p-4 border-t border-border dark:border-border", children: /* @__PURE__ */ jsxs(
18195
- Link,
18196
- {
18197
- to: "/settings",
18198
- className: "flex items-center gap-3 px-3 py-2 text-sm text-muted-foreground dark:text-muted-foreground rounded-lg hover:bg-muted dark:hover:bg-muted",
18199
- children: [
18200
- /* @__PURE__ */ jsx(Settings, { className: "h-5 w-5" }),
18201
- t("common.settings")
18202
- ]
18203
- }
18204
- ) })
18213
+ sidebarFooter && /* @__PURE__ */ jsx(Box, { className: "p-4 border-t border-border dark:border-border", children: sidebarFooter })
18205
18214
  ]
18206
18215
  }
18207
18216
  ),
@@ -18228,32 +18237,40 @@ var init_DashboardLayout = __esm({
18228
18237
  children: /* @__PURE__ */ jsx(Menu$1, { className: "h-5 w-5" })
18229
18238
  }
18230
18239
  ),
18231
- showSearch && /* @__PURE__ */ jsx(Box, { className: "hidden sm:block flex-1 max-w-md", children: /* @__PURE__ */ jsxs(Box, { className: "relative", children: [
18240
+ searchEnabled && /* @__PURE__ */ jsx(Box, { className: "hidden sm:block flex-1 max-w-md", children: /* @__PURE__ */ jsxs(Box, { className: "relative", children: [
18232
18241
  /* @__PURE__ */ jsx(Search, { className: "absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground dark:text-muted-foreground" }),
18233
18242
  /* @__PURE__ */ jsx(
18234
18243
  Input,
18235
18244
  {
18236
18245
  type: "search",
18237
18246
  placeholder: t("common.search"),
18238
- className: "pl-10 w-full"
18247
+ className: "pl-10 w-full",
18248
+ onKeyDown: (e) => {
18249
+ if (e.key === "Enter") {
18250
+ handleSearchSubmit(e.target.value);
18251
+ }
18252
+ }
18239
18253
  }
18240
18254
  )
18241
18255
  ] }) }),
18242
18256
  /* @__PURE__ */ jsxs(HStack, { align: "center", gap: "xs", children: [
18243
18257
  headerActions,
18244
- /* @__PURE__ */ jsx(ThemeToggle, {}),
18245
- /* @__PURE__ */ jsxs(
18258
+ showThemeToggle && /* @__PURE__ */ jsx(ThemeToggle, {}),
18259
+ notificationsEnabled && /* @__PURE__ */ jsxs(
18246
18260
  Button,
18247
18261
  {
18248
18262
  variant: "ghost",
18249
18263
  className: "relative p-2 rounded-full hover:bg-muted dark:hover:bg-muted",
18264
+ onClick: handleNotificationClick,
18265
+ "aria-label": t("common.notifications"),
18250
18266
  children: [
18251
18267
  /* @__PURE__ */ jsx(Bell, { className: "h-5 w-5 text-muted-foreground dark:text-muted-foreground" }),
18252
- /* @__PURE__ */ jsx(
18268
+ unreadCount > 0 && /* @__PURE__ */ jsx(
18253
18269
  Box,
18254
18270
  {
18255
18271
  as: "span",
18256
- className: "absolute top-1 right-1 w-2 h-2 bg-error rounded-full"
18272
+ className: "absolute -top-0.5 -right-0.5 min-w-[18px] h-[18px] px-1 bg-error rounded-full text-[10px] font-semibold text-white flex items-center justify-center",
18273
+ children: unreadCount > 99 ? "99+" : unreadCount
18257
18274
  }
18258
18275
  )
18259
18276
  ]
@@ -18318,17 +18335,6 @@ var init_DashboardLayout = __esm({
18318
18335
  }
18319
18336
  )
18320
18337
  ] }),
18321
- /* @__PURE__ */ jsxs(
18322
- Link,
18323
- {
18324
- to: "/settings",
18325
- className: "flex items-center gap-2 px-4 py-2 text-sm text-foreground dark:text-foreground hover:bg-muted dark:hover:bg-muted",
18326
- children: [
18327
- /* @__PURE__ */ jsx(Settings, { className: "h-4 w-4" }),
18328
- t("common.settings")
18329
- ]
18330
- }
18331
- ),
18332
18338
  /* @__PURE__ */ jsxs(
18333
18339
  Button,
18334
18340
  {
@@ -39480,6 +39486,7 @@ function prepareSchemaForPreview(input) {
39480
39486
  // runtime/OrbPreview.tsx
39481
39487
  init_logger();
39482
39488
  var xOrbitalLog2 = createLogger("almadar:runtime:cross-orbital");
39489
+ var navLog = createLogger("almadar:runtime:navigation");
39483
39490
  function normalizeChild(child) {
39484
39491
  if (typeof child === "string") return child;
39485
39492
  if (child === null || typeof child !== "object" || Array.isArray(child)) {
@@ -39555,6 +39562,19 @@ function TraitInitializer({ traits: traits2, orbitalNames, onNavigate, onLocalFa
39555
39562
  }, [bridge.connected, bridge.sendEvent, orbitalNames, uiSlots, onNavigate, embeddedTraits]);
39556
39563
  const opts = orbitalNames ? { onEventProcessed, navigate: onNavigate, traitConfigsByName, orbitalsByTrait, embeddedTraits } : { navigate: onNavigate, persistence, traitConfigsByName, orbitalsByTrait, embeddedTraits };
39557
39564
  const { sendEvent } = useTraitStateMachine(traits2, uiSlots, opts);
39565
+ const prevTraitNamesRef = useRef("");
39566
+ useEffect(() => {
39567
+ const traitNames = traits2.map((b) => b.trait?.name ?? "").filter(Boolean).sort().join(",");
39568
+ if (prevTraitNamesRef.current && prevTraitNamesRef.current !== traitNames) {
39569
+ navLog.info("page:trait-set-changed", {
39570
+ from: prevTraitNamesRef.current,
39571
+ to: traitNames,
39572
+ action: "clearAll-slots"
39573
+ });
39574
+ uiSlots.clearAll();
39575
+ }
39576
+ prevTraitNamesRef.current = traitNames;
39577
+ }, [traits2, uiSlots]);
39558
39578
  const initSentRef = useRef(false);
39559
39579
  useEffect(() => {
39560
39580
  if (!orbitalNames?.length) {
@@ -39569,6 +39589,10 @@ function TraitInitializer({ traits: traits2, orbitalNames, onNavigate, onLocalFa
39569
39589
  }, 5e3);
39570
39590
  return () => clearTimeout(fallback);
39571
39591
  }, [traits2, orbitalNames, sendEvent, onLocalFallback]);
39592
+ const orbitalsKey = (orbitalNames ?? []).slice().sort().join(",");
39593
+ useEffect(() => {
39594
+ initSentRef.current = false;
39595
+ }, [orbitalsKey]);
39572
39596
  useEffect(() => {
39573
39597
  if (!bridge.connected || !orbitalNames?.length || initSentRef.current) return;
39574
39598
  initSentRef.current = true;
@@ -39809,8 +39833,19 @@ function OrbPreview({
39809
39833
  }, [initialPageName, currentPage]);
39810
39834
  const handleNavigate = useCallback((path) => {
39811
39835
  const match = pages.find(({ page }) => page.path === path);
39836
+ navLog.info("handleNavigate", {
39837
+ path,
39838
+ matched: match?.page.name ?? null,
39839
+ availablePaths: pages.map((p2) => p2.page.path)
39840
+ });
39812
39841
  if (match) {
39813
39842
  setCurrentPage(match.page.name);
39843
+ if (typeof window !== "undefined") {
39844
+ const url = new URL(window.location.href);
39845
+ url.searchParams.set("page", path);
39846
+ window.history.pushState({}, "", url.toString());
39847
+ window.dispatchEvent(new PopStateEvent("popstate"));
39848
+ }
39814
39849
  }
39815
39850
  }, [pages]);
39816
39851
  if (!parseResult.ok) {
@@ -39822,18 +39857,30 @@ function OrbPreview({
39822
39857
  const containerRef = useRef(null);
39823
39858
  useEffect(() => {
39824
39859
  const el = containerRef.current;
39825
- if (!el || pages.length <= 1) return;
39860
+ if (!el) return;
39861
+ if (pages.length <= 1) {
39862
+ navLog.info("interceptor:skipped", { reason: "single-page schema", pageCount: pages.length });
39863
+ return;
39864
+ }
39826
39865
  const handler = (e) => {
39827
39866
  const anchor = e.target.closest("a");
39828
39867
  if (!anchor) return;
39829
39868
  const href = anchor.getAttribute("href") ?? anchor.getAttribute("to") ?? "";
39830
- if (!href || href.startsWith("http") || href.startsWith("mailto:") || href.startsWith("#")) return;
39869
+ navLog.info("click:intercepted", {
39870
+ href,
39871
+ anchorText: anchor.textContent?.trim().slice(0, 40)
39872
+ });
39873
+ if (!href || href.startsWith("http") || href.startsWith("mailto:") || href.startsWith("#")) {
39874
+ navLog.info("click:skipped", { href, reason: "external/empty/hash" });
39875
+ return;
39876
+ }
39831
39877
  e.preventDefault();
39832
39878
  e.stopPropagation();
39833
39879
  e.stopImmediatePropagation();
39834
39880
  handleNavigate(href);
39835
39881
  };
39836
39882
  el.addEventListener("click", handler, true);
39883
+ navLog.info("interceptor:installed", { pageCount: pages.length, paths: pages.map((p2) => p2.page.path) });
39837
39884
  return () => el.removeEventListener("click", handler, true);
39838
39885
  }, [pages, handleNavigate]);
39839
39886
  return /* @__PURE__ */ jsxs(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@almadar/ui",
3
- "version": "4.22.4",
3
+ "version": "4.24.0",
4
4
  "description": "React UI components, hooks, and providers for Almadar",
5
5
  "type": "module",
6
6
  "main": "./dist/components/index.js",