@almadar/ui 5.15.0 → 5.16.1

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.js CHANGED
@@ -14577,13 +14577,13 @@ var init_MapView = __esm({
14577
14577
  shadowSize: [41, 41]
14578
14578
  });
14579
14579
  L.Marker.prototype.options.icon = defaultIcon;
14580
- const { useEffect: useEffect89, useRef: useRef88, useCallback: useCallback130, useState: useState125 } = React98__default;
14580
+ const { useEffect: useEffect90, useRef: useRef89, useCallback: useCallback130, useState: useState125 } = React98__default;
14581
14581
  const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
14582
14582
  const { useEventBus: useEventBus3 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
14583
14583
  function MapUpdater({ centerLat, centerLng, zoom }) {
14584
14584
  const map = useMap();
14585
- const prevRef = useRef88({ centerLat, centerLng, zoom });
14586
- useEffect89(() => {
14585
+ const prevRef = useRef89({ centerLat, centerLng, zoom });
14586
+ useEffect90(() => {
14587
14587
  const prev = prevRef.current;
14588
14588
  if (prev.centerLat !== centerLat || prev.centerLng !== centerLng || prev.zoom !== zoom) {
14589
14589
  map.setView([centerLat, centerLng], zoom);
@@ -14594,7 +14594,7 @@ var init_MapView = __esm({
14594
14594
  }
14595
14595
  function MapClickHandler({ onMapClick }) {
14596
14596
  const map = useMap();
14597
- useEffect89(() => {
14597
+ useEffect90(() => {
14598
14598
  if (!onMapClick) return;
14599
14599
  const handler = (e) => {
14600
14600
  onMapClick(e.latlng.lat, e.latlng.lng);
@@ -26109,6 +26109,21 @@ var init_DashboardLayout = __esm({
26109
26109
  };
26110
26110
  const [sidebarOpen, setSidebarOpen] = useState(false);
26111
26111
  const [userMenuOpen, setUserMenuOpen] = useState(false);
26112
+ const layoutRef = useRef(null);
26113
+ const [isMobile, setIsMobile] = useState(false);
26114
+ useEffect(() => {
26115
+ const el = layoutRef.current;
26116
+ if (!el || typeof ResizeObserver === "undefined") return;
26117
+ const ro = new ResizeObserver((entries) => {
26118
+ const w = entries[0]?.contentRect.width ?? el.clientWidth;
26119
+ setIsMobile(w < 1024);
26120
+ });
26121
+ ro.observe(el);
26122
+ return () => ro.disconnect();
26123
+ }, []);
26124
+ useEffect(() => {
26125
+ if (!isMobile && sidebarOpen) setSidebarOpen(false);
26126
+ }, [isMobile, sidebarOpen]);
26112
26127
  const location = useLocation();
26113
26128
  const ctxPagePath = useCurrentPagePath();
26114
26129
  const activePath = currentPath ?? ctxPagePath ?? location.pathname;
@@ -26121,15 +26136,15 @@ var init_DashboardLayout = __esm({
26121
26136
  const showBottomNav = layoutMode === "bottomnav";
26122
26137
  const isTopNav = layoutMode === "topnav";
26123
26138
  return /* @__PURE__ */ jsxs(
26124
- HStack,
26139
+ Box,
26125
26140
  {
26126
- gap: "none",
26127
- className: "@container/dashboard min-h-screen w-full bg-background dark:bg-background items-stretch",
26141
+ ref: layoutRef,
26142
+ className: "@container/dashboard min-h-screen w-full bg-background dark:bg-background flex flex-row items-stretch",
26128
26143
  children: [
26129
- showSidebar && sidebarOpen && /* @__PURE__ */ jsx(
26144
+ showSidebar && isMobile && sidebarOpen && /* @__PURE__ */ jsx(
26130
26145
  Box,
26131
26146
  {
26132
- className: "fixed inset-0 bg-foreground/50 dark:bg-foreground/70 z-20 @lg/dashboard:hidden",
26147
+ className: "fixed inset-0 bg-foreground/50 dark:bg-foreground/70 z-20",
26133
26148
  onClick: () => setSidebarOpen(false)
26134
26149
  }
26135
26150
  ),
@@ -26139,11 +26154,16 @@ var init_DashboardLayout = __esm({
26139
26154
  as: "aside",
26140
26155
  className: cn(
26141
26156
  "z-30 w-64 flex-shrink-0 bg-card dark:bg-card border-r border-border dark:border-border",
26142
- "fixed inset-y-0 left-0 @lg/dashboard:static @lg/dashboard:translate-x-0 @lg/dashboard:h-auto",
26143
- "transform transition-transform duration-200 ease-in-out",
26144
- "flex flex-col",
26145
- sidebarOpen ? "translate-x-0" : "-translate-x-full"
26157
+ "flex flex-col"
26146
26158
  ),
26159
+ style: isMobile ? {
26160
+ position: "fixed",
26161
+ top: 0,
26162
+ bottom: 0,
26163
+ left: 0,
26164
+ transform: sidebarOpen ? "translateX(0)" : "translateX(-100%)",
26165
+ transition: "transform 200ms ease-in-out"
26166
+ } : { position: "static", transform: "none" },
26147
26167
  children: [
26148
26168
  /* @__PURE__ */ jsxs(
26149
26169
  HStack,
@@ -26172,11 +26192,11 @@ var init_DashboardLayout = __esm({
26172
26192
  }
26173
26193
  )
26174
26194
  ] }),
26175
- /* @__PURE__ */ jsx(
26195
+ isMobile && /* @__PURE__ */ jsx(
26176
26196
  Button,
26177
26197
  {
26178
26198
  variant: "ghost",
26179
- className: "@lg/dashboard:hidden p-2 rounded-md hover:bg-muted dark:hover:bg-muted text-muted-foreground dark:text-muted-foreground",
26199
+ className: "p-2 rounded-md hover:bg-muted dark:hover:bg-muted text-muted-foreground dark:text-muted-foreground",
26180
26200
  onClick: () => setSidebarOpen(false),
26181
26201
  children: /* @__PURE__ */ jsx(Icon, { name: "x", className: "h-5 w-5" })
26182
26202
  }
@@ -26217,11 +26237,11 @@ var init_DashboardLayout = __esm({
26217
26237
  justify: "between",
26218
26238
  className: "h-full px-3 @sm/dashboard:px-4 gap-2 @sm/dashboard:gap-4",
26219
26239
  children: [
26220
- showSidebar && /* @__PURE__ */ jsx(
26240
+ showSidebar && isMobile && /* @__PURE__ */ jsx(
26221
26241
  Button,
26222
26242
  {
26223
26243
  variant: "ghost",
26224
- className: "@lg/dashboard:hidden p-2 rounded-md hover:bg-muted dark:hover:bg-muted text-muted-foreground dark:text-muted-foreground touch-manipulation min-h-[44px] min-w-[44px] flex items-center justify-center",
26244
+ className: "p-2 rounded-md hover:bg-muted dark:hover:bg-muted text-muted-foreground dark:text-muted-foreground touch-manipulation min-h-[44px] min-w-[44px] flex items-center justify-center",
26225
26245
  onClick: () => setSidebarOpen(true),
26226
26246
  "aria-label": "Open sidebar",
26227
26247
  children: /* @__PURE__ */ jsx(Icon, { name: "menu", className: "h-5 w-5" })
@@ -62604,15 +62624,9 @@ function buildTransitionSchema(fullSchema, orbitalName, traitName, transitionEve
62604
62624
  return { ...fullSchema, name: `${fullSchema.name}__${orbitalName}__${traitName}__${transitionEvent}`, orbitals: [clonedOrbital] };
62605
62625
  }
62606
62626
  var SELECTION_STYLES = `
62607
- .orb-preview-live [data-pattern]:hover {
62608
- outline: 2px dashed var(--color-primary);
62609
- outline-offset: 1px;
62627
+ .orb-preview-live [data-pattern] {
62610
62628
  cursor: pointer;
62611
62629
  }
62612
- .orb-preview-live [data-pattern].pattern-selected {
62613
- outline: 2px solid var(--color-primary);
62614
- outline-offset: 1px;
62615
- }
62616
62630
  .orb-preview-live.drag-active [data-accepts-children="true"] {
62617
62631
  outline: 2px dashed var(--color-primary);
62618
62632
  outline-offset: -2px;
@@ -62629,15 +62643,66 @@ var SELECTION_STYLES = `
62629
62643
  pointer-events: none;
62630
62644
  }
62631
62645
  `;
62646
+ function absUnion(el) {
62647
+ const own = el.getBoundingClientRect();
62648
+ if (own.width > 0 || own.height > 0) {
62649
+ return { top: own.top, left: own.left, right: own.right, bottom: own.bottom };
62650
+ }
62651
+ let r2 = null;
62652
+ for (const child of Array.from(el.children)) {
62653
+ const box = absUnion(child);
62654
+ if (!box) continue;
62655
+ r2 = r2 ? {
62656
+ top: Math.min(r2.top, box.top),
62657
+ left: Math.min(r2.left, box.left),
62658
+ right: Math.max(r2.right, box.right),
62659
+ bottom: Math.max(r2.bottom, box.bottom)
62660
+ } : box;
62661
+ }
62662
+ return r2;
62663
+ }
62664
+ function rectRelativeTo(el, container) {
62665
+ const u = absUnion(el);
62666
+ if (!u) return null;
62667
+ const base = container.getBoundingClientRect();
62668
+ return { top: u.top - base.top, left: u.left - base.left, width: u.right - u.left, height: u.bottom - u.top };
62669
+ }
62670
+ function buildFocus(el, orbitalName) {
62671
+ if (!orbitalName) return null;
62672
+ const path = el.getAttribute("data-orb-path") ?? el.getAttribute("data-pattern-path");
62673
+ const patternType = el.getAttribute("data-orb-pattern") ?? el.getAttribute("data-pattern");
62674
+ const trait = el.getAttribute("data-orb-trait") ?? el.getAttribute("data-source-trait");
62675
+ const focus = {
62676
+ level: "node",
62677
+ orbital: orbitalName,
62678
+ label: patternType ?? trait ?? "element"
62679
+ };
62680
+ if (path !== null) focus.path = path;
62681
+ if (trait !== null) focus.trait = trait;
62682
+ if (patternType !== null) focus.patternType = patternType;
62683
+ const transition = el.getAttribute("data-orb-transition");
62684
+ if (transition !== null) focus.transition = transition;
62685
+ const state = el.getAttribute("data-orb-state");
62686
+ if (state !== null) focus.state = state;
62687
+ const slot = el.getAttribute("data-orb-slot");
62688
+ if (slot !== null) focus.slot = slot;
62689
+ const entity = el.getAttribute("data-orb-entity");
62690
+ if (entity !== null) focus.entity = entity;
62691
+ return focus;
62692
+ }
62632
62693
  var OrbPreviewNodeInner = (props) => {
62633
62694
  const data = props.data;
62634
62695
  const screenSize = useContext(ScreenSizeContext);
62635
62696
  const preset = SCREEN_SIZE_PRESETS[screenSize];
62636
62697
  const { select } = useContext(PatternSelectionContext);
62698
+ const eventBus = useEventBus();
62637
62699
  const contentRef = useRef(null);
62638
62700
  const [hovered, setHovered] = useState(false);
62639
62701
  const handleMouseEnter = useCallback(() => setHovered(true), []);
62640
62702
  const handleMouseLeave = useCallback(() => setHovered(false), []);
62703
+ const [selectedRect, setSelectedRect] = useState(null);
62704
+ const [hoverRect, setHoverRect] = useState(null);
62705
+ const lastHoverElRef = useRef(null);
62641
62706
  const role = data.stateRole ?? "default";
62642
62707
  const colors = ROLE_COLORS[role] ?? ROLE_COLORS.default;
62643
62708
  const eventSources = data.eventSources ?? [];
@@ -62670,13 +62735,14 @@ var OrbPreviewNodeInner = (props) => {
62670
62735
  e.stopPropagation();
62671
62736
  const target = e.target;
62672
62737
  const patternEl = target.closest("[data-pattern]");
62673
- contentRef.current?.querySelectorAll(".pattern-selected").forEach((el) => {
62738
+ const container = contentRef.current;
62739
+ container?.querySelectorAll(".pattern-selected").forEach((el) => {
62674
62740
  el.classList.remove("pattern-selected");
62675
62741
  });
62676
- if (patternEl) {
62742
+ if (patternEl && container) {
62677
62743
  patternEl.classList.add("pattern-selected");
62678
- const nodeRect = contentRef.current?.getBoundingClientRect();
62679
- const elRect = patternEl.getBoundingClientRect();
62744
+ const rect = rectRelativeTo(patternEl, container);
62745
+ setSelectedRect(rect);
62680
62746
  select({
62681
62747
  patternType: patternEl.getAttribute("data-pattern") ?? "unknown",
62682
62748
  // `data-pattern-path` is the SExpr tree path (`children.0.…`) emitted by
@@ -62687,18 +62753,33 @@ var OrbPreviewNodeInner = (props) => {
62687
62753
  patternId: patternEl.getAttribute("data-pattern-path") ?? void 0,
62688
62754
  sourceTrait: patternEl.getAttribute("data-source-trait") ?? void 0,
62689
62755
  nodeData: data,
62690
- rect: nodeRect ? {
62691
- top: elRect.top - nodeRect.top,
62692
- left: elRect.left - nodeRect.left,
62693
- width: elRect.width,
62694
- height: elRect.height
62695
- } : void 0
62756
+ rect: rect ?? void 0
62696
62757
  });
62758
+ const focus = buildFocus(patternEl, data.orbitalName);
62759
+ if (focus) eventBus.emit("UI:ELEMENT_SELECTED", { focus: { ...focus } });
62697
62760
  } else {
62761
+ setSelectedRect(null);
62698
62762
  select(null);
62699
- }
62700
- }, [data, select]);
62701
- const eventBus = useEventBus();
62763
+ eventBus.emit("UI:ELEMENT_SELECTED", { focus: null });
62764
+ }
62765
+ }, [data, select, eventBus]);
62766
+ const handleContentMouseMove = useCallback((e) => {
62767
+ const container = contentRef.current;
62768
+ if (!container) return;
62769
+ const el = e.target.closest("[data-pattern]");
62770
+ if (el === lastHoverElRef.current) return;
62771
+ lastHoverElRef.current = el;
62772
+ setHoverRect(el ? rectRelativeTo(el, container) : null);
62773
+ }, []);
62774
+ const handleContentMouseLeave = useCallback(() => {
62775
+ lastHoverElRef.current = null;
62776
+ setHoverRect(null);
62777
+ }, []);
62778
+ useEffect(() => {
62779
+ setSelectedRect(null);
62780
+ setHoverRect(null);
62781
+ lastHoverElRef.current = null;
62782
+ }, [orbitalSchema]);
62702
62783
  const [dragActive, setDragActive] = useState(false);
62703
62784
  useEffect(() => {
62704
62785
  const unsub1 = eventBus.on("UI:DRAG_START", (e) => {
@@ -62917,26 +62998,66 @@ var OrbPreviewNodeInner = (props) => {
62917
62998
  src.event
62918
62999
  )) })
62919
63000
  ] }),
62920
- /* @__PURE__ */ jsx(
63001
+ /* @__PURE__ */ jsxs(
62921
63002
  Box,
62922
63003
  {
62923
63004
  ref: setContentRef,
62924
- className: `orb-preview-live nodrag${dragActive || l2IsOver ? " drag-active" : ""}`,
63005
+ className: `orb-preview-live nodrag relative${dragActive || l2IsOver ? " drag-active" : ""}`,
62925
63006
  onClick: handleContentClick,
62926
- children: orbitalSchema ? (
62927
- // L1 and L2 both auto-grow with content. L2's `buildTransitionSchema`
62928
- // rewrites portal slots (modal/drawer/overlay/center) to `main`, so
62929
- // the rendered pattern lands inline in the main slot and contributes
62930
- // to the card's height — same height model as L1 orbital cards.
62931
- /* @__PURE__ */ jsx(Box, { style: { minHeight: preset.minHeight }, children: /* @__PURE__ */ jsx(
62932
- BrowserPlayground,
63007
+ onMouseMove: handleContentMouseMove,
63008
+ onMouseLeave: handleContentMouseLeave,
63009
+ children: [
63010
+ hoverRect && /* @__PURE__ */ jsx(
63011
+ "div",
62933
63012
  {
62934
- schema: orbitalSchema,
62935
- mode: "mock",
62936
- height: "auto"
63013
+ "aria-hidden": true,
63014
+ style: {
63015
+ position: "absolute",
63016
+ pointerEvents: "none",
63017
+ top: hoverRect.top,
63018
+ left: hoverRect.left,
63019
+ width: hoverRect.width,
63020
+ height: hoverRect.height,
63021
+ outline: "2px dashed var(--color-primary)",
63022
+ outlineOffset: "1px",
63023
+ borderRadius: "2px",
63024
+ zIndex: 20
63025
+ }
62937
63026
  }
62938
- ) })
62939
- ) : /* @__PURE__ */ jsx(Box, { className: "flex items-center justify-center", style: { minHeight: preset.minHeight }, children: /* @__PURE__ */ jsx(Typography, { variant: "small", className: "text-muted-foreground", children: "No preview available" }) })
63027
+ ),
63028
+ selectedRect && /* @__PURE__ */ jsx(
63029
+ "div",
63030
+ {
63031
+ "aria-hidden": true,
63032
+ style: {
63033
+ position: "absolute",
63034
+ pointerEvents: "none",
63035
+ top: selectedRect.top,
63036
+ left: selectedRect.left,
63037
+ width: selectedRect.width,
63038
+ height: selectedRect.height,
63039
+ outline: "2px solid var(--color-primary)",
63040
+ outlineOffset: "1px",
63041
+ borderRadius: "2px",
63042
+ zIndex: 21
63043
+ }
63044
+ }
63045
+ ),
63046
+ orbitalSchema ? (
63047
+ // L1 and L2 both auto-grow with content. L2's `buildTransitionSchema`
63048
+ // rewrites portal slots (modal/drawer/overlay/center) to `main`, so
63049
+ // the rendered pattern lands inline in the main slot and contributes
63050
+ // to the card's height — same height model as L1 orbital cards.
63051
+ /* @__PURE__ */ jsx(Box, { style: { minHeight: preset.minHeight }, children: /* @__PURE__ */ jsx(
63052
+ BrowserPlayground,
63053
+ {
63054
+ schema: orbitalSchema,
63055
+ mode: "mock",
63056
+ height: "auto"
63057
+ }
63058
+ ) })
63059
+ ) : /* @__PURE__ */ jsx(Box, { className: "flex items-center justify-center", style: { minHeight: preset.minHeight }, children: /* @__PURE__ */ jsx(Typography, { variant: "small", className: "text-muted-foreground", children: "No preview available" }) })
63060
+ ]
62940
63061
  }
62941
63062
  ),
62942
63063
  /* @__PURE__ */ jsx(Handle, { type: "target", position: Position.Left, style: TARGET_HANDLE_STYLE }),
@@ -8679,13 +8679,13 @@ var init_MapView = __esm({
8679
8679
  shadowSize: [41, 41]
8680
8680
  });
8681
8681
  L.Marker.prototype.options.icon = defaultIcon;
8682
- const { useEffect: useEffect73, useRef: useRef67, useCallback: useCallback129, useState: useState112 } = React80__namespace.default;
8682
+ const { useEffect: useEffect74, useRef: useRef68, useCallback: useCallback129, useState: useState112 } = React80__namespace.default;
8683
8683
  const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
8684
8684
  const { useEventBus: useEventBus2 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
8685
8685
  function MapUpdater({ centerLat, centerLng, zoom }) {
8686
8686
  const map = useMap();
8687
- const prevRef = useRef67({ centerLat, centerLng, zoom });
8688
- useEffect73(() => {
8687
+ const prevRef = useRef68({ centerLat, centerLng, zoom });
8688
+ useEffect74(() => {
8689
8689
  const prev = prevRef.current;
8690
8690
  if (prev.centerLat !== centerLat || prev.centerLng !== centerLng || prev.zoom !== zoom) {
8691
8691
  map.setView([centerLat, centerLng], zoom);
@@ -8696,7 +8696,7 @@ var init_MapView = __esm({
8696
8696
  }
8697
8697
  function MapClickHandler({ onMapClick }) {
8698
8698
  const map = useMap();
8699
- useEffect73(() => {
8699
+ useEffect74(() => {
8700
8700
  if (!onMapClick) return;
8701
8701
  const handler = (e) => {
8702
8702
  onMapClick(e.latlng.lat, e.latlng.lng);
@@ -21317,6 +21317,21 @@ var init_DashboardLayout = __esm({
21317
21317
  };
21318
21318
  const [sidebarOpen, setSidebarOpen] = React80.useState(false);
21319
21319
  const [userMenuOpen, setUserMenuOpen] = React80.useState(false);
21320
+ const layoutRef = React80.useRef(null);
21321
+ const [isMobile, setIsMobile] = React80.useState(false);
21322
+ React80.useEffect(() => {
21323
+ const el = layoutRef.current;
21324
+ if (!el || typeof ResizeObserver === "undefined") return;
21325
+ const ro = new ResizeObserver((entries) => {
21326
+ const w = entries[0]?.contentRect.width ?? el.clientWidth;
21327
+ setIsMobile(w < 1024);
21328
+ });
21329
+ ro.observe(el);
21330
+ return () => ro.disconnect();
21331
+ }, []);
21332
+ React80.useEffect(() => {
21333
+ if (!isMobile && sidebarOpen) setSidebarOpen(false);
21334
+ }, [isMobile, sidebarOpen]);
21320
21335
  const location = reactRouterDom.useLocation();
21321
21336
  const ctxPagePath = useCurrentPagePath();
21322
21337
  const activePath = currentPath ?? ctxPagePath ?? location.pathname;
@@ -21333,15 +21348,15 @@ var init_DashboardLayout = __esm({
21333
21348
  const showBottomNav = layoutMode === "bottomnav";
21334
21349
  const isTopNav = layoutMode === "topnav";
21335
21350
  return /* @__PURE__ */ jsxRuntime.jsxs(
21336
- exports.HStack,
21351
+ exports.Box,
21337
21352
  {
21338
- gap: "none",
21339
- className: "@container/dashboard min-h-screen w-full bg-background dark:bg-background items-stretch",
21353
+ ref: layoutRef,
21354
+ className: "@container/dashboard min-h-screen w-full bg-background dark:bg-background flex flex-row items-stretch",
21340
21355
  children: [
21341
- showSidebar && sidebarOpen && /* @__PURE__ */ jsxRuntime.jsx(
21356
+ showSidebar && isMobile && sidebarOpen && /* @__PURE__ */ jsxRuntime.jsx(
21342
21357
  exports.Box,
21343
21358
  {
21344
- className: "fixed inset-0 bg-foreground/50 dark:bg-foreground/70 z-20 @lg/dashboard:hidden",
21359
+ className: "fixed inset-0 bg-foreground/50 dark:bg-foreground/70 z-20",
21345
21360
  onClick: () => setSidebarOpen(false)
21346
21361
  }
21347
21362
  ),
@@ -21351,11 +21366,16 @@ var init_DashboardLayout = __esm({
21351
21366
  as: "aside",
21352
21367
  className: cn(
21353
21368
  "z-30 w-64 flex-shrink-0 bg-card dark:bg-card border-r border-border dark:border-border",
21354
- "fixed inset-y-0 left-0 @lg/dashboard:static @lg/dashboard:translate-x-0 @lg/dashboard:h-auto",
21355
- "transform transition-transform duration-200 ease-in-out",
21356
- "flex flex-col",
21357
- sidebarOpen ? "translate-x-0" : "-translate-x-full"
21369
+ "flex flex-col"
21358
21370
  ),
21371
+ style: isMobile ? {
21372
+ position: "fixed",
21373
+ top: 0,
21374
+ bottom: 0,
21375
+ left: 0,
21376
+ transform: sidebarOpen ? "translateX(0)" : "translateX(-100%)",
21377
+ transition: "transform 200ms ease-in-out"
21378
+ } : { position: "static", transform: "none" },
21359
21379
  children: [
21360
21380
  /* @__PURE__ */ jsxRuntime.jsxs(
21361
21381
  exports.HStack,
@@ -21384,11 +21404,11 @@ var init_DashboardLayout = __esm({
21384
21404
  }
21385
21405
  )
21386
21406
  ] }),
21387
- /* @__PURE__ */ jsxRuntime.jsx(
21407
+ isMobile && /* @__PURE__ */ jsxRuntime.jsx(
21388
21408
  exports.Button,
21389
21409
  {
21390
21410
  variant: "ghost",
21391
- className: "@lg/dashboard:hidden p-2 rounded-md hover:bg-muted dark:hover:bg-muted text-muted-foreground dark:text-muted-foreground",
21411
+ className: "p-2 rounded-md hover:bg-muted dark:hover:bg-muted text-muted-foreground dark:text-muted-foreground",
21392
21412
  onClick: () => setSidebarOpen(false),
21393
21413
  children: /* @__PURE__ */ jsxRuntime.jsx(exports.Icon, { name: "x", className: "h-5 w-5" })
21394
21414
  }
@@ -21429,11 +21449,11 @@ var init_DashboardLayout = __esm({
21429
21449
  justify: "between",
21430
21450
  className: "h-full px-3 @sm/dashboard:px-4 gap-2 @sm/dashboard:gap-4",
21431
21451
  children: [
21432
- showSidebar && /* @__PURE__ */ jsxRuntime.jsx(
21452
+ showSidebar && isMobile && /* @__PURE__ */ jsxRuntime.jsx(
21433
21453
  exports.Button,
21434
21454
  {
21435
21455
  variant: "ghost",
21436
- className: "@lg/dashboard:hidden p-2 rounded-md hover:bg-muted dark:hover:bg-muted text-muted-foreground dark:text-muted-foreground touch-manipulation min-h-[44px] min-w-[44px] flex items-center justify-center",
21456
+ className: "p-2 rounded-md hover:bg-muted dark:hover:bg-muted text-muted-foreground dark:text-muted-foreground touch-manipulation min-h-[44px] min-w-[44px] flex items-center justify-center",
21437
21457
  onClick: () => setSidebarOpen(true),
21438
21458
  "aria-label": "Open sidebar",
21439
21459
  children: /* @__PURE__ */ jsxRuntime.jsx(exports.Icon, { name: "menu", className: "h-5 w-5" })
@@ -8630,13 +8630,13 @@ var init_MapView = __esm({
8630
8630
  shadowSize: [41, 41]
8631
8631
  });
8632
8632
  L.Marker.prototype.options.icon = defaultIcon;
8633
- const { useEffect: useEffect73, useRef: useRef67, useCallback: useCallback129, useState: useState112 } = React80__default;
8633
+ const { useEffect: useEffect74, useRef: useRef68, useCallback: useCallback129, useState: useState112 } = React80__default;
8634
8634
  const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
8635
8635
  const { useEventBus: useEventBus2 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
8636
8636
  function MapUpdater({ centerLat, centerLng, zoom }) {
8637
8637
  const map = useMap();
8638
- const prevRef = useRef67({ centerLat, centerLng, zoom });
8639
- useEffect73(() => {
8638
+ const prevRef = useRef68({ centerLat, centerLng, zoom });
8639
+ useEffect74(() => {
8640
8640
  const prev = prevRef.current;
8641
8641
  if (prev.centerLat !== centerLat || prev.centerLng !== centerLng || prev.zoom !== zoom) {
8642
8642
  map.setView([centerLat, centerLng], zoom);
@@ -8647,7 +8647,7 @@ var init_MapView = __esm({
8647
8647
  }
8648
8648
  function MapClickHandler({ onMapClick }) {
8649
8649
  const map = useMap();
8650
- useEffect73(() => {
8650
+ useEffect74(() => {
8651
8651
  if (!onMapClick) return;
8652
8652
  const handler = (e) => {
8653
8653
  onMapClick(e.latlng.lat, e.latlng.lng);
@@ -21268,6 +21268,21 @@ var init_DashboardLayout = __esm({
21268
21268
  };
21269
21269
  const [sidebarOpen, setSidebarOpen] = useState(false);
21270
21270
  const [userMenuOpen, setUserMenuOpen] = useState(false);
21271
+ const layoutRef = useRef(null);
21272
+ const [isMobile, setIsMobile] = useState(false);
21273
+ useEffect(() => {
21274
+ const el = layoutRef.current;
21275
+ if (!el || typeof ResizeObserver === "undefined") return;
21276
+ const ro = new ResizeObserver((entries) => {
21277
+ const w = entries[0]?.contentRect.width ?? el.clientWidth;
21278
+ setIsMobile(w < 1024);
21279
+ });
21280
+ ro.observe(el);
21281
+ return () => ro.disconnect();
21282
+ }, []);
21283
+ useEffect(() => {
21284
+ if (!isMobile && sidebarOpen) setSidebarOpen(false);
21285
+ }, [isMobile, sidebarOpen]);
21271
21286
  const location = useLocation();
21272
21287
  const ctxPagePath = useCurrentPagePath();
21273
21288
  const activePath = currentPath ?? ctxPagePath ?? location.pathname;
@@ -21284,15 +21299,15 @@ var init_DashboardLayout = __esm({
21284
21299
  const showBottomNav = layoutMode === "bottomnav";
21285
21300
  const isTopNav = layoutMode === "topnav";
21286
21301
  return /* @__PURE__ */ jsxs(
21287
- HStack,
21302
+ Box,
21288
21303
  {
21289
- gap: "none",
21290
- className: "@container/dashboard min-h-screen w-full bg-background dark:bg-background items-stretch",
21304
+ ref: layoutRef,
21305
+ className: "@container/dashboard min-h-screen w-full bg-background dark:bg-background flex flex-row items-stretch",
21291
21306
  children: [
21292
- showSidebar && sidebarOpen && /* @__PURE__ */ jsx(
21307
+ showSidebar && isMobile && sidebarOpen && /* @__PURE__ */ jsx(
21293
21308
  Box,
21294
21309
  {
21295
- className: "fixed inset-0 bg-foreground/50 dark:bg-foreground/70 z-20 @lg/dashboard:hidden",
21310
+ className: "fixed inset-0 bg-foreground/50 dark:bg-foreground/70 z-20",
21296
21311
  onClick: () => setSidebarOpen(false)
21297
21312
  }
21298
21313
  ),
@@ -21302,11 +21317,16 @@ var init_DashboardLayout = __esm({
21302
21317
  as: "aside",
21303
21318
  className: cn(
21304
21319
  "z-30 w-64 flex-shrink-0 bg-card dark:bg-card border-r border-border dark:border-border",
21305
- "fixed inset-y-0 left-0 @lg/dashboard:static @lg/dashboard:translate-x-0 @lg/dashboard:h-auto",
21306
- "transform transition-transform duration-200 ease-in-out",
21307
- "flex flex-col",
21308
- sidebarOpen ? "translate-x-0" : "-translate-x-full"
21320
+ "flex flex-col"
21309
21321
  ),
21322
+ style: isMobile ? {
21323
+ position: "fixed",
21324
+ top: 0,
21325
+ bottom: 0,
21326
+ left: 0,
21327
+ transform: sidebarOpen ? "translateX(0)" : "translateX(-100%)",
21328
+ transition: "transform 200ms ease-in-out"
21329
+ } : { position: "static", transform: "none" },
21310
21330
  children: [
21311
21331
  /* @__PURE__ */ jsxs(
21312
21332
  HStack,
@@ -21335,11 +21355,11 @@ var init_DashboardLayout = __esm({
21335
21355
  }
21336
21356
  )
21337
21357
  ] }),
21338
- /* @__PURE__ */ jsx(
21358
+ isMobile && /* @__PURE__ */ jsx(
21339
21359
  Button,
21340
21360
  {
21341
21361
  variant: "ghost",
21342
- className: "@lg/dashboard:hidden p-2 rounded-md hover:bg-muted dark:hover:bg-muted text-muted-foreground dark:text-muted-foreground",
21362
+ className: "p-2 rounded-md hover:bg-muted dark:hover:bg-muted text-muted-foreground dark:text-muted-foreground",
21343
21363
  onClick: () => setSidebarOpen(false),
21344
21364
  children: /* @__PURE__ */ jsx(Icon, { name: "x", className: "h-5 w-5" })
21345
21365
  }
@@ -21380,11 +21400,11 @@ var init_DashboardLayout = __esm({
21380
21400
  justify: "between",
21381
21401
  className: "h-full px-3 @sm/dashboard:px-4 gap-2 @sm/dashboard:gap-4",
21382
21402
  children: [
21383
- showSidebar && /* @__PURE__ */ jsx(
21403
+ showSidebar && isMobile && /* @__PURE__ */ jsx(
21384
21404
  Button,
21385
21405
  {
21386
21406
  variant: "ghost",
21387
- className: "@lg/dashboard:hidden p-2 rounded-md hover:bg-muted dark:hover:bg-muted text-muted-foreground dark:text-muted-foreground touch-manipulation min-h-[44px] min-w-[44px] flex items-center justify-center",
21407
+ className: "p-2 rounded-md hover:bg-muted dark:hover:bg-muted text-muted-foreground dark:text-muted-foreground touch-manipulation min-h-[44px] min-w-[44px] flex items-center justify-center",
21388
21408
  onClick: () => setSidebarOpen(true),
21389
21409
  "aria-label": "Open sidebar",
21390
21410
  children: /* @__PURE__ */ jsx(Icon, { name: "menu", className: "h-5 w-5" })