@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.
- package/dist/avl/index.cjs +78 -31
- package/dist/avl/index.js +79 -32
- package/dist/components/index.cjs +35 -29
- package/dist/components/index.js +36 -30
- package/dist/components/templates/DashboardLayout.d.ts +40 -4
- package/dist/providers/index.cjs +35 -29
- package/dist/providers/index.js +36 -30
- package/dist/runtime/index.cjs +78 -31
- package/dist/runtime/index.js +79 -32
- package/package.json +1 -1
package/dist/avl/index.cjs
CHANGED
|
@@ -21617,6 +21617,7 @@ var init_DashboardLayout = __esm({
|
|
|
21617
21617
|
init_Typography();
|
|
21618
21618
|
init_Icon();
|
|
21619
21619
|
init_useAuthContext();
|
|
21620
|
+
init_useEventBus();
|
|
21620
21621
|
init_useTranslate();
|
|
21621
21622
|
DashboardLayout = ({
|
|
21622
21623
|
appName = "{{APP_TITLE}}",
|
|
@@ -21624,11 +21625,29 @@ var init_DashboardLayout = __esm({
|
|
|
21624
21625
|
navItems = [],
|
|
21625
21626
|
user: userProp,
|
|
21626
21627
|
headerActions,
|
|
21627
|
-
showSearch =
|
|
21628
|
+
showSearch = false,
|
|
21629
|
+
searchEvent,
|
|
21630
|
+
onSearchSubmit,
|
|
21631
|
+
notifications,
|
|
21632
|
+
notificationClickEvent,
|
|
21633
|
+
onNotificationClick,
|
|
21634
|
+
showThemeToggle = true,
|
|
21628
21635
|
sidebarFooter,
|
|
21629
21636
|
onSignOut: onSignOutProp,
|
|
21630
21637
|
children
|
|
21631
21638
|
}) => {
|
|
21639
|
+
const eventBus = useEventBus();
|
|
21640
|
+
const searchEnabled = showSearch || Boolean(searchEvent) || Boolean(onSearchSubmit);
|
|
21641
|
+
const notificationsEnabled = Array.isArray(notifications);
|
|
21642
|
+
const unreadCount = notificationsEnabled ? notifications.filter((n) => n.read !== true).length : 0;
|
|
21643
|
+
const handleSearchSubmit = (value) => {
|
|
21644
|
+
if (searchEvent) eventBus.emit(`UI:${searchEvent}`, { value });
|
|
21645
|
+
if (onSearchSubmit) onSearchSubmit(value);
|
|
21646
|
+
};
|
|
21647
|
+
const handleNotificationClick = () => {
|
|
21648
|
+
if (notificationClickEvent) eventBus.emit(`UI:${notificationClickEvent}`, {});
|
|
21649
|
+
if (onNotificationClick) onNotificationClick();
|
|
21650
|
+
};
|
|
21632
21651
|
const [sidebarOpen, setSidebarOpen] = React127.useState(false);
|
|
21633
21652
|
const [userMenuOpen, setUserMenuOpen] = React127.useState(false);
|
|
21634
21653
|
const location = reactRouterDom.useLocation();
|
|
@@ -21709,17 +21728,7 @@ var init_DashboardLayout = __esm({
|
|
|
21709
21728
|
))
|
|
21710
21729
|
}
|
|
21711
21730
|
),
|
|
21712
|
-
sidebarFooter
|
|
21713
|
-
reactRouterDom.Link,
|
|
21714
|
-
{
|
|
21715
|
-
to: "/settings",
|
|
21716
|
-
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",
|
|
21717
|
-
children: [
|
|
21718
|
-
/* @__PURE__ */ jsxRuntime.jsx(LucideIcons.Settings, { className: "h-5 w-5" }),
|
|
21719
|
-
t("common.settings")
|
|
21720
|
-
]
|
|
21721
|
-
}
|
|
21722
|
-
) })
|
|
21731
|
+
sidebarFooter && /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "p-4 border-t border-border dark:border-border", children: sidebarFooter })
|
|
21723
21732
|
]
|
|
21724
21733
|
}
|
|
21725
21734
|
),
|
|
@@ -21746,32 +21755,40 @@ var init_DashboardLayout = __esm({
|
|
|
21746
21755
|
children: /* @__PURE__ */ jsxRuntime.jsx(LucideIcons.Menu, { className: "h-5 w-5" })
|
|
21747
21756
|
}
|
|
21748
21757
|
),
|
|
21749
|
-
|
|
21758
|
+
searchEnabled && /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "hidden sm:block flex-1 max-w-md", children: /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "relative", children: [
|
|
21750
21759
|
/* @__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" }),
|
|
21751
21760
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
21752
21761
|
Input,
|
|
21753
21762
|
{
|
|
21754
21763
|
type: "search",
|
|
21755
21764
|
placeholder: t("common.search"),
|
|
21756
|
-
className: "pl-10 w-full"
|
|
21765
|
+
className: "pl-10 w-full",
|
|
21766
|
+
onKeyDown: (e) => {
|
|
21767
|
+
if (e.key === "Enter") {
|
|
21768
|
+
handleSearchSubmit(e.target.value);
|
|
21769
|
+
}
|
|
21770
|
+
}
|
|
21757
21771
|
}
|
|
21758
21772
|
)
|
|
21759
21773
|
] }) }),
|
|
21760
21774
|
/* @__PURE__ */ jsxRuntime.jsxs(HStack, { align: "center", gap: "xs", children: [
|
|
21761
21775
|
headerActions,
|
|
21762
|
-
/* @__PURE__ */ jsxRuntime.jsx(ThemeToggle, {}),
|
|
21763
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
21776
|
+
showThemeToggle && /* @__PURE__ */ jsxRuntime.jsx(ThemeToggle, {}),
|
|
21777
|
+
notificationsEnabled && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
21764
21778
|
Button,
|
|
21765
21779
|
{
|
|
21766
21780
|
variant: "ghost",
|
|
21767
21781
|
className: "relative p-2 rounded-full hover:bg-muted dark:hover:bg-muted",
|
|
21782
|
+
onClick: handleNotificationClick,
|
|
21783
|
+
"aria-label": t("common.notifications"),
|
|
21768
21784
|
children: [
|
|
21769
21785
|
/* @__PURE__ */ jsxRuntime.jsx(LucideIcons.Bell, { className: "h-5 w-5 text-muted-foreground dark:text-muted-foreground" }),
|
|
21770
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
21786
|
+
unreadCount > 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
21771
21787
|
Box,
|
|
21772
21788
|
{
|
|
21773
21789
|
as: "span",
|
|
21774
|
-
className: "absolute top-
|
|
21790
|
+
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",
|
|
21791
|
+
children: unreadCount > 99 ? "99+" : unreadCount
|
|
21775
21792
|
}
|
|
21776
21793
|
)
|
|
21777
21794
|
]
|
|
@@ -21836,17 +21853,6 @@ var init_DashboardLayout = __esm({
|
|
|
21836
21853
|
}
|
|
21837
21854
|
)
|
|
21838
21855
|
] }),
|
|
21839
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
21840
|
-
reactRouterDom.Link,
|
|
21841
|
-
{
|
|
21842
|
-
to: "/settings",
|
|
21843
|
-
className: "flex items-center gap-2 px-4 py-2 text-sm text-foreground dark:text-foreground hover:bg-muted dark:hover:bg-muted",
|
|
21844
|
-
children: [
|
|
21845
|
-
/* @__PURE__ */ jsxRuntime.jsx(LucideIcons.Settings, { className: "h-4 w-4" }),
|
|
21846
|
-
t("common.settings")
|
|
21847
|
-
]
|
|
21848
|
-
}
|
|
21849
|
-
),
|
|
21850
21856
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
21851
21857
|
Button,
|
|
21852
21858
|
{
|
|
@@ -52767,6 +52773,7 @@ function prepareSchemaForPreview(input) {
|
|
|
52767
52773
|
// runtime/OrbPreview.tsx
|
|
52768
52774
|
init_logger();
|
|
52769
52775
|
var xOrbitalLog2 = createLogger("almadar:runtime:cross-orbital");
|
|
52776
|
+
var navLog = createLogger("almadar:runtime:navigation");
|
|
52770
52777
|
function normalizeChild(child) {
|
|
52771
52778
|
if (typeof child === "string") return child;
|
|
52772
52779
|
if (child === null || typeof child !== "object" || Array.isArray(child)) {
|
|
@@ -52842,6 +52849,19 @@ function TraitInitializer({ traits: traits2, orbitalNames, onNavigate, onLocalFa
|
|
|
52842
52849
|
}, [bridge.connected, bridge.sendEvent, orbitalNames, uiSlots, onNavigate, embeddedTraits]);
|
|
52843
52850
|
const opts = orbitalNames ? { onEventProcessed, navigate: onNavigate, traitConfigsByName, orbitalsByTrait, embeddedTraits } : { navigate: onNavigate, persistence, traitConfigsByName, orbitalsByTrait, embeddedTraits };
|
|
52844
52851
|
const { sendEvent } = useTraitStateMachine(traits2, uiSlots, opts);
|
|
52852
|
+
const prevTraitNamesRef = React127.useRef("");
|
|
52853
|
+
React127.useEffect(() => {
|
|
52854
|
+
const traitNames = traits2.map((b) => b.trait?.name ?? "").filter(Boolean).sort().join(",");
|
|
52855
|
+
if (prevTraitNamesRef.current && prevTraitNamesRef.current !== traitNames) {
|
|
52856
|
+
navLog.info("page:trait-set-changed", {
|
|
52857
|
+
from: prevTraitNamesRef.current,
|
|
52858
|
+
to: traitNames,
|
|
52859
|
+
action: "clearAll-slots"
|
|
52860
|
+
});
|
|
52861
|
+
uiSlots.clearAll();
|
|
52862
|
+
}
|
|
52863
|
+
prevTraitNamesRef.current = traitNames;
|
|
52864
|
+
}, [traits2, uiSlots]);
|
|
52845
52865
|
const initSentRef = React127.useRef(false);
|
|
52846
52866
|
React127.useEffect(() => {
|
|
52847
52867
|
if (!orbitalNames?.length) {
|
|
@@ -52856,6 +52876,10 @@ function TraitInitializer({ traits: traits2, orbitalNames, onNavigate, onLocalFa
|
|
|
52856
52876
|
}, 5e3);
|
|
52857
52877
|
return () => clearTimeout(fallback);
|
|
52858
52878
|
}, [traits2, orbitalNames, sendEvent, onLocalFallback]);
|
|
52879
|
+
const orbitalsKey = (orbitalNames ?? []).slice().sort().join(",");
|
|
52880
|
+
React127.useEffect(() => {
|
|
52881
|
+
initSentRef.current = false;
|
|
52882
|
+
}, [orbitalsKey]);
|
|
52859
52883
|
React127.useEffect(() => {
|
|
52860
52884
|
if (!bridge.connected || !orbitalNames?.length || initSentRef.current) return;
|
|
52861
52885
|
initSentRef.current = true;
|
|
@@ -53096,8 +53120,19 @@ function OrbPreview({
|
|
|
53096
53120
|
}, [initialPageName, currentPage]);
|
|
53097
53121
|
const handleNavigate = React127.useCallback((path) => {
|
|
53098
53122
|
const match = pages.find(({ page }) => page.path === path);
|
|
53123
|
+
navLog.info("handleNavigate", {
|
|
53124
|
+
path,
|
|
53125
|
+
matched: match?.page.name ?? null,
|
|
53126
|
+
availablePaths: pages.map((p2) => p2.page.path)
|
|
53127
|
+
});
|
|
53099
53128
|
if (match) {
|
|
53100
53129
|
setCurrentPage(match.page.name);
|
|
53130
|
+
if (typeof window !== "undefined") {
|
|
53131
|
+
const url = new URL(window.location.href);
|
|
53132
|
+
url.searchParams.set("page", path);
|
|
53133
|
+
window.history.pushState({}, "", url.toString());
|
|
53134
|
+
window.dispatchEvent(new PopStateEvent("popstate"));
|
|
53135
|
+
}
|
|
53101
53136
|
}
|
|
53102
53137
|
}, [pages]);
|
|
53103
53138
|
if (!parseResult.ok) {
|
|
@@ -53109,18 +53144,30 @@ function OrbPreview({
|
|
|
53109
53144
|
const containerRef = React127.useRef(null);
|
|
53110
53145
|
React127.useEffect(() => {
|
|
53111
53146
|
const el = containerRef.current;
|
|
53112
|
-
if (!el
|
|
53147
|
+
if (!el) return;
|
|
53148
|
+
if (pages.length <= 1) {
|
|
53149
|
+
navLog.info("interceptor:skipped", { reason: "single-page schema", pageCount: pages.length });
|
|
53150
|
+
return;
|
|
53151
|
+
}
|
|
53113
53152
|
const handler = (e) => {
|
|
53114
53153
|
const anchor = e.target.closest("a");
|
|
53115
53154
|
if (!anchor) return;
|
|
53116
53155
|
const href = anchor.getAttribute("href") ?? anchor.getAttribute("to") ?? "";
|
|
53117
|
-
|
|
53156
|
+
navLog.info("click:intercepted", {
|
|
53157
|
+
href,
|
|
53158
|
+
anchorText: anchor.textContent?.trim().slice(0, 40)
|
|
53159
|
+
});
|
|
53160
|
+
if (!href || href.startsWith("http") || href.startsWith("mailto:") || href.startsWith("#")) {
|
|
53161
|
+
navLog.info("click:skipped", { href, reason: "external/empty/hash" });
|
|
53162
|
+
return;
|
|
53163
|
+
}
|
|
53118
53164
|
e.preventDefault();
|
|
53119
53165
|
e.stopPropagation();
|
|
53120
53166
|
e.stopImmediatePropagation();
|
|
53121
53167
|
handleNavigate(href);
|
|
53122
53168
|
};
|
|
53123
53169
|
el.addEventListener("click", handler, true);
|
|
53170
|
+
navLog.info("interceptor:installed", { pageCount: pages.length, paths: pages.map((p2) => p2.page.path) });
|
|
53124
53171
|
return () => el.removeEventListener("click", handler, true);
|
|
53125
53172
|
}, [pages, handleNavigate]);
|
|
53126
53173
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
package/dist/avl/index.js
CHANGED
|
@@ -3,7 +3,7 @@ import { Html, RoundedBox, OrbitControls as OrbitControls$1, Grid as Grid$1, Sta
|
|
|
3
3
|
import * as React127 from 'react';
|
|
4
4
|
import React127__default, { createContext, useContext, useRef, useState, useCallback, useMemo, useEffect, Suspense, useLayoutEffect, useReducer, lazy, useId, forwardRef, useImperativeHandle, Component } from 'react';
|
|
5
5
|
import * as LucideIcons from 'lucide-react';
|
|
6
|
-
import { Loader2, ChevronDown, X, Check, Copy, AlertTriangle, Info, AlertCircle, CheckCircle, List, Printer, ChevronRight, ChevronLeft, Code, FileText, WrapText, Trash2,
|
|
6
|
+
import { Loader2, ChevronDown, X, Check, Copy, AlertTriangle, Info, AlertCircle, CheckCircle, List, Printer, ChevronRight, ChevronLeft, Code, FileText, WrapText, Trash2, Menu as Menu$1, Search, Bell, 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';
|
|
7
7
|
import { evaluate, createMinimalContext } from '@almadar/evaluator';
|
|
8
8
|
import { getPatternDefinition, getComponentForPattern as getComponentForPattern$1, isEntityAwarePattern } from '@almadar/patterns';
|
|
9
9
|
import { createPortal } from 'react-dom';
|
|
@@ -21571,6 +21571,7 @@ var init_DashboardLayout = __esm({
|
|
|
21571
21571
|
init_Typography();
|
|
21572
21572
|
init_Icon();
|
|
21573
21573
|
init_useAuthContext();
|
|
21574
|
+
init_useEventBus();
|
|
21574
21575
|
init_useTranslate();
|
|
21575
21576
|
DashboardLayout = ({
|
|
21576
21577
|
appName = "{{APP_TITLE}}",
|
|
@@ -21578,11 +21579,29 @@ var init_DashboardLayout = __esm({
|
|
|
21578
21579
|
navItems = [],
|
|
21579
21580
|
user: userProp,
|
|
21580
21581
|
headerActions,
|
|
21581
|
-
showSearch =
|
|
21582
|
+
showSearch = false,
|
|
21583
|
+
searchEvent,
|
|
21584
|
+
onSearchSubmit,
|
|
21585
|
+
notifications,
|
|
21586
|
+
notificationClickEvent,
|
|
21587
|
+
onNotificationClick,
|
|
21588
|
+
showThemeToggle = true,
|
|
21582
21589
|
sidebarFooter,
|
|
21583
21590
|
onSignOut: onSignOutProp,
|
|
21584
21591
|
children
|
|
21585
21592
|
}) => {
|
|
21593
|
+
const eventBus = useEventBus();
|
|
21594
|
+
const searchEnabled = showSearch || Boolean(searchEvent) || Boolean(onSearchSubmit);
|
|
21595
|
+
const notificationsEnabled = Array.isArray(notifications);
|
|
21596
|
+
const unreadCount = notificationsEnabled ? notifications.filter((n) => n.read !== true).length : 0;
|
|
21597
|
+
const handleSearchSubmit = (value) => {
|
|
21598
|
+
if (searchEvent) eventBus.emit(`UI:${searchEvent}`, { value });
|
|
21599
|
+
if (onSearchSubmit) onSearchSubmit(value);
|
|
21600
|
+
};
|
|
21601
|
+
const handleNotificationClick = () => {
|
|
21602
|
+
if (notificationClickEvent) eventBus.emit(`UI:${notificationClickEvent}`, {});
|
|
21603
|
+
if (onNotificationClick) onNotificationClick();
|
|
21604
|
+
};
|
|
21586
21605
|
const [sidebarOpen, setSidebarOpen] = useState(false);
|
|
21587
21606
|
const [userMenuOpen, setUserMenuOpen] = useState(false);
|
|
21588
21607
|
const location = useLocation();
|
|
@@ -21663,17 +21682,7 @@ var init_DashboardLayout = __esm({
|
|
|
21663
21682
|
))
|
|
21664
21683
|
}
|
|
21665
21684
|
),
|
|
21666
|
-
sidebarFooter
|
|
21667
|
-
Link,
|
|
21668
|
-
{
|
|
21669
|
-
to: "/settings",
|
|
21670
|
-
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",
|
|
21671
|
-
children: [
|
|
21672
|
-
/* @__PURE__ */ jsx(Settings, { className: "h-5 w-5" }),
|
|
21673
|
-
t("common.settings")
|
|
21674
|
-
]
|
|
21675
|
-
}
|
|
21676
|
-
) })
|
|
21685
|
+
sidebarFooter && /* @__PURE__ */ jsx(Box, { className: "p-4 border-t border-border dark:border-border", children: sidebarFooter })
|
|
21677
21686
|
]
|
|
21678
21687
|
}
|
|
21679
21688
|
),
|
|
@@ -21700,32 +21709,40 @@ var init_DashboardLayout = __esm({
|
|
|
21700
21709
|
children: /* @__PURE__ */ jsx(Menu$1, { className: "h-5 w-5" })
|
|
21701
21710
|
}
|
|
21702
21711
|
),
|
|
21703
|
-
|
|
21712
|
+
searchEnabled && /* @__PURE__ */ jsx(Box, { className: "hidden sm:block flex-1 max-w-md", children: /* @__PURE__ */ jsxs(Box, { className: "relative", children: [
|
|
21704
21713
|
/* @__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" }),
|
|
21705
21714
|
/* @__PURE__ */ jsx(
|
|
21706
21715
|
Input,
|
|
21707
21716
|
{
|
|
21708
21717
|
type: "search",
|
|
21709
21718
|
placeholder: t("common.search"),
|
|
21710
|
-
className: "pl-10 w-full"
|
|
21719
|
+
className: "pl-10 w-full",
|
|
21720
|
+
onKeyDown: (e) => {
|
|
21721
|
+
if (e.key === "Enter") {
|
|
21722
|
+
handleSearchSubmit(e.target.value);
|
|
21723
|
+
}
|
|
21724
|
+
}
|
|
21711
21725
|
}
|
|
21712
21726
|
)
|
|
21713
21727
|
] }) }),
|
|
21714
21728
|
/* @__PURE__ */ jsxs(HStack, { align: "center", gap: "xs", children: [
|
|
21715
21729
|
headerActions,
|
|
21716
|
-
/* @__PURE__ */ jsx(ThemeToggle, {}),
|
|
21717
|
-
/* @__PURE__ */ jsxs(
|
|
21730
|
+
showThemeToggle && /* @__PURE__ */ jsx(ThemeToggle, {}),
|
|
21731
|
+
notificationsEnabled && /* @__PURE__ */ jsxs(
|
|
21718
21732
|
Button,
|
|
21719
21733
|
{
|
|
21720
21734
|
variant: "ghost",
|
|
21721
21735
|
className: "relative p-2 rounded-full hover:bg-muted dark:hover:bg-muted",
|
|
21736
|
+
onClick: handleNotificationClick,
|
|
21737
|
+
"aria-label": t("common.notifications"),
|
|
21722
21738
|
children: [
|
|
21723
21739
|
/* @__PURE__ */ jsx(Bell, { className: "h-5 w-5 text-muted-foreground dark:text-muted-foreground" }),
|
|
21724
|
-
/* @__PURE__ */ jsx(
|
|
21740
|
+
unreadCount > 0 && /* @__PURE__ */ jsx(
|
|
21725
21741
|
Box,
|
|
21726
21742
|
{
|
|
21727
21743
|
as: "span",
|
|
21728
|
-
className: "absolute top-
|
|
21744
|
+
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",
|
|
21745
|
+
children: unreadCount > 99 ? "99+" : unreadCount
|
|
21729
21746
|
}
|
|
21730
21747
|
)
|
|
21731
21748
|
]
|
|
@@ -21790,17 +21807,6 @@ var init_DashboardLayout = __esm({
|
|
|
21790
21807
|
}
|
|
21791
21808
|
)
|
|
21792
21809
|
] }),
|
|
21793
|
-
/* @__PURE__ */ jsxs(
|
|
21794
|
-
Link,
|
|
21795
|
-
{
|
|
21796
|
-
to: "/settings",
|
|
21797
|
-
className: "flex items-center gap-2 px-4 py-2 text-sm text-foreground dark:text-foreground hover:bg-muted dark:hover:bg-muted",
|
|
21798
|
-
children: [
|
|
21799
|
-
/* @__PURE__ */ jsx(Settings, { className: "h-4 w-4" }),
|
|
21800
|
-
t("common.settings")
|
|
21801
|
-
]
|
|
21802
|
-
}
|
|
21803
|
-
),
|
|
21804
21810
|
/* @__PURE__ */ jsxs(
|
|
21805
21811
|
Button,
|
|
21806
21812
|
{
|
|
@@ -52721,6 +52727,7 @@ function prepareSchemaForPreview(input) {
|
|
|
52721
52727
|
// runtime/OrbPreview.tsx
|
|
52722
52728
|
init_logger();
|
|
52723
52729
|
var xOrbitalLog2 = createLogger("almadar:runtime:cross-orbital");
|
|
52730
|
+
var navLog = createLogger("almadar:runtime:navigation");
|
|
52724
52731
|
function normalizeChild(child) {
|
|
52725
52732
|
if (typeof child === "string") return child;
|
|
52726
52733
|
if (child === null || typeof child !== "object" || Array.isArray(child)) {
|
|
@@ -52796,6 +52803,19 @@ function TraitInitializer({ traits: traits2, orbitalNames, onNavigate, onLocalFa
|
|
|
52796
52803
|
}, [bridge.connected, bridge.sendEvent, orbitalNames, uiSlots, onNavigate, embeddedTraits]);
|
|
52797
52804
|
const opts = orbitalNames ? { onEventProcessed, navigate: onNavigate, traitConfigsByName, orbitalsByTrait, embeddedTraits } : { navigate: onNavigate, persistence, traitConfigsByName, orbitalsByTrait, embeddedTraits };
|
|
52798
52805
|
const { sendEvent } = useTraitStateMachine(traits2, uiSlots, opts);
|
|
52806
|
+
const prevTraitNamesRef = useRef("");
|
|
52807
|
+
useEffect(() => {
|
|
52808
|
+
const traitNames = traits2.map((b) => b.trait?.name ?? "").filter(Boolean).sort().join(",");
|
|
52809
|
+
if (prevTraitNamesRef.current && prevTraitNamesRef.current !== traitNames) {
|
|
52810
|
+
navLog.info("page:trait-set-changed", {
|
|
52811
|
+
from: prevTraitNamesRef.current,
|
|
52812
|
+
to: traitNames,
|
|
52813
|
+
action: "clearAll-slots"
|
|
52814
|
+
});
|
|
52815
|
+
uiSlots.clearAll();
|
|
52816
|
+
}
|
|
52817
|
+
prevTraitNamesRef.current = traitNames;
|
|
52818
|
+
}, [traits2, uiSlots]);
|
|
52799
52819
|
const initSentRef = useRef(false);
|
|
52800
52820
|
useEffect(() => {
|
|
52801
52821
|
if (!orbitalNames?.length) {
|
|
@@ -52810,6 +52830,10 @@ function TraitInitializer({ traits: traits2, orbitalNames, onNavigate, onLocalFa
|
|
|
52810
52830
|
}, 5e3);
|
|
52811
52831
|
return () => clearTimeout(fallback);
|
|
52812
52832
|
}, [traits2, orbitalNames, sendEvent, onLocalFallback]);
|
|
52833
|
+
const orbitalsKey = (orbitalNames ?? []).slice().sort().join(",");
|
|
52834
|
+
useEffect(() => {
|
|
52835
|
+
initSentRef.current = false;
|
|
52836
|
+
}, [orbitalsKey]);
|
|
52813
52837
|
useEffect(() => {
|
|
52814
52838
|
if (!bridge.connected || !orbitalNames?.length || initSentRef.current) return;
|
|
52815
52839
|
initSentRef.current = true;
|
|
@@ -53050,8 +53074,19 @@ function OrbPreview({
|
|
|
53050
53074
|
}, [initialPageName, currentPage]);
|
|
53051
53075
|
const handleNavigate = useCallback((path) => {
|
|
53052
53076
|
const match = pages.find(({ page }) => page.path === path);
|
|
53077
|
+
navLog.info("handleNavigate", {
|
|
53078
|
+
path,
|
|
53079
|
+
matched: match?.page.name ?? null,
|
|
53080
|
+
availablePaths: pages.map((p2) => p2.page.path)
|
|
53081
|
+
});
|
|
53053
53082
|
if (match) {
|
|
53054
53083
|
setCurrentPage(match.page.name);
|
|
53084
|
+
if (typeof window !== "undefined") {
|
|
53085
|
+
const url = new URL(window.location.href);
|
|
53086
|
+
url.searchParams.set("page", path);
|
|
53087
|
+
window.history.pushState({}, "", url.toString());
|
|
53088
|
+
window.dispatchEvent(new PopStateEvent("popstate"));
|
|
53089
|
+
}
|
|
53055
53090
|
}
|
|
53056
53091
|
}, [pages]);
|
|
53057
53092
|
if (!parseResult.ok) {
|
|
@@ -53063,18 +53098,30 @@ function OrbPreview({
|
|
|
53063
53098
|
const containerRef = useRef(null);
|
|
53064
53099
|
useEffect(() => {
|
|
53065
53100
|
const el = containerRef.current;
|
|
53066
|
-
if (!el
|
|
53101
|
+
if (!el) return;
|
|
53102
|
+
if (pages.length <= 1) {
|
|
53103
|
+
navLog.info("interceptor:skipped", { reason: "single-page schema", pageCount: pages.length });
|
|
53104
|
+
return;
|
|
53105
|
+
}
|
|
53067
53106
|
const handler = (e) => {
|
|
53068
53107
|
const anchor = e.target.closest("a");
|
|
53069
53108
|
if (!anchor) return;
|
|
53070
53109
|
const href = anchor.getAttribute("href") ?? anchor.getAttribute("to") ?? "";
|
|
53071
|
-
|
|
53110
|
+
navLog.info("click:intercepted", {
|
|
53111
|
+
href,
|
|
53112
|
+
anchorText: anchor.textContent?.trim().slice(0, 40)
|
|
53113
|
+
});
|
|
53114
|
+
if (!href || href.startsWith("http") || href.startsWith("mailto:") || href.startsWith("#")) {
|
|
53115
|
+
navLog.info("click:skipped", { href, reason: "external/empty/hash" });
|
|
53116
|
+
return;
|
|
53117
|
+
}
|
|
53072
53118
|
e.preventDefault();
|
|
53073
53119
|
e.stopPropagation();
|
|
53074
53120
|
e.stopImmediatePropagation();
|
|
53075
53121
|
handleNavigate(href);
|
|
53076
53122
|
};
|
|
53077
53123
|
el.addEventListener("click", handler, true);
|
|
53124
|
+
navLog.info("interceptor:installed", { pageCount: pages.length, paths: pages.map((p2) => p2.page.path) });
|
|
53078
53125
|
return () => el.removeEventListener("click", handler, true);
|
|
53079
53126
|
}, [pages, handleNavigate]);
|
|
53080
53127
|
return /* @__PURE__ */ jsxs(
|
|
@@ -17041,6 +17041,7 @@ var init_DashboardLayout = __esm({
|
|
|
17041
17041
|
init_Typography();
|
|
17042
17042
|
init_Icon();
|
|
17043
17043
|
init_useAuthContext();
|
|
17044
|
+
init_useEventBus();
|
|
17044
17045
|
init_useTranslate();
|
|
17045
17046
|
exports.DashboardLayout = ({
|
|
17046
17047
|
appName = "{{APP_TITLE}}",
|
|
@@ -17048,11 +17049,29 @@ var init_DashboardLayout = __esm({
|
|
|
17048
17049
|
navItems = [],
|
|
17049
17050
|
user: userProp,
|
|
17050
17051
|
headerActions,
|
|
17051
|
-
showSearch =
|
|
17052
|
+
showSearch = false,
|
|
17053
|
+
searchEvent,
|
|
17054
|
+
onSearchSubmit,
|
|
17055
|
+
notifications,
|
|
17056
|
+
notificationClickEvent,
|
|
17057
|
+
onNotificationClick,
|
|
17058
|
+
showThemeToggle = true,
|
|
17052
17059
|
sidebarFooter,
|
|
17053
17060
|
onSignOut: onSignOutProp,
|
|
17054
17061
|
children
|
|
17055
17062
|
}) => {
|
|
17063
|
+
const eventBus = useEventBus();
|
|
17064
|
+
const searchEnabled = showSearch || Boolean(searchEvent) || Boolean(onSearchSubmit);
|
|
17065
|
+
const notificationsEnabled = Array.isArray(notifications);
|
|
17066
|
+
const unreadCount = notificationsEnabled ? notifications.filter((n) => n.read !== true).length : 0;
|
|
17067
|
+
const handleSearchSubmit = (value) => {
|
|
17068
|
+
if (searchEvent) eventBus.emit(`UI:${searchEvent}`, { value });
|
|
17069
|
+
if (onSearchSubmit) onSearchSubmit(value);
|
|
17070
|
+
};
|
|
17071
|
+
const handleNotificationClick = () => {
|
|
17072
|
+
if (notificationClickEvent) eventBus.emit(`UI:${notificationClickEvent}`, {});
|
|
17073
|
+
if (onNotificationClick) onNotificationClick();
|
|
17074
|
+
};
|
|
17056
17075
|
const [sidebarOpen, setSidebarOpen] = React110.useState(false);
|
|
17057
17076
|
const [userMenuOpen, setUserMenuOpen] = React110.useState(false);
|
|
17058
17077
|
const location = reactRouterDom.useLocation();
|
|
@@ -17137,17 +17156,7 @@ var init_DashboardLayout = __esm({
|
|
|
17137
17156
|
))
|
|
17138
17157
|
}
|
|
17139
17158
|
),
|
|
17140
|
-
sidebarFooter
|
|
17141
|
-
reactRouterDom.Link,
|
|
17142
|
-
{
|
|
17143
|
-
to: "/settings",
|
|
17144
|
-
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",
|
|
17145
|
-
children: [
|
|
17146
|
-
/* @__PURE__ */ jsxRuntime.jsx(LucideIcons.Settings, { className: "h-5 w-5" }),
|
|
17147
|
-
t("common.settings")
|
|
17148
|
-
]
|
|
17149
|
-
}
|
|
17150
|
-
) })
|
|
17159
|
+
sidebarFooter && /* @__PURE__ */ jsxRuntime.jsx(exports.Box, { className: "p-4 border-t border-border dark:border-border", children: sidebarFooter })
|
|
17151
17160
|
]
|
|
17152
17161
|
}
|
|
17153
17162
|
),
|
|
@@ -17174,32 +17183,40 @@ var init_DashboardLayout = __esm({
|
|
|
17174
17183
|
children: /* @__PURE__ */ jsxRuntime.jsx(LucideIcons.Menu, { className: "h-5 w-5" })
|
|
17175
17184
|
}
|
|
17176
17185
|
),
|
|
17177
|
-
|
|
17186
|
+
searchEnabled && /* @__PURE__ */ jsxRuntime.jsx(exports.Box, { className: "hidden sm:block flex-1 max-w-md", children: /* @__PURE__ */ jsxRuntime.jsxs(exports.Box, { className: "relative", children: [
|
|
17178
17187
|
/* @__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" }),
|
|
17179
17188
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
17180
17189
|
exports.Input,
|
|
17181
17190
|
{
|
|
17182
17191
|
type: "search",
|
|
17183
17192
|
placeholder: t("common.search"),
|
|
17184
|
-
className: "pl-10 w-full"
|
|
17193
|
+
className: "pl-10 w-full",
|
|
17194
|
+
onKeyDown: (e) => {
|
|
17195
|
+
if (e.key === "Enter") {
|
|
17196
|
+
handleSearchSubmit(e.target.value);
|
|
17197
|
+
}
|
|
17198
|
+
}
|
|
17185
17199
|
}
|
|
17186
17200
|
)
|
|
17187
17201
|
] }) }),
|
|
17188
17202
|
/* @__PURE__ */ jsxRuntime.jsxs(exports.HStack, { align: "center", gap: "xs", children: [
|
|
17189
17203
|
headerActions,
|
|
17190
|
-
/* @__PURE__ */ jsxRuntime.jsx(exports.ThemeToggle, {}),
|
|
17191
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
17204
|
+
showThemeToggle && /* @__PURE__ */ jsxRuntime.jsx(exports.ThemeToggle, {}),
|
|
17205
|
+
notificationsEnabled && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
17192
17206
|
exports.Button,
|
|
17193
17207
|
{
|
|
17194
17208
|
variant: "ghost",
|
|
17195
17209
|
className: "relative p-2 rounded-full hover:bg-muted dark:hover:bg-muted",
|
|
17210
|
+
onClick: handleNotificationClick,
|
|
17211
|
+
"aria-label": t("common.notifications"),
|
|
17196
17212
|
children: [
|
|
17197
17213
|
/* @__PURE__ */ jsxRuntime.jsx(LucideIcons.Bell, { className: "h-5 w-5 text-muted-foreground dark:text-muted-foreground" }),
|
|
17198
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
17214
|
+
unreadCount > 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
17199
17215
|
exports.Box,
|
|
17200
17216
|
{
|
|
17201
17217
|
as: "span",
|
|
17202
|
-
className: "absolute top-
|
|
17218
|
+
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",
|
|
17219
|
+
children: unreadCount > 99 ? "99+" : unreadCount
|
|
17203
17220
|
}
|
|
17204
17221
|
)
|
|
17205
17222
|
]
|
|
@@ -17264,17 +17281,6 @@ var init_DashboardLayout = __esm({
|
|
|
17264
17281
|
}
|
|
17265
17282
|
)
|
|
17266
17283
|
] }),
|
|
17267
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
17268
|
-
reactRouterDom.Link,
|
|
17269
|
-
{
|
|
17270
|
-
to: "/settings",
|
|
17271
|
-
className: "flex items-center gap-2 px-4 py-2 text-sm text-foreground dark:text-foreground hover:bg-muted dark:hover:bg-muted",
|
|
17272
|
-
children: [
|
|
17273
|
-
/* @__PURE__ */ jsxRuntime.jsx(LucideIcons.Settings, { className: "h-4 w-4" }),
|
|
17274
|
-
t("common.settings")
|
|
17275
|
-
]
|
|
17276
|
-
}
|
|
17277
|
-
),
|
|
17278
17284
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
17279
17285
|
exports.Button,
|
|
17280
17286
|
{
|