@almadar/ui 5.76.7 → 5.77.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 (62) hide show
  1. package/dist/avl/index.cjs +264 -443
  2. package/dist/avl/index.css +3 -3
  3. package/dist/avl/index.js +265 -444
  4. package/dist/components/core/atoms/FlipContainer.d.ts +1 -1
  5. package/dist/components/core/molecules/Card.d.ts +1 -1
  6. package/dist/components/core/molecules/DataGrid.d.ts +1 -1
  7. package/dist/components/core/molecules/DataList.d.ts +1 -1
  8. package/dist/components/core/molecules/DocPagination.d.ts +1 -8
  9. package/dist/components/core/molecules/DocSearch.d.ts +1 -8
  10. package/dist/components/core/molecules/FlipCard.d.ts +1 -1
  11. package/dist/components/core/molecules/MapView.d.ts +1 -18
  12. package/dist/components/core/molecules/SortableList.d.ts +1 -1
  13. package/dist/components/core/molecules/TableView.d.ts +1 -1
  14. package/dist/components/core/organisms/DataTable.d.ts +1 -1
  15. package/dist/components/core/organisms/debug/RuntimeDebugger.d.ts +1 -10
  16. package/dist/components/core/organisms/debug/tabs/EntitiesTab.d.ts +1 -2
  17. package/dist/components/core/organisms/debug/tabs/EventDispatcherTab.d.ts +1 -2
  18. package/dist/components/core/organisms/debug/tabs/EventFlowTab.d.ts +1 -6
  19. package/dist/components/core/organisms/debug/tabs/GuardsPanel.d.ts +1 -6
  20. package/dist/components/core/organisms/debug/tabs/ServerBridgeTab.d.ts +1 -12
  21. package/dist/components/core/organisms/debug/tabs/TicksTab.d.ts +1 -2
  22. package/dist/components/core/organisms/debug/tabs/TraitsTab.d.ts +1 -2
  23. package/dist/components/core/organisms/debug/tabs/TransitionTimeline.d.ts +1 -11
  24. package/dist/components/core/organisms/debug/tabs/VerificationTab.d.ts +1 -8
  25. package/dist/components/game/2d/atoms/ActionButton.d.ts +1 -2
  26. package/dist/components/game/2d/atoms/ChoiceButton.d.ts +1 -2
  27. package/dist/components/game/2d/atoms/ComboCounter.d.ts +1 -2
  28. package/dist/components/game/2d/atoms/ControlButton.d.ts +1 -2
  29. package/dist/components/game/2d/atoms/DamageNumber.d.ts +1 -2
  30. package/dist/components/game/2d/atoms/DialogueBubble.d.ts +1 -2
  31. package/dist/components/game/2d/atoms/GameIcon.d.ts +1 -2
  32. package/dist/components/game/2d/atoms/HealthBar.d.ts +1 -2
  33. package/dist/components/game/2d/atoms/ItemSlot.d.ts +1 -2
  34. package/dist/components/game/2d/atoms/MiniMap.d.ts +1 -2
  35. package/dist/components/game/2d/atoms/ResourceCounter.d.ts +1 -2
  36. package/dist/components/game/2d/atoms/ScoreDisplay.d.ts +1 -2
  37. package/dist/components/game/2d/atoms/StatusEffect.d.ts +1 -2
  38. package/dist/components/game/2d/atoms/TimerDisplay.d.ts +1 -2
  39. package/dist/components/game/2d/atoms/TurnIndicator.d.ts +1 -2
  40. package/dist/components/game/2d/atoms/WaypointMarker.d.ts +1 -2
  41. package/dist/components/game/2d/molecules/GameHud.d.ts +1 -2
  42. package/dist/components/game/2d/molecules/GameMenu.d.ts +1 -2
  43. package/dist/components/game/2d/molecules/InventoryGrid.d.ts +1 -2
  44. package/dist/components/game/2d/molecules/ResourceBar.d.ts +1 -2
  45. package/dist/components/game/2d/molecules/StatBadge.d.ts +1 -2
  46. package/dist/components/game/shared/lib/editorUtils.d.ts +8 -8
  47. package/dist/components/index.cjs +133 -134
  48. package/dist/components/index.css +3 -3
  49. package/dist/components/index.js +133 -134
  50. package/dist/hooks/useGitHub.d.ts +7 -7
  51. package/dist/marketing/index.cjs +2 -2
  52. package/dist/marketing/index.js +2 -2
  53. package/dist/providers/EventBusProvider.d.ts +1 -1
  54. package/dist/providers/SelectionProvider.d.ts +1 -1
  55. package/dist/providers/ServerBridge.d.ts +1 -1
  56. package/dist/providers/index.cjs +260 -439
  57. package/dist/providers/index.css +3 -3
  58. package/dist/providers/index.js +261 -440
  59. package/dist/runtime/index.cjs +260 -439
  60. package/dist/runtime/index.css +3 -3
  61. package/dist/runtime/index.js +261 -440
  62. package/package.json +2 -2
@@ -6,7 +6,7 @@ import { createLogger, isLogLevelEnabled } from '@almadar/logger';
6
6
  import { clsx } from 'clsx';
7
7
  import { twMerge } from 'tailwind-merge';
8
8
  import * as LucideIcons2 from 'lucide-react';
