@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
@@ -5,7 +5,7 @@ import { createLogger, isLogLevelEnabled } from '@almadar/logger';
5
5
  import { clsx } from 'clsx';
6
6
  import { twMerge } from 'tailwind-merge';
7
7
  import * as LucideIcons2 from 'lucide-react';
8
- 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';
8
+ 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';
9
9
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
10
10
  import { createPortal } from 'react-dom';
11
11
  import { useTranslate } from '@almadar/ui/hooks';
@@ -12108,318 +12108,14 @@ var init_useCanvasEffects = __esm({
12108
12108
  "use client";
12109
12109
  }
12110
12110
  });
12111
- function pickPath(entry) {
12112
- if (Array.isArray(entry.path)) {
12113
- return entry.path[Math.floor(Math.random() * entry.path.length)];
12114
- }
12115
- return entry.path;
12116
- }
12117
- function useGameAudio({
12118
- manifest,
12119
- baseUrl = "",
12120
- initialMuted = false,
12121
- initialVolume = 1
12122
- }) {
12123
- const [muted, setMutedState] = useState(initialMuted);
12124
- const [masterVolume, setMasterVolumeState] = useState(initialVolume);
12125
- const mutedRef = useRef(muted);
12126
- const volumeRef = useRef(masterVolume);
12127
- const manifestRef = useRef(manifest);
12128
- mutedRef.current = muted;
12129
- volumeRef.current = masterVolume;
12130
- manifestRef.current = manifest;
12131
- const poolsRef = useRef(/* @__PURE__ */ new Map());
12132
- const getOrCreateElement = useCallback((key) => {
12133
- const entry = manifestRef.current[key];
12134
- if (!entry) return null;
12135
- let pool = poolsRef.current.get(key);
12136
- if (!pool) {
12137
- pool = [];
12138
- poolsRef.current.set(key, pool);
12139
- }
12140
- const maxSize = entry.poolSize ?? 1;
12141
- for (const audio of pool) {
12142
- if (audio.paused && (audio.ended || audio.currentTime === 0)) {
12143
- return audio;
12144
- }
12145
- }
12146
- if (pool.length < maxSize) {
12147
- const src = baseUrl + pickPath(entry);
12148
- const audio = new Audio(src);
12149
- audio.loop = entry.loop ?? false;
12150
- pool.push(audio);
12151
- return audio;
12152
- }
12153
- if (!entry.loop) {
12154
- let oldest = pool[0];
12155
- for (const audio of pool) {
12156
- if (audio.currentTime > oldest.currentTime) {
12157
- oldest = audio;
12158
- }
12159
- }
12160
- oldest.pause();
12161
- oldest.currentTime = 0;
12162
- return oldest;
12163
- }
12164
- return null;
12165
- }, [baseUrl]);
12166
- const play = useCallback((key) => {
12167
- if (mutedRef.current) return;
12168
- const entry = manifestRef.current[key];
12169
- if (!entry) return;
12170
- const audio = getOrCreateElement(key);
12171
- if (!audio) return;
12172
- audio.volume = Math.min(1, (entry.volume ?? 1) * volumeRef.current);
12173
- if (!entry.loop) {
12174
- audio.currentTime = 0;
12175
- }
12176
- const promise = audio.play();
12177
- if (promise) {
12178
- promise.catch(() => {
12179
- });
12180
- }
12181
- }, [getOrCreateElement]);
12182
- const stop = useCallback((key) => {
12183
- const pool = poolsRef.current.get(key);
12184
- if (!pool) return;
12185
- for (const audio of pool) {
12186
- audio.pause();
12187
- audio.currentTime = 0;
12188
- }
12189
- }, []);
12190
- const currentMusicKeyRef = useRef(null);
12191
- const currentMusicElRef = useRef(null);
12192
- const musicFadeRef = useRef(null);
12193
- const pendingMusicKeyRef = useRef(null);
12194
- const clearMusicFade = useCallback(() => {
12195
- if (musicFadeRef.current) {
12196
- clearInterval(musicFadeRef.current);
12197
- musicFadeRef.current = null;
12198
- }
12199
- }, []);
12200
- const playMusic = useCallback((key) => {
12201
- if (key === currentMusicKeyRef.current) return;
12202
- pendingMusicKeyRef.current = key;
12203
- const entry = manifestRef.current[key];
12204
- if (!entry) return;
12205
- const fadeDurationMs = entry.crossfadeDurationMs ?? 1500;
12206
- const stepMs = 50;
12207
- const totalSteps = Math.max(1, fadeDurationMs / stepMs);
12208
- const targetVolume = Math.min(1, (entry.volume ?? 1) * volumeRef.current);
12209
- clearMusicFade();
12210
- const src = baseUrl + (Array.isArray(entry.path) ? entry.path[0] : entry.path);
12211
- const incoming = new Audio(src);
12212
- incoming.loop = true;
12213
- incoming.volume = 0;
12214
- const outgoing = currentMusicElRef.current;
12215
- const outgoingStartVol = outgoing?.volume ?? 0;
12216
- currentMusicKeyRef.current = key;
12217
- currentMusicElRef.current = incoming;
12218
- if (!mutedRef.current) {
12219
- incoming.play().catch(() => {
12220
- currentMusicKeyRef.current = null;
12221
- currentMusicElRef.current = outgoing;
12222
- });
12223
- }
12224
- let step = 0;
12225
- musicFadeRef.current = setInterval(() => {
12226
- step++;
12227
- const progress = Math.min(step / totalSteps, 1);
12228
- incoming.volume = Math.min(1, targetVolume * progress);
12229
- if (outgoing) {
12230
- outgoing.volume = Math.max(0, outgoingStartVol * (1 - progress));
12231
- }
12232
- if (progress >= 1) {
12233
- clearMusicFade();
12234
- if (outgoing) {
12235
- outgoing.pause();
12236
- outgoing.src = "";
12237
- }
12238
- }
12239
- }, stepMs);
12240
- }, [baseUrl, clearMusicFade]);
12241
- const stopMusic = useCallback((fadeDurationMs = 1e3) => {
12242
- const outgoing = currentMusicElRef.current;
12243
- if (!outgoing) return;
12244
- currentMusicKeyRef.current = null;
12245
- currentMusicElRef.current = null;
12246
- pendingMusicKeyRef.current = null;
12247
- clearMusicFade();
12248
- const startVolume = outgoing.volume;
12249
- const stepMs = 50;
12250
- const totalSteps = Math.max(1, fadeDurationMs / stepMs);
12251
- let step = 0;
12252
- musicFadeRef.current = setInterval(() => {
12253
- step++;
12254
- const progress = step / totalSteps;
12255
- outgoing.volume = Math.max(0, startVolume * (1 - progress));
12256
- if (progress >= 1) {
12257
- clearMusicFade();
12258
- outgoing.pause();
12259
- outgoing.src = "";
12260
- }
12261
- }, stepMs);
12262
- }, [clearMusicFade]);
12263
- const stopAll = useCallback(() => {
12264
- for (const pool of poolsRef.current.values()) {
12265
- for (const audio of pool) {
12266
- audio.pause();
12267
- audio.currentTime = 0;
12268
- }
12269
- }
12270
- stopMusic(0);
12271
- }, [stopMusic]);
12272
- const setMuted = useCallback((value) => {
12273
- setMutedState(value);
12274
- if (value) {
12275
- for (const [key, pool] of poolsRef.current.entries()) {
12276
- if (manifestRef.current[key]?.loop) {
12277
- for (const audio of pool) {
12278
- if (!audio.paused) audio.pause();
12279
- }
12280
- }
12281
- }
12282
- currentMusicElRef.current?.pause();
12283
- } else {
12284
- for (const [key, pool] of poolsRef.current.entries()) {
12285
- const entry = manifestRef.current[key];
12286
- if (entry?.loop && entry?.autostart) {
12287
- for (const audio of pool) {
12288
- if (audio.paused) audio.play().catch(() => {
12289
- });
12290
- }
12291
- }
12292
- }
12293
- const musicEl = currentMusicElRef.current;
12294
- if (musicEl) {
12295
- musicEl.play().catch(() => {
12296
- });
12297
- }
12298
- }
12299
- }, []);
12300
- const setMasterVolume = useCallback((volume) => {
12301
- const clamped = Math.max(0, Math.min(1, volume));
12302
- setMasterVolumeState(clamped);
12303
- for (const [key, pool] of poolsRef.current.entries()) {
12304
- const entryVol = manifestRef.current[key]?.volume ?? 1;
12305
- for (const audio of pool) {
12306
- audio.volume = Math.min(1, entryVol * clamped);
12307
- }
12308
- }
12309
- if (!musicFadeRef.current && currentMusicElRef.current) {
12310
- const key = currentMusicKeyRef.current;
12311
- const entryVol = key ? manifestRef.current[key]?.volume ?? 1 : 1;
12312
- currentMusicElRef.current.volume = Math.min(1, entryVol * clamped);
12313
- }
12314
- }, []);
12315
- const unlockedRef = useRef(false);
12316
- useEffect(() => {
12317
- const autoKeys = Object.keys(manifest).filter((k) => manifest[k].autostart);
12318
- const hasPendingMusic = () => pendingMusicKeyRef.current !== null;
12319
- const hasAutoStart = autoKeys.length > 0;
12320
- if (!hasAutoStart && !hasPendingMusic()) return;
12321
- const unlock = () => {
12322
- if (unlockedRef.current) return;
12323
- unlockedRef.current = true;
12324
- if (!mutedRef.current) {
12325
- for (const key of autoKeys) {
12326
- play(key);
12327
- }
12328
- const pending = pendingMusicKeyRef.current;
12329
- if (pending && pending !== currentMusicKeyRef.current) {
12330
- playMusic(pending);
12331
- }
12332
- }
12333
- };
12334
- document.addEventListener("click", unlock, { once: true });
12335
- document.addEventListener("keydown", unlock, { once: true });
12336
- document.addEventListener("touchstart", unlock, { once: true });
12337
- return () => {
12338
- document.removeEventListener("click", unlock);
12339
- document.removeEventListener("keydown", unlock);
12340
- document.removeEventListener("touchstart", unlock);
12341
- };
12342
- }, [manifest, play, playMusic]);
12343
- useEffect(() => {
12344
- return () => {
12345
- clearMusicFade();
12346
- for (const pool of poolsRef.current.values()) {
12347
- for (const audio of pool) {
12348
- audio.pause();
12349
- audio.src = "";
12350
- }
12351
- }
12352
- poolsRef.current.clear();
12353
- if (currentMusicElRef.current) {
12354
- currentMusicElRef.current.pause();
12355
- currentMusicElRef.current.src = "";
12356
- currentMusicElRef.current = null;
12357
- }
12358
- };
12359
- }, [clearMusicFade]);
12360
- return {
12361
- play,
12362
- stop,
12363
- stopAll,
12364
- playMusic,
12365
- stopMusic,
12366
- muted,
12367
- setMuted,
12368
- masterVolume,
12369
- setMasterVolume
12370
- };
12371
- }
12372
12111
  var init_useGameAudio = __esm({
12373
12112
  "components/game/shared/hooks/useGameAudio.ts"() {
12374
12113
  "use client";
12375
- useGameAudio.displayName = "useGameAudio";
12376
12114
  }
12377
12115
  });
