@almadar/ui 6.61.0 → 6.62.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 (41) hide show
  1. package/dist/{BehaviorValueFrame-QTD7BWOI.js → BehaviorValueFrame-QYFJEMN5.js} +12 -12
  2. package/dist/{TraitValueFrame-WOXNLLMM.js → TraitValueFrame-X6IL3UST.js} +11 -11
  3. package/dist/Typography-KBATMU2V.js +5 -0
  4. package/dist/{UISlotRenderer-EEOXSJCI.js → UISlotRenderer-NZBV5BUI.js} +10 -10
  5. package/dist/avl/index.cjs +303 -261
  6. package/dist/avl/index.js +13 -13
  7. package/dist/{chunk-CB64IOYD.js → chunk-7JRWELUC.js} +4 -2
  8. package/dist/{chunk-6ZCU3BQN.js → chunk-CXQENFO2.js} +1 -1
  9. package/dist/{chunk-LUREMDI3.js → chunk-D4NAA2JW.js} +2 -2
  10. package/dist/{chunk-UTSDPJUP.js → chunk-DXPCAQJU.js} +3 -3
  11. package/dist/{chunk-MGN6B6OQ.js → chunk-EDPUQ2ZJ.js} +9 -0
  12. package/dist/{chunk-KZRAMPM6.js → chunk-ERDYADVZ.js} +1 -1
  13. package/dist/{chunk-7NIU5GDC.js → chunk-EZ5FSNOE.js} +2 -2
  14. package/dist/{chunk-6PV4LASE.js → chunk-G6EFTACU.js} +281 -206
  15. package/dist/{chunk-EIIQGOZW.js → chunk-GVQOTA7T.js} +1 -1
  16. package/dist/{chunk-FYX64CDL.js → chunk-QOV3TUAA.js} +2 -1
  17. package/dist/{chunk-F7NZ3KZQ.js → chunk-WBWXBA5H.js} +1 -1
  18. package/dist/components/index.cjs +414 -312
  19. package/dist/components/index.d.ts +40 -8
  20. package/dist/components/index.js +14 -14
  21. package/dist/hooks/index.cjs +6 -3
  22. package/dist/hooks/index.js +5 -5
  23. package/dist/lib/drawable/three/index.cjs +11 -1
  24. package/dist/lib/drawable/three/index.js +6 -6
  25. package/dist/lib/index.cjs +27 -1
  26. package/dist/lib/index.js +27 -2
  27. package/dist/locales/index.cjs +6 -3
  28. package/dist/locales/index.js +2 -2
  29. package/dist/providers/index.cjs +302 -260
  30. package/dist/providers/index.js +10 -10
  31. package/dist/runtime/index.cjs +302 -260
  32. package/dist/runtime/index.d.ts +6 -1
  33. package/dist/runtime/index.js +12 -12
  34. package/dist/ssr/index.cjs +2 -1
  35. package/dist/ssr/index.js +2 -1
  36. package/locales/ar.json +2 -1
  37. package/locales/en.json +2 -1
  38. package/locales/sl.json +2 -1
  39. package/package.json +6 -6
  40. package/themes/_base.css +27 -0
  41. package/dist/Typography-BY4A2NBY.js +0 -5
@@ -1,14 +1,14 @@
1
- import { pressableProps, Box, HStack, useCanvasTheme, STATE_COLORS, avlSeries, isAtlasAsset, getAtlas, subRectFor, VStack, avlTint, CONNECTION_COLORS, parseTraitLevel, AVL_INK, AVL_FONT, AVL_STROKE, getStateRole, effectCategoryOf, EFFECT_CATEGORY_COLORS, OPERATOR_CATEGORY_COLORS, asEffectOperator, Stack, DrawSkinnedMesh, DrawShape, DrawMesh, DrawGroup, DrawFxLayer, withSeries, markColor, resolveDrawableColors, traitLevelFromTrait, resolveThemeColor, applyLineCharacter, fillLabel, labelText, THEME_SERIES, CONFETTI_BURST_KEYFRAMES, STRETCHED_CONTROL, rowOpenControlProps, STRETCHED_ABOVE, createConfettiParticles, collectDrawnItems, buildHitIndex, resolveAssetSource, blit, withPreviewPosition, hitTestSprites, DrawableRegistryContext, outlineStroke, markStrokeWidth, outlineCarriesFill, markDash, labelFont, fillMark, tracePolyline, arcPoints, drawMarker, getOrLoadImage, expandFxLayer, paintSkinnedMesh, isValidScenePos, isAnimatedGroup, applyMeshAnimation, paintShape, parseApplicationLevel, parseOrbitalLevel, traitTransitionRenderUi, spriteRect, effectZoneOf, motionTiming, layoutScale, spriteAssetState, getImageStatus, atlasUrlOf, atlasFailed, isSpriteSheetAtlas, fxHash01, traitEventWires, isAnimatedShape, SPRITE_FALLBACK_FILL, SPRITE_FALLBACK_STROKE, avlBlend } from './chunk-MGN6B6OQ.js';
2
- import { INLINE_TEXT_ATTR, Typography } from './chunk-KZRAMPM6.js';
3
- import { usePendingAction, useMediaQuery, usePrefersReducedMotion, useTranslate as useTranslate$1, usePageHead, usePendingScopeValue, PendingScopeContext, useRenderI18n, useScopeHasPending, runTickFrame, claimDelivery, beginPending, endPending, useDragReorder, useQuerySingleton, usePullToRefresh, useInfiniteScroll, useCanvasGestures, useAuthContext, useSwipeGesture, usePendingRows, useLongPress, useDraggable as useDraggable$1, useDropZone } from './chunk-UTSDPJUP.js';
1
+ import { pressableProps, Box, HStack, useCanvasTheme, avlSeries, isAtlasAsset, getAtlas, subRectFor, VStack, avlTint, CONNECTION_COLORS, parseTraitLevel, STATE_COLORS, AVL_INK, AVL_FONT, AVL_STROKE, getStateRole, effectCategoryOf, EFFECT_CATEGORY_COLORS, OPERATOR_CATEGORY_COLORS, asEffectOperator, Stack, DrawSkinnedMesh, DrawShape, DrawMesh, DrawGroup, DrawFxLayer, withSeries, markColor, resolveDrawableColors, traitLevelFromTrait, resolveThemeColor, applyLineCharacter, fillLabel, labelText, THEME_SERIES, CONFETTI_BURST_KEYFRAMES, STRETCHED_CONTROL, rowOpenControlProps, STRETCHED_ABOVE, createConfettiParticles, collectDrawnItems, buildHitIndex, resolveAssetSource, blit, withPreviewPosition, hitTestSprites, DrawableRegistryContext, outlineStroke, markStrokeWidth, outlineCarriesFill, markDash, labelFont, fillMark, tracePolyline, arcPoints, drawMarker, getOrLoadImage, expandFxLayer, paintSkinnedMesh, isValidScenePos, isAnimatedGroup, applyMeshAnimation, paintShape, parseApplicationLevel, parseOrbitalLevel, traitTransitionRenderUi, spriteRect, effectZoneOf, motionTiming, layoutScale, spriteAssetState, getImageStatus, atlasUrlOf, atlasFailed, isSpriteSheetAtlas, fxHash01, traitEventWires, isAnimatedShape, SPRITE_FALLBACK_FILL, SPRITE_FALLBACK_STROKE, avlBlend } from './chunk-EDPUQ2ZJ.js';
2
+ import { INLINE_TEXT_ATTR, Typography } from './chunk-ERDYADVZ.js';
3
+ import { usePendingAction, useMediaQuery, usePrefersReducedMotion, useTranslate as useTranslate$1, usePageHead, usePendingScopeValue, PendingScopeContext, useRenderI18n, useScopeHasPending, runTickFrame, claimDelivery, beginPending, endPending, useDragReorder, useQuerySingleton, usePullToRefresh, useInfiniteScroll, useCanvasGestures, useAuthContext, useSwipeGesture, usePendingRows, useLongPress, useDraggable as useDraggable$1, useDropZone } from './chunk-DXPCAQJU.js';
4
4
  import { useTapReveal } from './chunk-XJTHMW4G.js';