9
- import { Loader2, X, Lightbulb, CheckCircle, List, Printer, ChevronRight, ChevronLeft, GitBranch, Pencil, Eye, Plus, ArrowRight, Trash, Code, FileText, WrapText, Check, Copy, RotateCcw, Play, Terminal, XCircle, AlertTriangle, Trash2, Link2, ZoomOut, ZoomIn, Download, Menu as Menu$1, Package, Calendar, MoreHorizontal, Image as Image$1, Upload, ArrowLeft, HelpCircle, PauseCircle, Search, Type, Heading1, Heading2, Heading3, ListOrdered, Quote, Minus, Eraser, TrendingUp, TrendingDown, AlertCircle, Circle, Clock, CheckCircle2, Bug, Send, ChevronUp, ChevronDown, Wrench, Tag, User, DollarSign } from 'lucide-react';
9
+ import { Loader2, X, Lightbulb, CheckCircle, List, Printer, ChevronRight, ChevronLeft, GitBranch, Pencil, Eye, Plus, ArrowRight, Trash, Code, FileText, WrapText, Check, Copy, RotateCcw, Play, Terminal, XCircle, AlertTriangle, Trash2, Link2, ZoomOut, ZoomIn, Download, ChevronDown, Menu as Menu$1, Package, Calendar, MoreHorizontal, Image as Image$1, Upload, ArrowLeft, HelpCircle, PauseCircle, Search, Type, Heading1, Heading2, Heading3, ListOrdered, Quote, Minus, Eraser, TrendingUp, TrendingDown, AlertCircle, Circle, Clock, CheckCircle2, Bug, Send, ChevronUp, Wrench, Tag, User, DollarSign } from 'lucide-react';
10
10
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
11
11
  import { createPortal } from 'react-dom';
12
12
  import { useTranslate } from '@almadar/ui/hooks';
@@ -12455,318 +12455,14 @@ var init_useCanvasEffects = __esm({
12455
12455
  "use client";
12456
12456
  }
12457
12457
  });