12378
12116
  function useGameAudioContextOptional() {
12379
12117
  return useContext(GameAudioContext);
12380
12118
  }
12381
- function GameAudioProvider({
12382
- manifest,
12383
- baseUrl = "",
12384
- children,
12385
- initialMuted = false
12386
- }) {
12387
- const eventBus = useEventBus();
12388
- const { play, stop, stopAll, playMusic, stopMusic, muted, setMuted, masterVolume, setMasterVolume } = useGameAudio({ manifest, baseUrl, initialMuted });
12389
- useEffect(() => {
12390
- const unsubPlay = eventBus.on("UI:PLAY_SOUND", (event) => {
12391
- const key = event.payload?.key;
12392
- if (key) play(key);
12393
- });
12394
- const unsubStop = eventBus.on("UI:STOP_SOUND", (event) => {
12395
- const key = event.payload?.key;
12396
- if (key) {
12397
- stop(key);
12398
- } else {
12399
- stopAll();
12400
- }
12401
- });
12402
- const unsubChangeMusic = eventBus.on("UI:CHANGE_MUSIC", (event) => {
12403
- const key = event.payload?.key;
12404
- if (key) {
12405
- playMusic(key);
12406
- } else {
12407
- stopMusic();
12408
- }
12409
- });
12410
- const unsubStopMusic = eventBus.on("UI:STOP_MUSIC", () => {
12411
- stopMusic();
12412
- });
12413
- return () => {
12414
- unsubPlay();
12415
- unsubStop();
12416
- unsubChangeMusic();
12417
- unsubStopMusic();
12418
- };
12419
- }, [eventBus, play, stop, stopAll, playMusic, stopMusic]);
12420
- const value = { muted, setMuted, masterVolume, setMasterVolume, play, playMusic, stopMusic };
12421
- return /* @__PURE__ */ jsx(GameAudioContext.Provider, { value, children });
12422
- }
12423
12119
  var GameAudioContext;