5
5
  import { useEventBus, useEventListener } from './chunk-CHNC4UYE.js';
6
+ import { ALL_SLOTS } from './chunk-L3MTZ3RH.js';
7
+ import { isNotificationSlot, isPortalSlot } from './chunk-PEST66PN.js';
6
8
  import { computeLineDiff, isEditorMotion, applyMotion, isEditorOperator, motionRange, applyOperator, gearTeethPath, registerTrait, unregisterTrait, asEnterAnimation, slotPlaysDefaultEnter, useSlotEnterRestart, ENTER_SLOT_CLASS, perfTimeAsync, enterClassName, getNestedValue, parseLessonSegments, isDebugEnabled2, onDebugToggle, debugGroup, debug, debugGroupEnd, resolveImageUrl, perfStart, perfEnd, isDebugEnabled, profilerOnRender, parseContentSegments, parseMarkdownWithCodeBlocks, subscribeToTraitChanges, subscribeToTickChanges, subscribeToGuardChanges, subscribeToDebugEvents, getEntitySnapshot, getDebugEvents, getGuardHistory, getAllTicks, getAllTraits } from './chunk-N4IJS5DD.js';
7
9
  import { isEditableTarget, usePresence, bindTraitStateGetter, registerTraitSnapshot, isMotionEnabled, recordTransition, recordingTransport, recordServerResponse, serverEffectTraces, Presence, bindCanvasCapture, bindLastDrawables, subscribeToVerification, updateAssetStatus, resolveKeyMapEvent, getSummary, getBridgeHealth, getTransitions, getAllChecks } from './chunk-N23SVGTH.js';
8
10
  import { cn, domPassthrough } from './chunk-64WACXM7.js';
9
- import { formatValue, toDateTimeInputValue, toDateInputValue, sortRows, formatDate } from './chunk-6ZCU3BQN.js';
10
- import { ALL_SLOTS } from './chunk-L3MTZ3RH.js';
11
- import { isNotificationSlot, isPortalSlot } from './chunk-PEST66PN.js';
11
+ import { formatValue, toDateTimeInputValue, toDateInputValue, sortRows, formatDate } from './chunk-CXQENFO2.js';
12
12
  import { __publicField } from './chunk-QPXIAUJD.js';
13
13
  import * as React93 from 'react';
14
14
  import React93__default, { createContext, useCallback, useState, useRef, useEffect, lazy, useMemo, useLayoutEffect, useId, useContext, useSyncExternalStore, Suspense, useReducer, Profiler } from 'react';