12458
- function pickPath(entry) {
12459
- if (Array.isArray(entry.path)) {
12460
- return entry.path[Math.floor(Math.random() * entry.path.length)];
12461
- }
12462
- return entry.path;
12463
- }
12464
- function useGameAudio({
12465
- manifest,
12466
- baseUrl = "",
12467
- initialMuted = false,
12468
- initialVolume = 1
12469
- }) {
12470
- const [muted, setMutedState] = useState(initialMuted);
12471
- const [masterVolume, setMasterVolumeState] = useState(initialVolume);
12472
- const mutedRef = useRef(muted);
12473
- const volumeRef = useRef(masterVolume);
12474
- const manifestRef = useRef(manifest);
12475
- mutedRef.current = muted;
12476
- volumeRef.current = masterVolume;
12477
- manifestRef.current = manifest;
12478
- const poolsRef = useRef(/* @__PURE__ */ new Map());
12479
- const getOrCreateElement = useCallback((key) => {
12480
- const entry = manifestRef.current[key];
12481
- if (!entry) return null;
12482
- let pool = poolsRef.current.get(key);
12483
- if (!pool) {
12484
- pool = [];
12485
- poolsRef.current.set(key, pool);
12486
- }
12487
- const maxSize = entry.poolSize ?? 1;
12488
- for (const audio of pool) {
12489
- if (audio.paused && (audio.ended || audio.currentTime === 0)) {
12490
- return audio;
12491
- }
12492
- }
12493
- if (pool.length < maxSize) {
12494
- const src = baseUrl + pickPath(entry);
12495
- const audio = new Audio(src);
12496
- audio.loop = entry.loop ?? false;
12497
- pool.push(audio);
12498
- return audio;
12499
- }
12500
- if (!entry.loop) {
12501
- let oldest = pool[0];
12502
- for (const audio of pool) {
12503
- if (audio.currentTime > oldest.currentTime) {
12504
- oldest = audio;
12505
- }
12506
- }
12507
- oldest.pause();
12508
- oldest.currentTime = 0;
12509
- return oldest;
12510
- }
12511
- return null;
12512
- }, [baseUrl]);
12513
- const play = useCallback((key) => {
12514
- if (mutedRef.current) return;
12515
- const entry = manifestRef.current[key];
12516
- if (!entry) return;
12517
- const audio = getOrCreateElement(key);
12518
- if (!audio) return;
12519
- audio.volume = Math.min(1, (entry.volume ?? 1) * volumeRef.current);
12520
- if (!entry.loop) {
12521
- audio.currentTime = 0;
12522
- }
12523
- const promise = audio.play();
12524
- if (promise) {
12525
- promise.catch(() => {
12526
- });
12527
- }
12528
- }, [getOrCreateElement]);
12529
- const stop = useCallback((key) => {
12530
- const pool = poolsRef.current.get(key);
12531
- if (!pool) return;
12532
- for (const audio of pool) {
12533
- audio.pause();
12534
- audio.currentTime = 0;
12535
- }
12536
- }, []);
12537
- const currentMusicKeyRef = useRef(null);
12538
- const currentMusicElRef = useRef(null);
12539
- const musicFadeRef = useRef(null);
12540
- const pendingMusicKeyRef = useRef(null);
12541
- const clearMusicFade = useCallback(() => {
12542
- if (musicFadeRef.current) {
12543
- clearInterval(musicFadeRef.current);
12544
- musicFadeRef.current = null;
12545
- }
12546
- }, []);
12547
- const playMusic = useCallback((key) => {
12548
- if (key === currentMusicKeyRef.current) return;
12549
- pendingMusicKeyRef.current = key;
12550
- const entry = manifestRef.current[key];
12551
- if (!entry) return;
12552
- const fadeDurationMs = entry.crossfadeDurationMs ?? 1500;
12553
- const stepMs = 50;
12554
- const totalSteps = Math.max(1, fadeDurationMs / stepMs);
12555
- const targetVolume = Math.min(1, (entry.volume ?? 1) * volumeRef.current);
12556
- clearMusicFade();
12557
- const src = baseUrl + (Array.isArray(entry.path) ? entry.path[0] : entry.path);
12558
- const incoming = new Audio(src);
12559
- incoming.loop = true;
12560
- incoming.volume = 0;
12561
- const outgoing = currentMusicElRef.current;
12562
- const outgoingStartVol = outgoing?.volume ?? 0;
12563
- currentMusicKeyRef.current = key;
12564
- currentMusicElRef.current = incoming;
12565
- if (!mutedRef.current) {
12566
- incoming.play().catch(() => {
12567
- currentMusicKeyRef.current = null;
12568
- currentMusicElRef.current = outgoing;
12569
- });
12570
- }
12571
- let step = 0;
12572
- musicFadeRef.current = setInterval(() => {
12573
- step++;
12574
- const progress = Math.min(step / totalSteps, 1);
12575
- incoming.volume = Math.min(1, targetVolume * progress);
12576
- if (outgoing) {
12577
- outgoing.volume = Math.max(0, outgoingStartVol * (1 - progress));
12578
- }
12579
- if (progress >= 1) {
12580
- clearMusicFade();
12581
- if (outgoing) {
12582
- outgoing.pause();
12583
- outgoing.src = "";
12584
- }
12585
- }
12586
- }, stepMs);
12587
- }, [baseUrl, clearMusicFade]);
12588
- const stopMusic = useCallback((fadeDurationMs = 1e3) => {
12589
- const outgoing = currentMusicElRef.current;
12590
- if (!outgoing) return;
12591
- currentMusicKeyRef.current = null;
12592
- currentMusicElRef.current = null;
12593
- pendingMusicKeyRef.current = null;
12594
- clearMusicFade();
12595
- const startVolume = outgoing.volume;
12596
- const stepMs = 50;
12597
- const totalSteps = Math.max(1, fadeDurationMs / stepMs);
12598
- let step = 0;
12599
- musicFadeRef.current = setInterval(() => {
12600
- step++;
12601
- const progress = step / totalSteps;
12602
- outgoing.volume = Math.max(0, startVolume * (1 - progress));
12603
- if (progress >= 1) {
12604
- clearMusicFade();
12605
- outgoing.pause();
12606
- outgoing.src = "";
12607
- }
12608
- }, stepMs);
12609
- }, [clearMusicFade]);
12610
- const stopAll = useCallback(() => {
12611
- for (const pool of poolsRef.current.values()) {
12612
- for (const audio of pool) {
12613
- audio.pause();
12614
- audio.currentTime = 0;
12615
- }
12616
- }
12617
- stopMusic(0);
12618
- }, [stopMusic]);
12619
- const setMuted = useCallback((value) => {
12620
- setMutedState(value);
12621
- if (value) {
12622
- for (const [key, pool] of poolsRef.current.entries()) {
12623
- if (manifestRef.current[key]?.loop) {
12624
- for (const audio of pool) {
12625
- if (!audio.paused) audio.pause();
12626
- }
12627
- }
12628
- }
12629
- currentMusicElRef.current?.pause();
12630
- } else {
12631
- for (const [key, pool] of poolsRef.current.entries()) {
12632
- const entry = manifestRef.current[key];
12633
- if (entry?.loop && entry?.autostart) {
12634
- for (const audio of pool) {
12635
- if (audio.paused) audio.play().catch(() => {
12636
- });
12637
- }
12638
- }
12639
- }
12640
- const musicEl = currentMusicElRef.current;
12641
- if (musicEl) {
12642
- musicEl.play().catch(() => {
12643
- });
12644
- }
12645
- }
12646
- }, []);
12647
- const setMasterVolume = useCallback((volume) => {
12648
- const clamped = Math.max(0, Math.min(1, volume));
12649
- setMasterVolumeState(clamped);
12650
- for (const [key, pool] of poolsRef.current.entries()) {
12651
- const entryVol = manifestRef.current[key]?.volume ?? 1;
12652
- for (const audio of pool) {
12653
- audio.volume = Math.min(1, entryVol * clamped);
12654
- }
12655
- }
12656
- if (!musicFadeRef.current && currentMusicElRef.current) {
12657
- const key = currentMusicKeyRef.current;
12658
- const entryVol = key ? manifestRef.current[key]?.volume ?? 1 : 1;
12659
- currentMusicElRef.current.volume = Math.min(1, entryVol * clamped);
12660
- }
12661
- }, []);
12662
- const unlockedRef = useRef(false);
12663
- useEffect(() => {
12664
- const autoKeys = Object.keys(manifest).filter((k) => manifest[k].autostart);
12665
- const hasPendingMusic = () => pendingMusicKeyRef.current !== null;
12666
- const hasAutoStart = autoKeys.length > 0;
12667
- if (!hasAutoStart && !hasPendingMusic()) return;
12668
- const unlock = () => {
12669
- if (unlockedRef.current) return;
12670
- unlockedRef.current = true;
12671
- if (!mutedRef.current) {
12672
- for (const key of autoKeys) {
12673
- play(key);
12674
- }
12675
- const pending = pendingMusicKeyRef.current;
12676
- if (pending && pending !== currentMusicKeyRef.current) {
12677
- playMusic(pending);
12678
- }
12679
- }
12680
- };
12681
- document.addEventListener("click", unlock, { once: true });
12682
- document.addEventListener("keydown", unlock, { once: true });
12683
- document.addEventListener("touchstart", unlock, { once: true });
12684
- return () => {
12685
- document.removeEventListener("click", unlock);
12686
- document.removeEventListener("keydown", unlock);
12687
- document.removeEventListener("touchstart", unlock);
12688
- };
12689
- }, [manifest, play, playMusic]);
12690
- useEffect(() => {
12691
- return () => {
12692
- clearMusicFade();
12693
- for (const pool of poolsRef.current.values()) {
12694
- for (const audio of pool) {
12695
- audio.pause();
12696
- audio.src = "";
12697
- }
12698
- }
12699
- poolsRef.current.clear();
12700
- if (currentMusicElRef.current) {
12701
- currentMusicElRef.current.pause();
12702
- currentMusicElRef.current.src = "";
12703
- currentMusicElRef.current = null;
12704
- }
12705
- };
12706
- }, [clearMusicFade]);
12707
- return {
12708
- play,
12709
- stop,
12710
- stopAll,
12711
- playMusic,
12712
- stopMusic,
12713
- muted,
12714
- setMuted,
12715
- masterVolume,
12716
- setMasterVolume
12717
- };
12718
- }
12719
12458
  var init_useGameAudio = __esm({
12720
12459
  "components/game/shared/hooks/useGameAudio.ts"() {
12721
12460
  "use client";
12722
- useGameAudio.displayName = "useGameAudio";
12723
12461
  }
12724
12462
  });