12424
12120
  var init_GameAudioProvider = __esm({
12425
12121
  "components/game/shared/providers/GameAudioProvider.tsx"() {
@@ -12428,7 +12124,6 @@ var init_GameAudioProvider = __esm({
12428
12124
  init_useGameAudio();
12429
12125
  GameAudioContext = createContext(null);
12430
12126
  GameAudioContext.displayName = "GameAudioContext";
12431
- GameAudioProvider.displayName = "GameAudioProvider";
12432
12127
  }
12433
12128
  });
12434
12129
  function GameAudioToggle({
@@ -22986,9 +22681,9 @@ var init_BehaviorView = __esm({
22986
22681
  }
22987
22682
  });
22988
22683
 
22989
- // node_modules/.pnpm/katex@0.16.47/node_modules/katex/dist/katex.min.css
22684
+ // node_modules/katex/dist/katex.min.css
22990
22685
  var init_katex_min = __esm({
22991
- "node_modules/.pnpm/katex@0.16.47/node_modules/katex/dist/katex.min.css"() {
22686
+ "node_modules/katex/dist/katex.min.css"() {
22992
22687
  }
22993
22688
  });
22994
22689
  var Tabs;
@@ -27381,129 +27076,6 @@ var init_Breadcrumb = __esm({
27381
27076
  Breadcrumb.displayName = "Breadcrumb";
27382
27077
  }
27383
27078
  });
27384
- function useSafeEventBus2() {
27385
- try {
27386
- return useEventBus();
27387
- } catch {
27388
- return { emit: () => {
27389
- }, on: () => () => {
27390
- }, once: () => {
27391
- } };
27392
- }
27393
- }
27394
- var log8, lookStyles4, ButtonGroup;
27395
- var init_ButtonGroup = __esm({
27396
- "components/core/molecules/ButtonGroup.tsx"() {
27397
- "use client";
27398
- init_cn();
27399
- init_atoms();
27400
- init_useEventBus();
27401
- log8 = createLogger("almadar:ui:button-group");
27402
- lookStyles4 = {
27403
- "right-aligned-buttons": "",
27404
- "floating-bar": "fixed bottom-section left-1/2 -translate-x-1/2 shadow-elevation-toast bg-card p-card-sm rounded-container",
27405
- "inline-row": "gap-2 inline-flex",
27406
- "dropdown-menu": "[&>button:not(:first-child)]:hidden",
27407
- "command-palette-trigger": "[&>button:not(:first-child)]:hidden"
27408
- };
27409
- ButtonGroup = ({
27410
- children,
27411
- primary,
27412
- secondary,
27413
- variant = "default",
27414
- orientation = "horizontal",
27415
- className,
27416
- // Filter-group pattern props (entity and filters are used for schema-driven filtering)
27417
- entity: _entity,
27418
- filters,
27419
- look = "right-aligned-buttons"
27420
- }) => {
27421
- const eventBus = useSafeEventBus2();
27422
- const variantClasses2 = {
27423
- default: "gap-0",
27424
- 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",
27425
- 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"
27426
- };
27427
- const orientationClasses = {
27428
- horizontal: "flex-row",
27429
- 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"
27430
- };
27431
- const handleActionClick = (action) => {
27432
- if (action.event) {
27433
- eventBus.emit("UI:DISPATCH", { event: action.event });
27434
- }
27435
- if (action.navigatesTo) {
27436
- eventBus.emit("UI:NAVIGATE", { url: action.navigatesTo });
27437
- }
27438
- };
27439
- const renderFormActions = () => {
27440
- const buttons = [];
27441
- if (secondary) {
27442
- secondary.forEach((action, index) => {
27443
- buttons.push(
27444
- /* @__PURE__ */ jsx(
27445
- Button,
27446
- {
27447
- type: action.actionType === "submit" ? "submit" : "button",
27448
- variant: action.variant || "ghost",
27449
- onClick: () => handleActionClick(action),
27450
- children: action.label
27451
- },
27452
- `secondary-${index}`
27453
- )
27454
- );
27455
- });
27456
- }
27457
- if (primary) {
27458
- const isSubmit = primary.actionType === "submit";
27459
- buttons.push(
27460
- /* @__PURE__ */ jsx(
27461
- Button,
27462
- {
27463
- type: isSubmit ? "submit" : "button",
27464
- variant: primary.variant || "primary",
27465
- onClick: () => handleActionClick(primary),
27466
- "data-testid": isSubmit ? "form-submit" : void 0,
27467
- children: primary.label
27468
- },
27469
- "primary"
27470
- )
27471
- );
27472
- }
27473
- return buttons;
27474
- };
27475
- const renderFilters = () => {
27476
- if (!filters || filters.length === 0) return null;
27477
- return filters.map((filter, index) => /* @__PURE__ */ jsx(
27478
- Button,
27479
- {
27480
- variant: "ghost",
27481
- onClick: () => {
27482
- log8.debug("Filter clicked", { field: filter.field });
27483
- },
27484
- children: filter.label
27485
- },
27486
- `filter-${filter.field}-${index}`
27487
- ));
27488
- };
27489
- return /* @__PURE__ */ jsx(
27490
- "div",
27491
- {
27492
- className: cn(
27493
- "inline-flex gap-2",
27494
- variantClasses2[variant],
27495
- orientationClasses[orientation],
27496
- lookStyles4[look],
27497
- className
27498
- ),
27499
- role: "group",
27500
- children: children || renderFilters() || renderFormActions()
27501
- }
27502
- );
27503
- };
27504
- ButtonGroup.displayName = "ButtonGroup";
27505
- }
27506
- });
27507
27079
  function useSwipeGesture(callbacks, options = {}) {
27508
27080
  const { threshold = 50, velocityThreshold = 0.3, preventDefault = false } = options;
27509
27081
  const startX = useRef(0);
@@ -28313,7 +27885,7 @@ var init_CardGrid = __esm({
28313
27885
  CardGrid.displayName = "CardGrid";
28314
27886
  }
28315
27887
  });
28316
- function useSafeEventBus3() {
27888
+ function useSafeEventBus2() {
28317
27889
  try {
28318
27890
  return useEventBus();
28319
27891
  } catch {
@@ -28349,7 +27921,7 @@ var init_Carousel = __esm({
28349
27921
  const [activeIndex, setActiveIndex] = useState(0);
28350
27922
  const scrollRef = useRef(null);
28351
27923
  const autoPlayRef = useRef(null);
28352
- const eventBus = useSafeEventBus3();
27924
+ const eventBus = useSafeEventBus2();
28353
27925
  const { t } = useTranslate();
28354
27926
  const safeItems = items ?? [];
28355
27927
  const totalSlides = safeItems.length;
@@ -31685,7 +31257,7 @@ function DataGrid({
31685
31257
  /* @__PURE__ */ jsx(
31686
31258
  Box,
31687
31259
  {
31688
- className: cn("grid", gapStyles5[gap], scrollX ? "grid-flow-col overflow-x-auto" : colsClass, lookStyles5[look], className),
31260
+ className: cn("grid", gapStyles5[gap], scrollX ? "grid-flow-col overflow-x-auto" : colsClass, lookStyles4[look], className),
31689
31261
  style: scrollX ? { gridAutoFlow: "column", gridAutoColumns: `minmax(${minCardWidth}px, 1fr)` } : gridTemplateColumns ? { gridTemplateColumns } : void 0,
31690
31262
  children: data.map((item, index) => {
31691
31263
  const itemData = item;
@@ -31880,7 +31452,7 @@ function DataGrid({
31880
31452
  ] })
31881
31453
  );
31882
31454
  }
31883
- var dataGridLog, BADGE_VARIANTS, gapStyles5, lookStyles5;
31455
+ var dataGridLog, BADGE_VARIANTS, gapStyles5, lookStyles4;
31884
31456
  var init_DataGrid = __esm({
31885
31457
  "components/core/molecules/DataGrid.tsx"() {
31886
31458
  "use client";
@@ -31915,7 +31487,7 @@ var init_DataGrid = __esm({
31915
31487
  lg: "gap-6",
31916
31488
  xl: "gap-8"
31917
31489
  };
31918
- lookStyles5 = {
31490
+ lookStyles4 = {
31919
31491
  dense: "gap-2 [&>*]:p-card-sm",
31920
31492
  spacious: "gap-8 [&>*]:p-card-lg",
31921
31493
  striped: "[&>*:nth-child(even)]:bg-muted/30",
@@ -32342,6 +31914,133 @@ var init_DataList = __esm({
32342
31914
  DataList.displayName = "DataList";
32343
31915
  }
32344
31916
  });
31917
+ var FormSection, FormLayout, FormActions;
31918
+ var init_FormSection = __esm({
31919
+ "components/core/molecules/FormSection.tsx"() {
31920
+ "use client";
31921
+ init_cn();
31922
+ init_atoms();
31923
+ init_Box();
31924
+ init_Typography();
31925
+ init_Button();
31926
+ init_Stack();
31927
+ init_Icon();
31928
+ init_useEventBus();
31929
+ FormSection = ({
31930
+ title,
31931
+ description,
31932
+ children,
31933
+ collapsible = false,
31934
+ defaultCollapsed = false,
31935
+ card = false,
31936
+ columns = 1,
31937
+ className
31938
+ }) => {
31939
+ const [collapsed, setCollapsed] = React107__default.useState(defaultCollapsed);
31940
+ const { t } = useTranslate();
31941
+ const eventBus = useEventBus();
31942
+ const gridClass = {
31943
+ 1: "grid-cols-1",
31944
+ 2: "grid-cols-1 md:grid-cols-2",
31945
+ 3: "grid-cols-1 md:grid-cols-2 lg:grid-cols-3"
31946
+ }[columns];
31947
+ React107__default.useCallback(() => {
31948
+ if (collapsible) {
31949
+ setCollapsed((prev) => !prev);
31950
+ eventBus.emit("UI:TOGGLE_COLLAPSE", { collapsed: !collapsed });
31951
+ }
31952
+ }, [collapsible, collapsed, eventBus]);
31953
+ const content = /* @__PURE__ */ jsxs(Fragment, { children: [
31954
+ (title || description) && /* @__PURE__ */ jsxs(VStack, { gap: "xs", className: "mb-4", children: [
31955
+ title && /* @__PURE__ */ jsxs(
31956
+ HStack,
31957
+ {
31958
+ justify: "between",
31959
+ align: "center",
31960
+ className: cn(collapsible && "cursor-pointer"),
31961
+ action: collapsible ? "TOGGLE_COLLAPSE" : void 0,
31962
+ children: [
31963
+ /* @__PURE__ */ jsx(Typography, { variant: "h3", weight: "semibold", children: title }),
31964
+ collapsible && /* @__PURE__ */ jsx(
31965
+ Button,
31966
+ {
31967
+ variant: "ghost",
31968
+ size: "sm",
31969
+ action: "TOGGLE_COLLAPSE",
31970
+ children: /* @__PURE__ */ jsx(
31971
+ Icon,
31972
+ {
31973
+ icon: ChevronDown,
31974
+ size: "sm",
31975
+ className: cn(
31976
+ "text-muted-foreground transition-transform",
31977
+ collapsed && "rotate-180"
31978
+ )
31979
+ }
31980
+ )
31981
+ }
31982
+ )
31983
+ ]
31984
+ }
31985
+ ),
31986
+ description && /* @__PURE__ */ jsx(Typography, { variant: "small", color: "secondary", children: description })
31987
+ ] }),
31988
+ (!collapsible || !collapsed) && /* @__PURE__ */ jsx(Box, { className: cn("grid gap-4", gridClass), children })
31989
+ ] });
31990
+ if (card) {
31991
+ return /* @__PURE__ */ jsx(Card, { className: cn("p-6", className), children: content });
31992
+ }
31993
+ return /* @__PURE__ */ jsx(Box, { className, children: content });
31994
+ };
31995
+ FormSection.displayName = "FormSection";
31996
+ FormLayout = ({
31997
+ children,
31998
+ dividers = true,
31999
+ className
32000
+ }) => {
32001
+ return /* @__PURE__ */ jsx(
32002
+ VStack,
32003
+ {
32004
+ gap: "lg",
32005
+ className: cn(
32006
+ dividers && "[&>*+*]:pt-8 [&>*+*]:border-t [&>*+*]:border-border",
32007
+ className
32008
+ ),
32009
+ children
32010
+ }
32011
+ );
32012
+ };
32013
+ FormLayout.displayName = "FormLayout";
32014
+ FormActions = ({
32015
+ children,
32016
+ sticky = false,
32017
+ align = "right",
32018
+ className
32019
+ }) => {
32020
+ const alignClass2 = {
32021
+ left: "justify-start",
32022
+ right: "justify-end",
32023
+ between: "justify-between",
32024
+ center: "justify-center"
32025
+ }[align];
32026
+ return /* @__PURE__ */ jsx(
32027
+ HStack,
32028
+ {
32029
+ gap: "sm",
32030
+ align: "center",
32031
+ className: cn(
32032
+ "pt-6 border-t border-border",
32033
+ alignClass2,
32034
+ sticky && "sticky bottom-0 bg-card py-4 -mx-6 px-6 shadow-[0_-4px_6px_-1px_rgb(0,0,0,0.05)]",
32035
+ className
32036
+ ),
32037
+ children
32038
+ }
32039
+ );
32040
+ };
32041
+ FormActions.displayName = "FormActions";
32042
+ }
32043
+ });
32345
32044
  function fileIcon(name) {
32346
32045
  const ext = name.split(".").pop()?.toLowerCase() ?? "";
32347
32046
  switch (ext) {
@@ -32503,6 +32202,129 @@ var init_FormField = __esm({
32503
32202
  FormField.displayName = "FormField";
32504
32203
  }
32505
32204
  });
32205
+ function useSafeEventBus3() {
32206
+ try {
32207
+ return useEventBus();
32208
+ } catch {
32209
+ return { emit: () => {
32210
+ }, on: () => () => {
32211
+ }, once: () => {
32212
+ } };
32213
+ }
32214
+ }
32215
+ var log8, lookStyles5, ButtonGroup;
32216
+ var init_ButtonGroup = __esm({
32217
+ "components/core/molecules/ButtonGroup.tsx"() {
32218
+ "use client";
32219
+ init_cn();
32220
+ init_atoms();
32221
+ init_useEventBus();
32222
+ log8 = createLogger("almadar:ui:button-group");
32223
+ lookStyles5 = {
32224
+ "right-aligned-buttons": "",
32225
+ "floating-bar": "fixed bottom-section left-1/2 -translate-x-1/2 shadow-elevation-toast bg-card p-card-sm rounded-container",
32226
+ "inline-row": "gap-2 inline-flex",
32227
+ "dropdown-menu": "[&>button:not(:first-child)]:hidden",
32228
+ "command-palette-trigger": "[&>button:not(:first-child)]:hidden"
32229
+ };
32230
+ ButtonGroup = ({
32231
+ children,
32232
+ primary,
32233
+ secondary,
32234
+ variant = "default",
32235
+ orientation = "horizontal",
32236
+ className,
32237
+ // Filter-group pattern props (entity and filters are used for schema-driven filtering)
32238
+ entity: _entity,
32239
+ filters,
32240
+ look = "right-aligned-buttons"
32241
+ }) => {
32242
+ const eventBus = useSafeEventBus3();
32243
+ const variantClasses2 = {
32244
+ default: "gap-0",
32245
+ 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",
32246
+ 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"
32247
+ };
32248
+ const orientationClasses = {
32249
+ horizontal: "flex-row",
32250
+ 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"
32251
+ };
32252
+ const handleActionClick = (action) => {
32253
+ if (action.event) {
32254
+ eventBus.emit("UI:DISPATCH", { event: action.event });
32255
+ }
32256
+ if (action.navigatesTo) {
32257
+ eventBus.emit("UI:NAVIGATE", { url: action.navigatesTo });
32258
+ }
32259
+ };
32260
+ const renderFormActions = () => {
32261
+ const buttons = [];
32262
+ if (secondary) {
32263
+ secondary.forEach((action, index) => {
32264
+ buttons.push(
32265
+ /* @__PURE__ */ jsx(
32266
+ Button,
32267
+ {
32268
+ type: action.actionType === "submit" ? "submit" : "button",
32269
+ variant: action.variant || "ghost",
32270
+ onClick: () => handleActionClick(action),
32271
+ children: action.label
32272
+ },
32273
+ `secondary-${index}`
32274
+ )
32275
+ );
32276
+ });
32277
+ }
32278
+ if (primary) {
32279
+ const isSubmit = primary.actionType === "submit";
32280
+ buttons.push(
32281
+ /* @__PURE__ */ jsx(
32282
+ Button,
32283
+ {
32284
+ type: isSubmit ? "submit" : "button",
32285
+ variant: primary.variant || "primary",
32286
+ onClick: () => handleActionClick(primary),
32287
+ "data-testid": isSubmit ? "form-submit" : void 0,
32288
+ children: primary.label
32289
+ },
32290
+ "primary"
32291
+ )
32292
+ );
32293
+ }
32294
+ return buttons;
32295
+ };
32296
+ const renderFilters = () => {
32297
+ if (!filters || filters.length === 0) return null;
32298
+ return filters.map((filter, index) => /* @__PURE__ */ jsx(
32299
+ Button,
32300
+ {
32301
+ variant: "ghost",
32302
+ onClick: () => {
32303
+ log8.debug("Filter clicked", { field: filter.field });
32304
+ },
32305
+ children: filter.label
32306
+ },
32307
+ `filter-${filter.field}-${index}`
32308
+ ));
32309
+ };
32310
+ return /* @__PURE__ */ jsx(
32311
+ "div",
32312
+ {
32313
+ className: cn(
32314
+ "inline-flex gap-2",
32315
+ variantClasses2[variant],
32316
+ orientationClasses[orientation],
32317
+ lookStyles5[look],
32318
+ className
32319
+ ),
32320
+ role: "group",
32321
+ children: children || renderFilters() || renderFormActions()
32322
+ }
32323
+ );
32324
+ };
32325
+ ButtonGroup.displayName = "ButtonGroup";
32326
+ }
32327
+ });
32506
32328
  function getOrCreateStore(query) {
32507
32329
  if (!queryStores.has(query)) {
32508
32330
  queryStores.set(query, {
@@ -51063,7 +50885,6 @@ var init_component_registry_generated = __esm({
51063
50885
  init_BranchingLogicBuilder();
51064
50886
  init_Breadcrumb();
51065
50887
  init_BuilderBoard();
51066
- init_ButtonGroup();
51067
50888
  init_CTABanner();
51068
50889
  init_CalendarGrid();
51069
50890
  init_Canvas2D();
@@ -51140,9 +50961,9 @@ var init_component_registry_generated = __esm({
51140
50961
  init_FlipContainer();
51141
50962
  init_FloatingActionButton();
51142
50963
  init_Form();
50964
+ init_FormSection();
51143
50965
  init_FormField();
51144
50966
  init_FormSectionHeader();
51145
- init_GameAudioProvider();
51146
50967
  init_GameAudioToggle();
51147
50968
  init_GameCard();
51148
50969
  init_GameHud();
@@ -51391,7 +51212,6 @@ var init_component_registry_generated = __esm({
51391
51212
  "Breadcrumb": Breadcrumb,
51392
51213
  "BuilderBoard": BuilderBoard,
51393
51214
  "Button": ButtonPattern,
51394
- "ButtonGroup": ButtonGroup,
51395
51215
  "ButtonPattern": ButtonPattern,
51396
51216
  "CTABanner": CTABanner,
51397
51217
  "CalendarGrid": CalendarGrid,
@@ -51471,9 +51291,10 @@ var init_component_registry_generated = __esm({
51471
51291
  "FlipContainer": FlipContainer,
51472
51292
  "FloatingActionButton": FloatingActionButton,
51473
51293
  "Form": Form,
51294
+ "FormActions": FormActions,
51474
51295
  "FormField": FormField,
51296
+ "FormLayout": FormLayout,
51475
51297
  "FormSectionHeader": FormSectionHeader,
51476
- "GameAudioProvider": GameAudioProvider,
51477
51298
  "GameAudioToggle": GameAudioToggle,
51478
51299
  "GameBoard3D": GameBoard3D,
51479
51300
  "GameCanvas3D": GameCanvas3D,