@@ -19,7 +19,7 @@ import { actionTestId, LOADING_STATE_MARKER, FieldTypeSchema, EFFECT_OPERATORS,
19
19
  import { renderUiEntriesOf, SELF_OVERLAY_PATTERN_TYPES, getPatternDefinition, isDrawHostPattern, getPatternFieldsContract, getComponentForPattern, isEntityAwarePattern, eventKeyPropsOf, eventListPropsOf } from '@almadar/core/patterns';
20
20
  import { useScopedMode, useThemeScope, UISlotProvider, useUISlots, useTheme } from '@almadar/ui/context';
21
21
  import * as LucideIcons2 from 'lucide-react';
22
- import { Loader2, X, Code, FileText, WrapText, Check, Copy, ChevronLeft, ChevronRight, AlertCircle, Circle, Clock, CheckCircle2, TrendingUp, TrendingDown, Minus, Eraser, Search, Bold, Italic, Underline, Strikethrough, Heading1, Heading2, Heading3, List, ListOrdered, Quote, Link, Image as Image$1, PauseCircle, HelpCircle, Upload, ZoomIn, Menu as Menu$1, ZoomOut, RotateCcw, DollarSign, Download, Printer, ArrowLeft, Link2, AlertTriangle, Trash2, Play, Terminal, CheckCircle, XCircle, GitBranch, Pencil, Eye, Plus, Lightbulb, ArrowRight, Trash, ChevronDown } from 'lucide-react';
22
+ import { Loader2, X, Code, FileText, WrapText, Check, Copy, ChevronLeft, ChevronRight, AlertCircle, Circle, Clock, CheckCircle2, TrendingUp, TrendingDown, Minus, Eraser, Search, Bold, Italic, Underline, Strikethrough, Heading1, Heading2, Heading3, List, ListOrdered, Quote, Link, Image as Image$1, PauseCircle, HelpCircle, Upload, ZoomIn, Menu as Menu$1, ZoomOut, RotateCcw, DollarSign, Download, Printer, ArrowLeft, Link2, AlertTriangle, Trash2, Play, Terminal, CheckCircle, XCircle, ChevronUp, ChevronDown, GitBranch, Pencil, Eye, Plus, Lightbulb, ArrowRight, Trash } from 'lucide-react';
23
23
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
24
24
  import { useTranslate, createTranslate, I18nProvider, useRenderI18n as useRenderI18n$1, useFormatContext } from '@almadar/ui/hooks';
25
25
  import { createPortal } from 'react-dom';
@@ -37,7 +37,7 @@ import createHighlightElement from 'react-syntax-highlighter/dist/esm/create-ele
37
37
  import dark from 'react-syntax-highlighter/dist/esm/styles/prism/vsc-dark-plus.js';
38
38
  import light from 'react-syntax-highlighter/dist/esm/styles/prism/vs.js';
39
39
  import { orbLanguage, loloLanguage, ORB_COLORS, translateLolo, translateOrb } from '@almadar/syntax';
40
- import { coreTables, localeDirection } from '@almadar/core/i18n';
40
+ import { getVocabulary, localeDirection } from '@almadar/core/i18n';
41
41
  import langJson from 'react-syntax-highlighter/dist/esm/languages/prism/json.js';
42
42
  import langJavascript from 'react-syntax-highlighter/dist/esm/languages/prism/javascript.js';
43
43
  import langTypescript from 'react-syntax-highlighter/dist/esm/languages/prism/typescript.js';
@@ -2317,6 +2317,17 @@ var SvgBranch = ({
2317
2317
  return /* @__PURE__ */ jsx(Fragment, { children: inner });
2318
2318
  };
2319
2319
  SvgBranch.displayName = "SvgBranch";
2320
+
2321
+ // lib/svgMotion.ts
2322
+ var SVG_MOTION_CLASSES = {
2323
+ flowDash: "almadar-svg-flow-dash",
2324
+ pulseRing: "almadar-svg-pulse-ring",
2325
+ pulseExpand: "almadar-svg-pulse-expand"
2326
+ };
2327
+ function svgMotionClass(motion, animated) {
2328
+ if (!animated || !isMotionEnabled()) return void 0;
2329
+ return SVG_MOTION_CLASSES[motion];
2330
+ }
2320
2331
  var SvgConnection = ({
2321
2332
  x1 = 10,
2322
2333
  y1 = 50,
@@ -2341,7 +2352,7 @@ var SvgConnection = ({
2341
2352
  {
2342
2353
  ...asRoot ? void 0 : a11y,
2343
2354
  className: [
2344
- variant === "animated" ? "almadar-svg-flow-dash" : void 0,
2355
+ svgMotionClass("flowDash", variant === "animated"),
2345
2356
  className
2346
2357
  ].filter(Boolean).join(" ") || void 0,
2347
2358
  x1,
@@ -2408,7 +2419,7 @@ var SvgFlow = ({
2408
2419
  strokeLinecap: "round",
2409
2420
  strokeLinejoin: "round",
2410
2421
  markerEnd: `url(#${markerId})`,
2411
- className: animated ? "almadar-svg-flow-dash" : void 0,
2422
+ className: svgMotionClass("flowDash", animated),
2412
2423
  strokeDasharray: animated ? "8 6" : void 0
2413
2424
  }
2414
2425
  )
@@ -2833,7 +2844,7 @@ var SvgNode = ({
2833
2844
  stroke: color,
2834
2845
  strokeWidth: 1,
2835
2846
  opacity: 0.3,
2836
- className: "almadar-svg-pulse-ring"
2847
+ className: svgMotionClass("pulseRing", true)
2837
2848
  }
2838
2849
  ),
2839
2850
  /* @__PURE__ */ jsx(
@@ -2866,18 +2877,6 @@ var SvgNode = ({
2866
2877
  return inner;
2867
2878
  };
2868
2879
  SvgNode.displayName = "SvgNode";
2869
- var PULSE_KEYFRAMES = `
2870
- @keyframes almadar-svg-pulse-expand {
2871
- 0% {
2872
- transform: scale(0.3);
2873
- opacity: 0.4;
2874
- }
2875
- 100% {
2876
- transform: scale(1);
2877
- opacity: 0;
2878
- }
2879
- }
2880
- `;
2881
2880
  var SvgPulse = ({
2882
2881
  cx = 70,
2883
2882
  cy = 70,
@@ -2893,8 +2892,8 @@ var SvgPulse = ({
2893
2892
  ...rest
2894
2893
  }) => {
2895
2894
  const a11y = domPassthrough(rest);
2895
+ const pulseClass2 = svgMotionClass("pulseExpand", animated);
2896
2896
  const inner = /* @__PURE__ */ jsxs("g", { ...asRoot ? void 0 : a11y, className, opacity, children: [
2897
- animated && /* @__PURE__ */ jsx("style", { children: PULSE_KEYFRAMES }),
2898
2897
  Array.from({ length: rings }).map((_, i) => {
2899
2898
  const ringRadius = (i + 1) / rings * maxRadius;
2900
2899
  const ringOpacity = 1 - i / rings * 0.6;
@@ -2908,11 +2907,9 @@ var SvgPulse = ({
2908
2907
  fill: "none",
2909
2908
  stroke: color,
2910
2909
  strokeWidth: 1.5,
2911
- opacity: animated ? void 0 : ringOpacity * 0.4,
2912
- style: animated ? {
2913
- transformOrigin: `${cx}px ${cy}px`,
2914
- animation: `almadar-svg-pulse-expand 2s ease-out ${delay}s infinite`
2915
- } : void 0
2910
+ opacity: pulseClass2 ? void 0 : ringOpacity * 0.4,
2911
+ className: pulseClass2,
2912
+ style: pulseClass2 ? { animationDelay: `${delay}s` } : void 0
2916
2913
  },
2917
2914
  i
2918
2915
  );
@@ -6919,7 +6916,7 @@ function renderVariant(variant, rows2, columns, fields, className) {
6919
6916
  }
6920
6917
  Skeleton.displayName = "Skeleton";
6921
6918
  var LazySlotContentRenderer = lazy(
6922
- () => import('./UISlotRenderer-EEOXSJCI.js').then((m) => ({
6919
+ () => import('./UISlotRenderer-NZBV5BUI.js').then((m) => ({
6923
6920
  default: m.SlotContentRenderer
6924
6921
  }))
6925
6922
  );
@@ -14437,7 +14434,7 @@ var CodeBlock = React93__default.memo(
14437
14434
  () => naturalTabs?.find((lang) => lang === pageLocale) ?? naturalTabs?.[0] ?? "en"
14438
14435
  );
14439
14436
  const activeNaturalLanguage = naturalTabs?.includes(naturalLanguage) === true ? naturalLanguage : naturalTabs?.[0] ?? "en";
14440
- const codeDir = naturalTabs && coreTables[activeNaturalLanguage].meta.rtl ? "rtl" : "ltr";
14437
+ const codeDir = naturalTabs && getVocabulary(activeNaturalLanguage).meta.rtl ? "rtl" : "ltr";
14441
14438
  const translationCache = useMemo(() => /* @__PURE__ */ new Map(), [englishCode, files]);
14442
14439
  const translateFor = useCallback(
14443
14440
  (source, sourceLanguage, cacheKey) => {
@@ -14454,14 +14451,14 @@ var CodeBlock = React93__default.memo(
14454
14451
  const code = translateFor(englishCode, language, "code");
14455
14452
  const naturalTabItems = naturalTabs?.map((lang) => ({
14456
14453
  id: `lang-${lang}`,
14457
- label: coreTables[lang].meta.name,
14454
+ label: getVocabulary(lang).meta.name,
14458
14455
  content: null
14459
14456
  }));
14460
14457
  const naturalTabStrip = naturalTabs && naturalTabItems ? /* @__PURE__ */ jsx(
14461
14458
  Box,
14462
14459
  {
14463
14460
  className: "border-b border-border",
14464
- dir: coreTables[activeNaturalLanguage].meta.rtl ? "rtl" : "ltr",
14461
+ dir: getVocabulary(activeNaturalLanguage).meta.rtl ? "rtl" : "ltr",
14465
14462
  "data-testid": "codeblock-language-tabs",
14466
14463
  children: /* @__PURE__ */ jsx(
14467
14464
  Tabs,
@@ -18352,10 +18349,10 @@ var AvlState = ({
18352
18349
  }) => {
18353
18350
  const width = computeWidth(explicitWidth, transitionCount);
18354
18351
  const rx = height / 2;
18355
- const roleColors = role ? STATE_COLORS[role] : null;
18356
- const fillColor = roleColors ? roleColors.fill : "none";
18357
- const strokeColor = roleColors ? roleColors.border : color;
18358
- const textColor = roleColors ? roleColors.border : color;
18352
+ const roleColors2 = role ? STATE_COLORS[role] : null;
18353
+ const fillColor = roleColors2 ? roleColors2.fill : "none";
18354
+ const strokeColor = roleColors2 ? roleColors2.border : color;
18355
+ const textColor = roleColors2 ? roleColors2.border : color;
18359
18356
  return /* @__PURE__ */ jsxs("g", { className, opacity, transform: `translate(${x},${y})`, children: [
18360
18357
  isInitial && /* @__PURE__ */ jsx(
18361
18358
  "circle",
@@ -21987,18 +21984,30 @@ var Carousel = ({
21987
21984
  loop = false,
21988
21985
  slideChangeEvent,
21989
21986
  slideChangePayload,
21987
+ orientation = "horizontal",
21988
+ fullHeight = false,
21989
+ loadMoreEvent,
21990
+ loadMoreAhead = 2,
21991
+ hasMore = false,
21992
+ isLoadingMore = false,
21990
21993
  className,
21991
21994
  ...rest
21992
21995
  }) => {
21996
+ const vertical = orientation === "vertical";
21997
+ const loadRequestedAt = useRef(null);
21993
21998
  const [activeIndex, setActiveIndex] = useState(0);
21994
21999
  const scrollRef = useRef(null);
22000
+ const rootRef = useRef(null);
22001
+ const [topOffset, setTopOffset] = useState(0);
21995
22002
  const autoPlayRef = useRef(null);
21996
22003
  const eventBus = useSafeEventBus3();
21997
22004
  const { t } = useTranslate();
21998
22005
  const safeItems = items ?? [];
21999
22006
  const totalSlides = safeItems.length;
22007
+ const announcedIndex = useRef(0);
22000
22008
  const emitSlideChange = useCallback(
22001
22009
  (newIndex) => {
22010
+ announcedIndex.current = newIndex;
22002
22011
  if (slideChangeEvent) {
22003
22012
  eventBus.emit(`UI:${slideChangeEvent}`, {
22004
22013
  index: newIndex,
@@ -22012,13 +22021,13 @@ var Carousel = ({
22012
22021
  (index) => {
22013
22022
  const container = scrollRef.current;
22014
22023
  if (!container) return;
22015
- const slideWidth = container.offsetWidth;
22016
- container.scrollTo({
22017
- left: slideWidth * index,
22018
- behavior: "smooth"
22019
- });
22024
+ const reduceMotion = typeof window !== "undefined" && typeof window.matchMedia === "function" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
22025
+ const behavior = reduceMotion ? "auto" : "smooth";
22026
+ if (typeof container.scrollTo !== "function") return;
22027
+ if (vertical) container.scrollTo({ top: container.offsetHeight * index, behavior });
22028
+ else container.scrollTo({ left: container.offsetWidth * index, behavior });
22020
22029
  },
22021
- []
22030
+ [vertical]
22022
22031
  );
22023
22032
  const goToSlide = useCallback(
22024
22033
  (index) => {
@@ -22042,10 +22051,7 @@ var Carousel = ({
22042
22051
  goToSlide(activeIndex - 1);
22043
22052
  }, [goToSlide, activeIndex]);
22044
22053
  const swipeHandlers = useSwipeGesture(
22045
- {
22046
- onSwipeLeft: goNext,
22047
- onSwipeRight: goPrev
22048
- },
22054
+ vertical ? { onSwipeUp: goNext, onSwipeDown: goPrev } : { onSwipeLeft: goNext, onSwipeRight: goPrev },
22049
22055
  { threshold: 40 }
22050
22056
  );
22051
22057
  useEffect(() => {
@@ -22070,138 +22076,189 @@ var Carousel = ({
22070
22076
  const handleScroll = useCallback(() => {
22071
22077
  const container = scrollRef.current;
22072
22078
  if (!container) return;
22073
- const slideWidth = container.offsetWidth;
22074
- if (slideWidth === 0) return;
22075
- const newIndex = Math.round(container.scrollLeft / slideWidth);
22076
- setActiveIndex((prev) => {
22077
- if (prev !== newIndex && newIndex >= 0 && newIndex < totalSlides) {
22078
- return newIndex;
22079
- }
22080
- return prev;
22081
- });
22082
- }, [totalSlides]);
22079
+ const slideSize = vertical ? container.offsetHeight : container.offsetWidth;
22080
+ if (slideSize === 0) return;
22081
+ const position = vertical ? container.scrollTop : container.scrollLeft;
22082
+ const newIndex = Math.round(position / slideSize);
22083
+ if (newIndex < 0 || newIndex >= totalSlides) return;
22084
+ setActiveIndex(newIndex);
22085
+ if (Math.abs(position - newIndex * slideSize) <= 1 && newIndex !== announcedIndex.current) {
22086
+ emitSlideChange(newIndex);
22087
+ }
22088
+ }, [totalSlides, vertical, emitSlideChange]);
22089
+ useEffect(() => {
22090
+ if (!loadMoreEvent || !hasMore || isLoadingMore || totalSlides === 0) return;
22091
+ if (activeIndex < totalSlides - 1 - loadMoreAhead) return;
22092
+ if (loadRequestedAt.current === totalSlides) return;
22093
+ loadRequestedAt.current = totalSlides;
22094
+ eventBus.emit(`UI:${loadMoreEvent}`, { index: activeIndex });
22095
+ }, [activeIndex, totalSlides, loadMoreEvent, hasMore, isLoadingMore, loadMoreAhead, eventBus]);
22096
+ const viewportBound = vertical && fullHeight;
22097
+ useLayoutEffect(() => {
22098
+ if (!viewportBound || typeof window === "undefined") return;
22099
+ const measure = () => {
22100
+ const root = rootRef.current;
22101
+ if (root) setTopOffset(Math.max(0, Math.round(root.getBoundingClientRect().top)));
22102
+ };
22103
+ measure();
22104
+ window.addEventListener("resize", measure);
22105
+ return () => window.removeEventListener("resize", measure);
22106
+ }, [viewportBound]);
22107
+ const handleKeyDown = useCallback(
22108
+ (e) => {
22109
+ const next = vertical ? ["ArrowDown", "PageDown"] : ["ArrowRight"];
22110
+ const prev = vertical ? ["ArrowUp", "PageUp"] : ["ArrowLeft"];
22111
+ if (next.includes(e.key)) {
22112
+ e.preventDefault();
22113
+ goNext();
22114
+ } else if (prev.includes(e.key)) {
22115
+ e.preventDefault();
22116
+ goPrev();
22117
+ }
22118
+ },
22119
+ [vertical, goNext, goPrev]
22120
+ );
22083
22121
  const hasPrev = loop || activeIndex > 0;
22084
22122
  const hasNext = loop || activeIndex < totalSlides - 1;
22085
22123
  if (totalSlides === 0) return null;
22086
- return /* @__PURE__ */ jsxs(Box, { position: "relative", overflow: "hidden", ...domPassthrough(rest), className: cn("w-full", className), children: [
22087
- /* @__PURE__ */ jsx(
22088
- Box,
22089
- {
22090
- ref: scrollRef,
22091
- display: "flex",
22092
- overflow: "auto",
22093
- className: cn(
22094
- "w-full",
22095
- "scroll-smooth",
22096
- "scrollbar-none",
22097
- "[scroll-snap-type:x_mandatory]",
22098
- "[&::-webkit-scrollbar]:hidden",
22099
- "[-ms-overflow-style:none]"
22100
- ),
22101
- style: {
22102
- scrollSnapType: "x mandatory",
22103
- WebkitOverflowScrolling: "touch"
22104
- },
22105
- onScroll: handleScroll,
22106
- onPointerDown: swipeHandlers.onPointerDown,
22107
- onPointerMove: swipeHandlers.onPointerMove,
22108
- onPointerUp: swipeHandlers.onPointerUp,
22109
- onPointerCancel: swipeHandlers.onPointerCancel,
22110
- children: safeItems.map((item, index) => /* @__PURE__ */ jsx(
22124
+ return /* @__PURE__ */ jsxs(
22125
+ Box,
22126
+ {
22127
+ position: "relative",
22128
+ overflow: "hidden",
22129
+ role: "region",
22130
+ "aria-roledescription": t("aria.carousel"),
22131
+ tabIndex: 0,
22132
+ onKeyDown: handleKeyDown,
22133
+ ...domPassthrough(rest),
22134
+ ref: rootRef,
22135
+ className: cn("w-full", fullHeight && !viewportBound && "h-full", className),
22136
+ style: viewportBound ? { height: `calc(100svh - ${topOffset}px)` } : void 0,
22137
+ children: [
22138
+ /* @__PURE__ */ jsx(
22111
22139
  Box,
22112
22140
  {
22141
+ ref: scrollRef,
22142
+ display: "flex",
22143
+ overflow: "auto",
22113
22144
  className: cn(
22114
- "flex-shrink-0 w-full",
22115
- "[scroll-snap-align:start]"
22145
+ "w-full",
22146
+ "scroll-smooth",
22147
+ "scrollbar-none",
22148
+ vertical ? "[scroll-snap-type:y_mandatory]" : "[scroll-snap-type:x_mandatory]",
22149
+ "[&::-webkit-scrollbar]:hidden",
22150
+ "[-ms-overflow-style:none]"
22116
22151
  ),
22117
22152
  style: {
22118
- scrollSnapAlign: "start"
22153
+ flexDirection: vertical ? "column" : "row",
22154
+ scrollSnapType: vertical ? "y mandatory" : "x mandatory",
22155
+ height: fullHeight ? "100%" : void 0,
22156
+ WebkitOverflowScrolling: "touch"
22119
22157
  },
22120
- children: (renderItem ?? children)?.(item, index)
22121
- },
22122
- index
22123
- ))
22124
- }
22125
- ),
22126
- showArrows && hasPrev && totalSlides > 1 && /* @__PURE__ */ jsx(
22127
- Box,
22128
- {
22129
- position: "absolute",
22130
- className: "left-2 top-1/2 -translate-y-1/2 z-10",
22131
- children: /* @__PURE__ */ jsx(
22132
- Button,
22158
+ onScroll: handleScroll,
22159
+ onPointerDown: swipeHandlers.onPointerDown,
22160
+ onPointerMove: swipeHandlers.onPointerMove,
22161
+ onPointerUp: swipeHandlers.onPointerUp,
22162
+ onPointerCancel: swipeHandlers.onPointerCancel,
22163
+ children: safeItems.map((item, index) => /* @__PURE__ */ jsx(
22164
+ Box,
22165
+ {
22166
+ className: cn(
22167
+ "flex-shrink-0 w-full",
22168
+ "[scroll-snap-align:start]"
22169
+ ),
22170
+ style: {
22171
+ scrollSnapAlign: "start",
22172
+ scrollSnapStop: vertical ? "always" : void 0,
22173
+ height: fullHeight ? "100%" : void 0
22174
+ },
22175
+ children: (renderItem ?? children)?.(item, index)
22176
+ },
22177
+ index
22178
+ ))
22179
+ }
22180
+ ),
22181
+ showArrows && hasPrev && totalSlides > 1 && /* @__PURE__ */ jsx(
22182
+ Box,
22133
22183
  {
22134
- variant: "ghost",
22135
- size: "sm",
22136
- onClick: goPrev,
22137
- "aria-label": t("aria.previousSlide"),
22138
- className: cn(
22139
- "rounded-full",
22140
- "bg-surface/80",
22141
- "backdrop-blur-sm",
22142
- "shadow-elevation-interactive",
22143
- "hover:bg-surface"
22144
- ),
22145
- children: /* @__PURE__ */ jsx(ChevronLeft, { className: "w-5 h-5" })
22184
+ position: "absolute",
22185
+ className: vertical ? "right-2 top-2 z-10" : "left-2 top-1/2 -translate-y-1/2 z-10",
22186
+ children: /* @__PURE__ */ jsx(
22187
+ Button,
22188
+ {
22189
+ variant: "ghost",
22190
+ size: "sm",
22191
+ onClick: goPrev,
22192
+ "aria-label": t("aria.previousSlide"),
22193
+ className: cn(
22194
+ "rounded-full",
22195
+ "bg-surface/80",
22196
+ "backdrop-blur-sm",
22197
+ "shadow-elevation-interactive",
22198
+ "hover:bg-surface"
22199
+ ),
22200
+ children: vertical ? /* @__PURE__ */ jsx(ChevronUp, { className: "w-5 h-5" }) : /* @__PURE__ */ jsx(ChevronLeft, { className: "w-5 h-5" })
22201
+ }
22202
+ )
22146
22203
  }
22147
- )
22148
- }
22149
- ),
22150
- showArrows && hasNext && totalSlides > 1 && /* @__PURE__ */ jsx(
22151
- Box,
22152
- {
22153
- position: "absolute",
22154
- className: "right-2 top-1/2 -translate-y-1/2 z-10",
22155
- children: /* @__PURE__ */ jsx(
22156
- Button,
22204
+ ),
22205
+ showArrows && hasNext && totalSlides > 1 && /* @__PURE__ */ jsx(
22206
+ Box,
22157
22207
  {
22158
- variant: "ghost",
22159
- size: "sm",
22160
- onClick: goNext,
22161
- "aria-label": t("aria.nextSlide"),
22162
- className: cn(
22163
- "rounded-full",
22164
- "bg-surface/80",
22165
- "backdrop-blur-sm",
22166
- "shadow-elevation-interactive",
22167
- "hover:bg-surface"
22168
- ),
22169
- children: /* @__PURE__ */ jsx(ChevronRight, { className: "w-5 h-5" })
22208
+ position: "absolute",
22209
+ className: vertical ? "right-2 bottom-2 z-10" : "right-2 top-1/2 -translate-y-1/2 z-10",
22210
+ children: /* @__PURE__ */ jsx(
22211
+ Button,
22212
+ {
22213
+ variant: "ghost",
22214
+ size: "sm",
22215
+ onClick: goNext,
22216
+ "aria-label": t("aria.nextSlide"),
22217
+ className: cn(
22218
+ "rounded-full",
22219
+ "bg-surface/80",
22220
+ "backdrop-blur-sm",
22221
+ "shadow-elevation-interactive",
22222
+ "hover:bg-surface"
22223
+ ),
22224
+ children: vertical ? /* @__PURE__ */ jsx(ChevronDown, { className: "w-5 h-5" }) : /* @__PURE__ */ jsx(ChevronRight, { className: "w-5 h-5" })
22225
+ }
22226
+ )
22227
+ }
22228
+ ),
22229
+ showDots && totalSlides > 1 && /* @__PURE__ */ jsx(
22230
+ Box,
22231
+ {
22232
+ position: "absolute",
22233
+ className: "bottom-3 left-0 right-0 z-10",
22234
+ children: /* @__PURE__ */ jsx(HStack, { gap: "xs", align: "center", justify: "center", role: "tablist", "aria-label": t("aria.carouselSlides"), children: safeItems.map((_, index) => {
22235
+ const isActive = index === activeIndex;
22236
+ return /* @__PURE__ */ jsx(
22237
+ Box,
22238
+ {
22239
+ className: cn(
22240
+ "rounded-full cursor-pointer transition-all duration-fast"
22241
+ ),
22242
+ style: {
22243
+ width: isActive ? 10 : 8,
22244
+ height: isActive ? 10 : 8,
22245
+ backgroundColor: isActive ? "var(--color-primary)" : "var(--color-muted, #d4d4d8)",
22246
+ opacity: isActive ? 1 : 0.6
22247
+ },
22248
+ ...pressableProps(() => goToSlide(index)),
22249
+ role: "tab",
22250
+ "aria-selected": isActive,
22251
+ tabIndex: isActive ? 0 : -1,
22252
+ "aria-label": t("carousel.goToSlide", { number: index + 1 })
22253
+ },
22254
+ index
22255
+ );
22256
+ }) })
22170
22257
  }
22171
22258
  )
22172
- }
22173
- ),
22174
- showDots && totalSlides > 1 && /* @__PURE__ */ jsx(
22175
- Box,
22176
- {
22177
- position: "absolute",
22178
- className: "bottom-3 left-0 right-0 z-10",
22179
- children: /* @__PURE__ */ jsx(HStack, { gap: "xs", align: "center", justify: "center", role: "tablist", "aria-label": t("aria.carouselSlides"), children: safeItems.map((_, index) => {
22180
- const isActive = index === activeIndex;
22181
- return /* @__PURE__ */ jsx(
22182
- Box,
22183
- {
22184
- className: cn(
22185
- "rounded-full cursor-pointer transition-all duration-fast"
22186
- ),
22187
- style: {
22188
- width: isActive ? 10 : 8,
22189
- height: isActive ? 10 : 8,
22190
- backgroundColor: isActive ? "var(--color-primary)" : "var(--color-muted, #d4d4d8)",
22191
- opacity: isActive ? 1 : 0.6
22192
- },
22193
- ...pressableProps(() => goToSlide(index)),
22194
- role: "tab",
22195
- "aria-selected": isActive,
22196
- tabIndex: isActive ? 0 : -1,
22197
- "aria-label": t("carousel.goToSlide", { number: index + 1 })
22198
- },
22199
- index
22200
- );
22201
- }) })
22202
- }
22203
- )
22204
- ] });
22259
+ ]
22260
+ }
22261
+ );
22205
22262
  };
22206
22263
  Carousel.displayName = "Carousel";
22207
22264
  var TYPE_STYLE = {
@@ -23223,6 +23280,8 @@ function ChatBar({
23223
23280
  placeholder,
23224
23281
  context,
23225
23282
  sendEvent = "CHAT_SEND",
23283
+ focusRequest,
23284
+ editFocus,
23226
23285
  className,
23227
23286
  ...rest
23228
23287
  }) {
@@ -23231,7 +23290,14 @@ function ChatBar({
23231
23290
  const [inputValue, setInputValue] = useState("");
23232
23291
  const inputRef = useRef(null);
23233
23292
  const [requestedPlaceholder, setRequestedPlaceholder] = useState(null);
23234
- const [focus, setFocus] = useState(null);
23293
+ const focus = editFocus ?? null;
23294
+ const requestId = focusRequest?.id;
23295
+ const requestPlaceholder = focusRequest?.placeholder;
23296
+ useEffect(() => {
23297
+ if (requestId === void 0) return;
23298
+ if (requestPlaceholder !== void 0 && requestPlaceholder.length > 0) setRequestedPlaceholder(requestPlaceholder);
23299
+ inputRef.current?.focus();
23300
+ }, [requestId, requestPlaceholder]);
23235
23301
  useLayoutEffect(() => {
23236
23302
  const el = inputRef.current;
23237
23303
  if (!el) return;
@@ -23241,36 +23307,21 @@ function ChatBar({
23241
23307
  el.style.overflowY = el.scrollHeight > INPUT_MAX_HEIGHT_PX ? "auto" : "hidden";
23242
23308
  }, [inputValue]);
23243
23309
  const clearFocus = useCallback(() => {
23244
- setFocus(null);
23245
23310
  eventBus.emit(ELEMENT_SELECTED_EVENT, { focus: null });
23246
23311
  }, [eventBus]);
23312
+ const clearSent = useCallback(() => {
23313
+ setInputValue("");
23314
+ setRequestedPlaceholder(null);
23315
+ }, []);
23247
23316
  const handleKeyDown = useCallback((e) => {
23248
23317
  if (e.key !== "Enter" || e.shiftKey) return;
23249
23318
  const trimmed = inputValue.trim();
23250
23319
  if (!trimmed) return;
23251
23320
  e.preventDefault();
23252
23321
  eventBus.emit(`UI:${sendEvent}`, { message: trimmed });
23253
- }, [inputValue, eventBus, sendEvent]);
23254
- useEffect(() => {
23255
- const unsubSend = eventBus.on(`UI:${sendEvent}`, () => {
23256
- setInputValue("");
23257
- setFocus(null);
23258
- setRequestedPlaceholder(null);
23259
- });
23260
- const unsubFocus = eventBus.on("UI:CHAT_FOCUS", (e) => {
23261
- const hint = e.payload?.placeholder;
23262
- if (typeof hint === "string" && hint.length > 0) setRequestedPlaceholder(hint);
23263
- inputRef.current?.focus();
23264
- });
23265
- const unsubSelect = eventBus.on(ELEMENT_SELECTED_EVENT, (e) => {
23266
- setFocus(parseEditFocus(e.payload?.focus));
23267
- });
23268
- return () => {
23269
- unsubSend();
23270
- unsubFocus();
23271
- unsubSelect();
23272
- };
23273
- }, [eventBus, sendEvent]);
23322
+ clearSent();
23323
+ }, [inputValue, eventBus, sendEvent, clearSent]);
23324
+ useEffect(() => eventBus.on(`UI:${sendEvent}`, clearSent), [eventBus, sendEvent, clearSent]);
23274
23325
  const trailingAction = status === "error" ? /* @__PURE__ */ jsxs(Button, { variant: "secondary", size: "sm", action: "RETRY_GENERATION", className: "rounded-none flex-shrink-0 h-auto", children: [
23275
23326
  /* @__PURE__ */ jsx(Icon, { name: "refresh-cw", size: "xs" }),
23276
23327
  /* @__PURE__ */ jsx(Typography, { variant: "caption", children: t("openFile.retry") })
@@ -23317,6 +23368,7 @@ function ChatBar({
23317
23368
  size: "sm",
23318
23369
  action: sendEvent,
23319
23370
  actionPayload: { message: inputValue.trim() },
23371
+ onClick: clearSent,
23320
23372
  disabled: !inputValue.trim(),
23321
23373
  "aria-label": t("chatBar.sendMessage"),
23322
23374
  className: "rounded-none flex-shrink-0 h-auto",
@@ -25494,13 +25546,16 @@ var DashboardLayout = ({
25494
25546
  useEffect(() => {
25495
25547
  registerNavItems(navItems);
25496
25548
  }, [navItems, registerNavItems]);
25497
- const { user: authUser, signOut: authSignOut } = useAuthContext();
25549
+ const { user: authUser } = useAuthContext();
25498
25550
  const user = userProp || (authUser ? {
25499
25551
  name: authUser.displayName || authUser.email?.split("@")[0] || t("dashboard.defaultUserName"),
25500
25552
  email: authUser.email || "",
25501
25553
  avatar: authUser.photoURL || void 0
25502
25554
  } : null);
25503
- const handleSignOut = onSignOutProp || authSignOut;
25555
+ const handleSignOut = () => {
25556
+ onSignOutProp?.();
25557
+ eventBus.emit("UI:SIGN_OUT", {});
25558
+ };
25504
25559
  const showSidebar = layoutMode === "sidebar" || isDrawer;
25505
25560
  const showHeader = layoutMode !== "minimal";
25506
25561
  const showBottomNav = layoutMode === "bottomnav";
@@ -25509,7 +25564,11 @@ var DashboardLayout = ({
25509
25564
  Box,
25510
25565
  {
25511
25566
  ref: layoutRef,
25512
- className: "@container/dashboard min-h-screen w-full bg-background surface-page flex flex-row items-stretch",
25567
+ className: cn(
25568
+ "@container/dashboard w-full bg-background surface-page flex flex-row items-stretch",
25569
+ // A full-bleed shell is an app frame: viewport-bound, so a full-height child gets a real height.
25570
+ fullBleed ? "h-screen overflow-hidden" : "min-h-screen"
25571
+ ),
25513
25572
  children: [
25514
25573
  /* @__PURE__ */ jsx(
25515
25574
  Button,
@@ -25613,7 +25672,7 @@ var DashboardLayout = ({
25613
25672
  ]
25614
25673
  }
25615
25674
  ),
25616
- /* @__PURE__ */ jsxs(VStack, { gap: "none", className: "flex-1 min-w-0 min-h-screen", children: [
25675
+ /* @__PURE__ */ jsxs(VStack, { gap: "none", className: cn("flex-1 min-w-0", fullBleed ? "h-full min-h-0" : "min-h-screen"), children: [
25617
25676
  showHeader && /* @__PURE__ */ jsx(
25618
25677
  Box,
25619
25678
  {
@@ -25836,7 +25895,7 @@ var DashboardLayout = ({
25836
25895
  id: "main-content",
25837
25896
  tabIndex: -1,
25838
25897
  className: cn(
25839
- fullBleed ? "flex-1 min-h-0 flex flex-col focus:outline-none" : "flex-1 p-3 @sm/dashboard:p-4 @md/dashboard:p-6 focus:outline-none",
25898
+ fullBleed ? "flex-1 min-h-0 flex flex-col overflow-y-auto focus:outline-none" : "flex-1 p-3 @sm/dashboard:p-4 @md/dashboard:p-6 focus:outline-none",
25840
25899
  // Reserve space for the fixed bottom nav so content isn't
25841
25900
  // hidden under the tab bar.
25842
25901
  showBottomNav && "pb-[calc(5rem+env(safe-area-inset-bottom))]"
@@ -28114,7 +28173,7 @@ var MapViewImpl = lazy(async () => {
28114
28173
  });
28115
28174
  L.Marker.prototype.options.icon = defaultIcon;
28116
28175
  const { useEffect: useEffect77, useRef: useRef79, useCallback: useCallback92, useState: useState107 } = React93__default;
28117
- const { Typography: Typography2 } = await import('./Typography-BY4A2NBY.js');
28176
+ const { Typography: Typography2 } = await import('./Typography-KBATMU2V.js');
28118
28177
  const { useEventBus: useEventBus2 } = await import('./useEventBus-SWRN475O.js');
28119
28178
  function MapUpdater({ centerLat, centerLng, zoom }) {
28120
28179
  const map = useMap();
@@ -35283,6 +35342,14 @@ function recordDispatchVerdict(orbitalName, event, verdict) {
35283
35342
  effectResults: serverEffectTraces(response.effectResults)
35284
35343
  });
35285
35344
  }
35345
+
35346
+ // lib/hostDispatchInView.ts
35347
+ function hostDispatchInView(request, response, owns) {
35348
+ if (request.targetTrait !== void 0 && owns(request.targetTrait)) return true;
35349
+ if (Object.keys(response.states).some(owns)) return true;
35350
+ if (Object.keys(response.entityByTrait ?? {}).some(owns)) return true;
35351
+ return (response.clientEffectsByTrait ?? []).some((e) => owns(e.traitName));
35352
+ }
35286
35353
  var tabClientId;
35287
35354
  function getTabClientId() {
35288
35355
  if (tabClientId === void 0) tabClientId = crypto.randomUUID();
@@ -35575,6 +35642,9 @@ function readsI18n(value) {
35575
35642
  const arr = value;
35576
35643
  return arr[0] === "i18n/t" || arr.some((v) => readsI18n(v));
35577
35644
  }
35645
+ if (value !== null && typeof value === "object" && !React93__default.isValidElement(value) && !(value instanceof Date) && typeof value !== "function") {
35646
+ return Object.values(value).some((v) => readsI18n(v));
35647
+ }
35578
35648
  return false;
35579
35649
  }
35580
35650
  function needsRenderContext(value) {
@@ -35652,7 +35722,7 @@ function resolveLambdaBindings(body, params, item, index) {
35652
35722
  return body;
35653
35723
  }
35654
35724
  var LazySlotContentRenderer2 = React93__default.lazy(
35655
- () => import('./UISlotRenderer-EEOXSJCI.js').then((m) => ({ default: m.SlotContentRenderer }))
35725
+ () => import('./UISlotRenderer-NZBV5BUI.js').then((m) => ({ default: m.SlotContentRenderer }))
35656
35726
  );
35657
35727
  function deferLambdaEntityExprs(value) {
35658
35728
  if (typeof value === "string") {
@@ -36485,7 +36555,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
36485
36555
  if (!transport?.subscribeHostDispatches) return;
36486
36556
  return transport.subscribeHostDispatches((_orbitalName, request, response) => {
36487
36557
  const traitName = request.targetTrait;
36488
- if (traitName === void 0 || !traitIndex.byName.has(traitName)) return;
36558
+ if (traitName === void 0 || !hostDispatchInView(request, response, (t2) => traitIndex.byName.has(t2))) return;
36489
36559
  const composedBefore = new Map(store.callsitePayloads);
36490
36560
  void kernel.foldHostDispatch(request, response).then((outcome) => settleOutcome(traitName, request.event, request.payload, outcome, composedBefore));
36491
36561
  }, { clientId: getTabClientId() });
@@ -36964,6 +37034,11 @@ function NavigateListener({ onNavigate }) {
36964
37034
  );
36965
37035
  return null;
36966
37036
  }
37037
+ function SignOutListener({ onSignOut }) {
37038
+ const bus = useEventBus();
37039
+ useEffect(() => bus.on("UI:SIGN_OUT", () => onSignOut()), [bus, onSignOut]);
37040
+ return null;
37041
+ }
36967
37042
  function OrbPreview({
36968
37043
  schema,
36969
37044
  mockData,
@@ -36984,7 +37059,8 @@ function OrbPreview({
36984
37059
  lazyLoader,
36985
37060
  schemaPath,
36986
37061
  onUnmatchedNavigate,
36987
- onSignIn
37062
+ onSignIn,
37063
+ onSignOut
36988
37064
  }) {
36989
37065
  if (serverUrl && transport) {
36990
37066
  throw new Error("OrbPreview accepts serverUrl OR transport, not both");
@@ -37272,6 +37348,7 @@ function OrbPreview({
37272
37348
  /* @__PURE__ */ jsx(NavStackRefBridge, { apiRef: navStackRef }),
37273
37349
  /* @__PURE__ */ jsxs(OrbitalProvider, { initialData: effectiveMockData, skipTheme: true, verification: true, isolated, user, children: [
37274
37350
  /* @__PURE__ */ jsx(NavigateListener, { onNavigate: handleNavigate }),
37351
+ onSignOut !== void 0 && /* @__PURE__ */ jsx(SignOutListener, { onSignOut }),
37275
37352
  /* @__PURE__ */ jsx(UISlotProvider, { children: /* @__PURE__ */ jsx(
37276
37353
  PageAccessHost,
37277
37354
  {
@@ -37710,12 +37787,10 @@ var VERDICT_VARIANT = {
37710
37787
  stale: "warning",
37711
37788
  running: "info"
37712
37789
  };
37713
- var ROLE_COLORS = {
37714
- initial: { border: STATE_COLORS.initial.border, dot: STATE_COLORS.initial.border },
37715
- terminal: { border: STATE_COLORS.terminal.border, dot: STATE_COLORS.terminal.border },
37716
- hub: { border: STATE_COLORS.hub.border, dot: STATE_COLORS.hub.border },
37717
- default: { border: "var(--color-border)", dot: STATE_COLORS.default.border }
37718
- };
37790
+ function roleColors(role) {
37791
+ if (role === "default") return { border: "var(--color-border)", dot: STATE_COLORS.default.border };
37792
+ return { border: STATE_COLORS[role].border, dot: STATE_COLORS[role].border };
37793
+ }
37719
37794
  var LAYER_ORDER = ["Infrastructure", "Services", "UI Patterns", "Game", "ML", "Domain", "Community"];
37720
37795
  var LAYER_LABEL_KEYS = {
37721
37796
  Infrastructure: "orbPreview.layer.infrastructure",
@@ -38094,7 +38169,7 @@ var OrbPreviewNodeInner = (props) => {
38094
38169
  const [hoverRect, setHoverRect] = useState(null);
38095
38170
  const lastHoverElRef = useRef(null);
38096
38171
  const role = data.stateRole ?? "default";
38097
- const colors = ROLE_COLORS[role] ?? ROLE_COLORS.default;
38172
+ const colors = roleColors(role);
38098
38173
  const eventSources = data.eventSources ?? [];
38099
38174
  const layerColor = data.layer ? LAYER_COLORS[data.layer] : void 0;
38100
38175
  const isExpanded = Boolean(data.traitName);
@@ -55673,8 +55748,8 @@ var COMPONENT_REGISTRY = {
55673
55748
  }
55674
55749
  };
55675
55750
  var scopeWrapLog = createLogger("almadar:ui:scope-wrap");
55676
- var LazyTraitValueFrame = React93__default.lazy(() => import('./TraitValueFrame-WOXNLLMM.js'));
55677
- var LazyBehaviorValueFrame = React93__default.lazy(() => import('./BehaviorValueFrame-QTD7BWOI.js'));
55751
+ var LazyTraitValueFrame = React93__default.lazy(() => import('./TraitValueFrame-X6IL3UST.js'));
55752
+ var LazyBehaviorValueFrame = React93__default.lazy(() => import('./BehaviorValueFrame-QYFJEMN5.js'));
55678
55753
  var TRAIT_BINDING_RE = /^@trait\.([A-Z][A-Za-z0-9]*)$/;
55679
55754
  function slotPropsOf(content) {
55680
55755
  return typeof content.props === "string" ? {} : content.props;