12725
12463
  function useGameAudioContextOptional() {
12726
12464
  return useContext(GameAudioContext);
12727
12465
  }
12728
- function GameAudioProvider({
12729
- manifest,
12730
- baseUrl = "",
12731
- children,
12732
- initialMuted = false
12733
- }) {
12734
- const eventBus = useEventBus();
12735
- const { play, stop, stopAll, playMusic, stopMusic, muted, setMuted, masterVolume, setMasterVolume } = useGameAudio({ manifest, baseUrl, initialMuted });
12736
- useEffect(() => {
12737
- const unsubPlay = eventBus.on("UI:PLAY_SOUND", (event) => {
12738
- const key = event.payload?.key;
12739
- if (key) play(key);
12740
- });
12741
- const unsubStop = eventBus.on("UI:STOP_SOUND", (event) => {
12742
- const key = event.payload?.key;
12743
- if (key) {
12744
- stop(key);
12745
- } else {
12746
- stopAll();
12747
- }
12748
- });
12749
- const unsubChangeMusic = eventBus.on("UI:CHANGE_MUSIC", (event) => {
12750
- const key = event.payload?.key;
12751
- if (key) {
12752
- playMusic(key);
12753
- } else {
12754
- stopMusic();
12755
- }
12756
- });
12757
- const unsubStopMusic = eventBus.on("UI:STOP_MUSIC", () => {
12758
- stopMusic();
12759
- });
12760
- return () => {
12761
- unsubPlay();
12762
- unsubStop();
12763
- unsubChangeMusic();
12764
- unsubStopMusic();
12765
- };
12766
- }, [eventBus, play, stop, stopAll, playMusic, stopMusic]);
12767
- const value = { muted, setMuted, masterVolume, setMasterVolume, play, playMusic, stopMusic };
12768
- return /* @__PURE__ */ jsx(GameAudioContext.Provider, { value, children });
12769
- }
12770
12466
  var GameAudioContext;
12771
12467
  var init_GameAudioProvider = __esm({
12772
12468
  "components/game/shared/providers/GameAudioProvider.tsx"() {
@@ -12775,7 +12471,6 @@ var init_GameAudioProvider = __esm({
12775
12471
  init_useGameAudio();
12776
12472
  GameAudioContext = createContext(null);
12777
12473
  GameAudioContext.displayName = "GameAudioContext";
12778
- GameAudioProvider.displayName = "GameAudioProvider";
12779
12474
  }
12780
12475
  });
12781
12476
  function GameAudioToggle({
@@ -22950,9 +22645,9 @@ var init_BehaviorView = __esm({
22950
22645
  }
22951
22646
  });
22952
22647
 
22953
- // node_modules/.pnpm/katex@0.16.47/node_modules/katex/dist/katex.min.css
22648
+ // node_modules/katex/dist/katex.min.css
22954
22649
  var init_katex_min = __esm({
22955
- "node_modules/.pnpm/katex@0.16.47/node_modules/katex/dist/katex.min.css"() {
22650
+ "node_modules/katex/dist/katex.min.css"() {
22956
22651
  }
22957
22652
  });
22958
22653
  var Tabs;
@@ -27295,129 +26990,6 @@ var init_Breadcrumb = __esm({
27295
26990
  Breadcrumb.displayName = "Breadcrumb";
27296
26991
  }
27297
26992
  });
27298
- function useSafeEventBus2() {
27299
- try {
27300
- return useEventBus();
27301
- } catch {
27302
- return { emit: () => {
27303
- }, on: () => () => {
27304
- }, once: () => {
27305
- } };
27306
- }
27307
- }
27308
- var log6, lookStyles4, ButtonGroup;
27309
- var init_ButtonGroup = __esm({
27310
- "components/core/molecules/ButtonGroup.tsx"() {
27311
- "use client";
27312
- init_cn();
27313
- init_atoms();
27314
- init_useEventBus();
27315
- log6 = createLogger("almadar:ui:button-group");
27316
- lookStyles4 = {
27317
- "right-aligned-buttons": "",
27318
- "floating-bar": "fixed bottom-section left-1/2 -translate-x-1/2 shadow-elevation-toast bg-card p-card-sm rounded-container",
27319
- "inline-row": "gap-2 inline-flex",
27320
- "dropdown-menu": "[&>button:not(:first-child)]:hidden",
27321
- "command-palette-trigger": "[&>button:not(:first-child)]:hidden"
27322
- };
27323
- ButtonGroup = ({
27324
- children,
27325
- primary,
27326
- secondary,
27327
- variant = "default",
27328
- orientation = "horizontal",
27329
- className,
27330
- // Filter-group pattern props (entity and filters are used for schema-driven filtering)
27331
- entity: _entity,
27332
- filters,
27333
- look = "right-aligned-buttons"
27334
- }) => {
27335
- const eventBus = useSafeEventBus2();
27336
- const variantClasses2 = {
27337
- default: "gap-0",
27338
- segmented: "gap-0 [&>button]:rounded-none [&>button:first-child]:rounded-l-lg [&>button:last-child]:rounded-r-lg [&>button:not(:first-child)]:border-l-0",
27339
- toggle: "gap-0 [&>button]:rounded-none [&>button:first-child]:rounded-l-lg [&>button:last-child]:rounded-r-lg [&>button:not(:first-child)]:border-l-0"
27340
- };
27341
- const orientationClasses = {
27342
- horizontal: "flex-row",
27343
- vertical: "flex-col [&>button:first-child]:rounded-t-lg [&>button:last-child]:rounded-b-lg [&>button:not(:first-child)]:border-t-0 [&>button:not(:first-child)]:border-l"
27344
- };
27345
- const handleActionClick = (action) => {
27346
- if (action.event) {
27347
- eventBus.emit("UI:DISPATCH", { event: action.event });
27348
- }
27349
- if (action.navigatesTo) {
27350
- eventBus.emit("UI:NAVIGATE", { url: action.navigatesTo });
27351
- }
27352
- };
27353
- const renderFormActions = () => {
27354
- const buttons = [];
27355
- if (secondary) {
27356
- secondary.forEach((action, index) => {
27357
- buttons.push(
27358
- /* @__PURE__ */ jsx(
27359
- Button,
27360
- {
27361
- type: action.actionType === "submit" ? "submit" : "button",
27362
- variant: action.variant || "ghost",
27363
- onClick: () => handleActionClick(action),
27364
- children: action.label
27365
- },
27366
- `secondary-${index}`
27367
- )
27368
- );
27369
- });
27370
- }
27371
- if (primary) {
27372
- const isSubmit = primary.actionType === "submit";
27373
- buttons.push(
27374
- /* @__PURE__ */ jsx(
27375
- Button,
27376
- {
27377
- type: isSubmit ? "submit" : "button",
27378
- variant: primary.variant || "primary",
27379
- onClick: () => handleActionClick(primary),
27380
- "data-testid": isSubmit ? "form-submit" : void 0,
27381
- children: primary.label
27382
- },
27383
- "primary"
27384
- )
27385
- );
27386
- }
27387
- return buttons;
27388
- };
27389
- const renderFilters = () => {
27390
- if (!filters || filters.length === 0) return null;
27391
- return filters.map((filter, index) => /* @__PURE__ */ jsx(
27392
- Button,
27393
- {
27394
- variant: "ghost",
27395
- onClick: () => {
27396
- log6.debug("Filter clicked", { field: filter.field });
27397
- },
27398
- children: filter.label
27399
- },
27400
- `filter-${filter.field}-${index}`
27401
- ));
27402
- };
27403
- return /* @__PURE__ */ jsx(
27404
- "div",
27405
- {
27406
- className: cn(
27407
- "inline-flex gap-2",
27408
- variantClasses2[variant],
27409
- orientationClasses[orientation],
27410
- lookStyles4[look],
27411
- className
27412
- ),
27413
- role: "group",
27414
- children: children || renderFilters() || renderFormActions()
27415
- }
27416
- );
27417
- };
27418
- ButtonGroup.displayName = "ButtonGroup";
27419
- }
27420
- });
27421
26993
  function dayWindowForViewport(width) {
27422
26994
  if (width <= 640) return 1;
27423
26995
  if (width <= 1024) return 3;
@@ -28160,7 +27732,7 @@ var init_CardGrid = __esm({
28160
27732
  CardGrid.displayName = "CardGrid";
28161
27733
  }
28162
27734
  });
28163
- function useSafeEventBus3() {
27735
+ function useSafeEventBus2() {
28164
27736
  try {
28165
27737
  return useEventBus();
28166
27738
  } catch {
@@ -28196,7 +27768,7 @@ var init_Carousel = __esm({
28196
27768
  const [activeIndex, setActiveIndex] = useState(0);
28197
27769
  const scrollRef = useRef(null);
28198
27770
  const autoPlayRef = useRef(null);
28199
- const eventBus = useSafeEventBus3();
27771
+ const eventBus = useSafeEventBus2();
28200
27772
  const { t } = useTranslate();
28201
27773
  const safeItems = items ?? [];
28202
27774
  const totalSlides = safeItems.length;
@@ -31518,7 +31090,7 @@ function DataGrid({
31518
31090
  /* @__PURE__ */ jsx(
31519
31091
  Box,
31520
31092
  {
31521
- className: cn("grid", gapStyles5[gap], scrollX ? "grid-flow-col overflow-x-auto" : colsClass, lookStyles5[look], className),
31093
+ className: cn("grid", gapStyles5[gap], scrollX ? "grid-flow-col overflow-x-auto" : colsClass, lookStyles4[look], className),
31522
31094
  style: scrollX ? { gridAutoFlow: "column", gridAutoColumns: `minmax(${minCardWidth}px, 1fr)` } : gridTemplateColumns ? { gridTemplateColumns } : void 0,
31523
31095
  children: data.map((item, index) => {
31524
31096
  const itemData = item;
@@ -31713,7 +31285,7 @@ function DataGrid({
31713
31285
  ] })
31714
31286
  );
31715
31287
  }
31716
- var dataGridLog, BADGE_VARIANTS, gapStyles5, lookStyles5;
31288
+ var dataGridLog, BADGE_VARIANTS, gapStyles5, lookStyles4;
31717
31289
  var init_DataGrid = __esm({
31718
31290
  "components/core/molecules/DataGrid.tsx"() {
31719
31291
  "use client";
@@ -31748,7 +31320,7 @@ var init_DataGrid = __esm({
31748
31320
  lg: "gap-6",
31749
31321
  xl: "gap-8"
31750
31322
  };
31751
- lookStyles5 = {
31323
+ lookStyles4 = {
31752
31324
  dense: "gap-2 [&>*]:p-card-sm",
31753
31325
  spacious: "gap-8 [&>*]:p-card-lg",
31754
31326
  striped: "[&>*:nth-child(even)]:bg-muted/30",
@@ -32175,6 +31747,133 @@ var init_DataList = __esm({
32175
31747
  DataList.displayName = "DataList";
32176
31748
  }
32177
31749
  });
31750
+ var FormSection, FormLayout, FormActions;
31751
+ var init_FormSection = __esm({
31752
+ "components/core/molecules/FormSection.tsx"() {
31753
+ "use client";
31754
+ init_cn();
31755
+ init_atoms();
31756
+ init_Box();
31757
+ init_Typography();
31758
+ init_Button();
31759
+ init_Stack();
31760
+ init_Icon();
31761
+ init_useEventBus();
31762
+ FormSection = ({
31763
+ title,
31764
+ description,
31765
+ children,
31766
+ collapsible = false,
31767
+ defaultCollapsed = false,
31768
+ card = false,
31769
+ columns = 1,
31770
+ className
31771
+ }) => {
31772
+ const [collapsed, setCollapsed] = React105__default.useState(defaultCollapsed);
31773
+ const { t } = useTranslate();
31774
+ const eventBus = useEventBus();
31775
+ const gridClass = {
31776
+ 1: "grid-cols-1",
31777
+ 2: "grid-cols-1 md:grid-cols-2",
31778
+ 3: "grid-cols-1 md:grid-cols-2 lg:grid-cols-3"
31779
+ }[columns];
31780
+ React105__default.useCallback(() => {
31781
+ if (collapsible) {
31782
+ setCollapsed((prev) => !prev);
31783
+ eventBus.emit("UI:TOGGLE_COLLAPSE", { collapsed: !collapsed });
31784
+ }
31785
+ }, [collapsible, collapsed, eventBus]);
31786
+ const content = /* @__PURE__ */ jsxs(Fragment, { children: [
31787
+ (title || description) && /* @__PURE__ */ jsxs(VStack, { gap: "xs", className: "mb-4", children: [
31788
+ title && /* @__PURE__ */ jsxs(
31789
+ HStack,
31790
+ {
31791
+ justify: "between",
31792
+ align: "center",
31793
+ className: cn(collapsible && "cursor-pointer"),
31794
+ action: collapsible ? "TOGGLE_COLLAPSE" : void 0,
31795
+ children: [
31796
+ /* @__PURE__ */ jsx(Typography, { variant: "h3", weight: "semibold", children: title }),
31797
+ collapsible && /* @__PURE__ */ jsx(
31798
+ Button,
31799
+ {
31800
+ variant: "ghost",
31801
+ size: "sm",
31802
+ action: "TOGGLE_COLLAPSE",
31803
+ children: /* @__PURE__ */ jsx(
31804
+ Icon,
31805
+ {
31806
+ icon: ChevronDown,
31807
+ size: "sm",
31808
+ className: cn(
31809
+ "text-muted-foreground transition-transform",
31810
+ collapsed && "rotate-180"
31811
+ )
31812
+ }
31813
+ )
31814
+ }
31815
+ )
31816
+ ]
31817
+ }
31818
+ ),
31819
+ description && /* @__PURE__ */ jsx(Typography, { variant: "small", color: "secondary", children: description })
31820
+ ] }),
31821
+ (!collapsible || !collapsed) && /* @__PURE__ */ jsx(Box, { className: cn("grid gap-4", gridClass), children })
31822
+ ] });
31823
+ if (card) {
31824
+ return /* @__PURE__ */ jsx(Card, { className: cn("p-6", className), children: content });
31825
+ }
31826
+ return /* @__PURE__ */ jsx(Box, { className, children: content });
31827
+ };
31828
+ FormSection.displayName = "FormSection";
31829
+ FormLayout = ({
31830
+ children,
31831
+ dividers = true,
31832
+ className
31833
+ }) => {
31834
+ return /* @__PURE__ */ jsx(
31835
+ VStack,
31836
+ {
31837
+ gap: "lg",
31838
+ className: cn(
31839
+ dividers && "[&>*+*]:pt-8 [&>*+*]:border-t [&>*+*]:border-border",
31840
+ className
31841
+ ),
31842
+ children
31843
+ }
31844
+ );
31845
+ };
31846
+ FormLayout.displayName = "FormLayout";
31847
+ FormActions = ({
31848
+ children,
31849
+ sticky = false,
31850
+ align = "right",
31851
+ className
31852
+ }) => {
31853
+ const alignClass2 = {
31854
+ left: "justify-start",
31855
+ right: "justify-end",
31856
+ between: "justify-between",
31857
+ center: "justify-center"
31858
+ }[align];
31859
+ return /* @__PURE__ */ jsx(
31860
+ HStack,
31861
+ {
31862
+ gap: "sm",
31863
+ align: "center",
31864
+ className: cn(
31865
+ "pt-6 border-t border-border",
31866
+ alignClass2,
31867
+ sticky && "sticky bottom-0 bg-card py-4 -mx-6 px-6 shadow-[0_-4px_6px_-1px_rgb(0,0,0,0.05)]",
31868
+ className
31869
+ ),
31870
+ children
31871
+ }
31872
+ );
31873
+ };
31874
+ FormActions.displayName = "FormActions";
31875
+ }
31876
+ });
32178
31877
  function fileIcon(name) {
32179
31878
  const ext = name.split(".").pop()?.toLowerCase() ?? "";
32180
31879
  switch (ext) {
@@ -32336,6 +32035,129 @@ var init_FormField = __esm({
32336
32035
  FormField.displayName = "FormField";
32337
32036
  }
32338
32037
  });
32038
+ function useSafeEventBus3() {
32039
+ try {
32040
+ return useEventBus();
32041
+ } catch {
32042
+ return { emit: () => {
32043
+ }, on: () => () => {
32044
+ }, once: () => {
32045
+ } };
32046
+ }
32047
+ }
32048
+ var log6, lookStyles5, ButtonGroup;
32049
+ var init_ButtonGroup = __esm({
32050
+ "components/core/molecules/ButtonGroup.tsx"() {
32051
+ "use client";
32052
+ init_cn();
32053
+ init_atoms();
32054
+ init_useEventBus();
32055
+ log6 = createLogger("almadar:ui:button-group");
32056
+ lookStyles5 = {
32057
+ "right-aligned-buttons": "",
32058
+ "floating-bar": "fixed bottom-section left-1/2 -translate-x-1/2 shadow-elevation-toast bg-card p-card-sm rounded-container",
32059
+ "inline-row": "gap-2 inline-flex",
32060
+ "dropdown-menu": "[&>button:not(:first-child)]:hidden",
32061
+ "command-palette-trigger": "[&>button:not(:first-child)]:hidden"
32062
+ };
32063
+ ButtonGroup = ({
32064
+ children,
32065
+ primary,
32066
+ secondary,
32067
+ variant = "default",
32068
+ orientation = "horizontal",
32069
+ className,
32070
+ // Filter-group pattern props (entity and filters are used for schema-driven filtering)
32071
+ entity: _entity,
32072
+ filters,
32073
+ look = "right-aligned-buttons"
32074
+ }) => {
32075
+ const eventBus = useSafeEventBus3();
32076
+ const variantClasses2 = {
32077
+ default: "gap-0",
32078
+ segmented: "gap-0 [&>button]:rounded-none [&>button:first-child]:rounded-l-lg [&>button:last-child]:rounded-r-lg [&>button:not(:first-child)]:border-l-0",
32079
+ toggle: "gap-0 [&>button]:rounded-none [&>button:first-child]:rounded-l-lg [&>button:last-child]:rounded-r-lg [&>button:not(:first-child)]:border-l-0"
32080
+ };
32081
+ const orientationClasses = {
32082
+ horizontal: "flex-row",
32083
+ vertical: "flex-col [&>button:first-child]:rounded-t-lg [&>button:last-child]:rounded-b-lg [&>button:not(:first-child)]:border-t-0 [&>button:not(:first-child)]:border-l"
32084
+ };
32085
+ const handleActionClick = (action) => {
32086
+ if (action.event) {
32087
+ eventBus.emit("UI:DISPATCH", { event: action.event });
32088
+ }
32089
+ if (action.navigatesTo) {
32090
+ eventBus.emit("UI:NAVIGATE", { url: action.navigatesTo });
32091
+ }
32092
+ };
32093
+ const renderFormActions = () => {
32094
+ const buttons = [];
32095
+ if (secondary) {
32096
+ secondary.forEach((action, index) => {
32097
+ buttons.push(
32098
+ /* @__PURE__ */ jsx(
32099
+ Button,
32100
+ {
32101
+ type: action.actionType === "submit" ? "submit" : "button",
32102
+ variant: action.variant || "ghost",
32103
+ onClick: () => handleActionClick(action),
32104
+ children: action.label
32105
+ },
32106
+ `secondary-${index}`
32107
+ )
32108
+ );
32109
+ });
32110
+ }
32111
+ if (primary) {
32112
+ const isSubmit = primary.actionType === "submit";
32113
+ buttons.push(
32114
+ /* @__PURE__ */ jsx(
32115
+ Button,
32116
+ {
32117
+ type: isSubmit ? "submit" : "button",
32118
+ variant: primary.variant || "primary",
32119
+ onClick: () => handleActionClick(primary),
32120
+ "data-testid": isSubmit ? "form-submit" : void 0,
32121
+ children: primary.label
32122
+ },
32123
+ "primary"
32124
+ )
32125
+ );
32126
+ }
32127
+ return buttons;
32128
+ };
32129
+ const renderFilters = () => {
32130
+ if (!filters || filters.length === 0) return null;
32131
+ return filters.map((filter, index) => /* @__PURE__ */ jsx(
32132
+ Button,
32133
+ {
32134
+ variant: "ghost",
32135
+ onClick: () => {
32136
+ log6.debug("Filter clicked", { field: filter.field });
32137
+ },
32138
+ children: filter.label
32139
+ },
32140
+ `filter-${filter.field}-${index}`
32141
+ ));
32142
+ };
32143
+ return /* @__PURE__ */ jsx(
32144
+ "div",
32145
+ {
32146
+ className: cn(
32147
+ "inline-flex gap-2",
32148
+ variantClasses2[variant],
32149
+ orientationClasses[orientation],
32150
+ lookStyles5[look],
32151
+ className
32152
+ ),
32153
+ role: "group",
32154
+ children: children || renderFilters() || renderFormActions()
32155
+ }
32156
+ );
32157
+ };
32158
+ ButtonGroup.displayName = "ButtonGroup";
32159
+ }
32160
+ });
32339
32161
  var resolveFilterType, lookStyles6, FilterGroup;
32340
32162
  var init_FilterGroup = __esm({
32341
32163
  "components/core/molecules/FilterGroup.tsx"() {
@@ -50713,7 +50535,6 @@ var init_component_registry_generated = __esm({
50713
50535
  init_BranchingLogicBuilder();
50714
50536
  init_Breadcrumb();
50715
50537
  init_BuilderBoard();
50716
- init_ButtonGroup();
50717
50538
  init_CTABanner();
50718
50539
  init_CalendarGrid();
50719
50540
  init_Canvas2D();
@@ -50790,9 +50611,9 @@ var init_component_registry_generated = __esm({
50790
50611
  init_FlipContainer();
50791
50612
  init_FloatingActionButton();
50792
50613
  init_Form();
50614
+ init_FormSection();
50793
50615
  init_FormField();
50794
50616
  init_FormSectionHeader();
50795
- init_GameAudioProvider();
50796
50617
  init_GameAudioToggle();
50797
50618
  init_GameCard();
50798
50619
  init_GameHud();
@@ -51041,7 +50862,6 @@ var init_component_registry_generated = __esm({
51041
50862
  "Breadcrumb": Breadcrumb,
51042
50863
  "BuilderBoard": BuilderBoard,
51043
50864
  "Button": ButtonPattern,
51044
- "ButtonGroup": ButtonGroup,
51045
50865
  "ButtonPattern": ButtonPattern,
51046
50866
  "CTABanner": CTABanner,
51047
50867
  "CalendarGrid": CalendarGrid,
@@ -51121,9 +50941,10 @@ var init_component_registry_generated = __esm({
51121
50941
  "FlipContainer": FlipContainer,
51122
50942
  "FloatingActionButton": FloatingActionButton,
51123
50943
  "Form": Form,
50944
+ "FormActions": FormActions,
51124
50945
  "FormField": FormField,
50946
+ "FormLayout": FormLayout,
51125
50947
  "FormSectionHeader": FormSectionHeader,
51126
- "GameAudioProvider": GameAudioProvider,
51127
50948
  "GameAudioToggle": GameAudioToggle,
51128
50949
  "GameBoard3D": GameBoard3D,
51129
50950
  "GameCanvas3D": GameCanvas3D,