@almadar/ui 5.12.0 → 5.13.2

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.
@@ -10195,7 +10195,7 @@ var init_MapView = __esm({
10195
10195
  shadowSize: [41, 41]
10196
10196
  });
10197
10197
  L.Marker.prototype.options.icon = defaultIcon;
10198
- const { useEffect: useEffect69, useRef: useRef65, useCallback: useCallback114, useState: useState99 } = React86__default;
10198
+ const { useEffect: useEffect69, useRef: useRef65, useCallback: useCallback114, useState: useState100 } = React86__default;
10199
10199
  const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
10200
10200
  const { useEventBus: useEventBus2 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
10201
10201
  function MapUpdater({ centerLat, centerLng, zoom }) {
@@ -10240,7 +10240,7 @@ var init_MapView = __esm({
10240
10240
  showAttribution = true
10241
10241
  }) {
10242
10242
  const eventBus = useEventBus2();
10243
- const [clickedPosition, setClickedPosition] = useState99(null);
10243
+ const [clickedPosition, setClickedPosition] = useState100(null);
10244
10244
  const handleMapClick = useCallback114((lat, lng) => {
10245
10245
  if (showClickedPin) {
10246
10246
  setClickedPosition({ lat, lng });
@@ -17854,6 +17854,7 @@ function CalendarGrid({
17854
17854
  swipeRightEvent,
17855
17855
  dayWindow = "auto"
17856
17856
  }) {
17857
+ const evs = Array.isArray(events2) ? events2 : events2 ? [events2] : [];
17857
17858
  const eventBus = useEventBus();
17858
17859
  const longPressTimer = useRef(null);
17859
17860
  const resolvedWeekStart = useMemo(
@@ -17902,7 +17903,7 @@ function CalendarGrid({
17902
17903
  [onEventClick]
17903
17904
  );
17904
17905
  const eventsForDayCount = useCallback(
17905
- (day) => events2.filter(
17906
+ (day) => evs.filter(
17906
17907
  (ev) => new Date(ev.startTime).toDateString() === day.toDateString()
17907
17908
  ).length,
17908
17909
  [events2]
@@ -18017,7 +18018,7 @@ function CalendarGrid({
18017
18018
  }
18018
18019
  ) }),
18019
18020
  visibleDays.map((day) => {
18020
- const slotEvents = events2.filter(
18021
+ const slotEvents = evs.filter(
18021
18022
  (ev) => eventInSlot(ev, day, time)
18022
18023
  );
18023
18024
  const isToday = day.toDateString() === (/* @__PURE__ */ new Date()).toDateString();
@@ -26804,8 +26805,16 @@ function GameCanvas2D({
26804
26805
  drawEventRef.current = drawEvent;
26805
26806
  const emitRef = React86.useRef(emit);
26806
26807
  emitRef.current = emit;
26808
+ const assetBaseUrlRef = React86.useRef(assetBaseUrl);
26809
+ assetBaseUrlRef.current = assetBaseUrl;
26810
+ const backgroundImageRef = React86.useRef(backgroundImage);
26811
+ backgroundImageRef.current = backgroundImage;
26812
+ const widthRef = React86.useRef(width);
26813
+ widthRef.current = width;
26814
+ const heightRef = React86.useRef(height);
26815
+ heightRef.current = height;
26807
26816
  const loadImage = React86.useCallback((url) => {
26808
- const fullUrl = url.startsWith("http") ? url : `${assetBaseUrl}${url}`;
26817
+ const fullUrl = url.startsWith("http") ? url : `${assetBaseUrlRef.current}${url}`;
26809
26818
  const cached = imageCache.current.get(fullUrl);
26810
26819
  if (cached?.complete && cached.naturalWidth > 0) return cached;
26811
26820
  if (!cached) {
@@ -26815,7 +26824,7 @@ function GameCanvas2D({
26815
26824
  imageCache.current.set(fullUrl, img);
26816
26825
  }
26817
26826
  return null;
26818
- }, [assetBaseUrl]);
26827
+ }, []);
26819
26828
  React86.useEffect(() => {
26820
26829
  const canvas = canvasRef.current;
26821
26830
  if (!canvas) return;
@@ -26837,10 +26846,10 @@ function GameCanvas2D({
26837
26846
  if (tickEventRef.current) {
26838
26847
  emitRef.current(tickEventRef.current, { dt, frame });
26839
26848
  }
26840
- if (backgroundImage) {
26841
- const bgImg = loadImage(backgroundImage);
26849
+ if (backgroundImageRef.current) {
26850
+ const bgImg = loadImage(backgroundImageRef.current);
26842
26851
  if (bgImg) {
26843
- ctx.drawImage(bgImg, 0, 0, width, height);
26852
+ ctx.drawImage(bgImg, 0, 0, widthRef.current, heightRef.current);
26844
26853
  }
26845
26854
  }
26846
26855
  onDrawRef.current?.(ctx, frame);
@@ -26856,7 +26865,7 @@ function GameCanvas2D({
26856
26865
  running = false;
26857
26866
  cancelAnimationFrame(rafRef.current);
26858
26867
  };
26859
- }, [fps]);
26868
+ }, [fps, loadImage]);
26860
26869
  return /* @__PURE__ */ jsx(Box, { className: cn("inline-block", className), children: /* @__PURE__ */ jsx(
26861
26870
  "canvas",
26862
26871
  {
@@ -27998,15 +28007,22 @@ function PlatformerCanvas({
27998
28007
  const eventBus = useEventBus();
27999
28008
  const keysRef = useRef(/* @__PURE__ */ new Set());
28000
28009
  const imageCache = useRef(/* @__PURE__ */ new Map());
28010
+ const [loadedImages, setLoadedImages] = useState(/* @__PURE__ */ new Set());
28001
28011
  const loadImage = useCallback((url) => {
28002
28012
  const fullUrl = url.startsWith("http") ? url : `${assetBaseUrl}${url}`;
28003
28013
  const cached = imageCache.current.get(fullUrl);
28004
- if (cached?.complete && cached.naturalWidth > 0) return cached;
28014
+ if (cached?.complete && cached.naturalWidth > 0) {
28015
+ if (!loadedImages.has(fullUrl)) {
28016
+ setLoadedImages((prev) => new Set(prev).add(fullUrl));
28017
+ }
28018
+ return cached;
28019
+ }
28005
28020
  if (!cached) {
28006
28021
  const img = new Image();
28007
28022
  img.crossOrigin = "anonymous";
28008
28023
  img.src = fullUrl;
28009
28024
  img.onload = () => {
28025
+ setLoadedImages((prev) => new Set(prev).add(fullUrl));
28010
28026
  updateAssetStatus(fullUrl, "loaded");
28011
28027
  };
28012
28028
  img.onerror = () => {
@@ -28016,7 +28032,7 @@ function PlatformerCanvas({
28016
28032
  updateAssetStatus(fullUrl, "pending");
28017
28033
  }
28018
28034
  return null;
28019
- }, [assetBaseUrl]);
28035
+ }, [assetBaseUrl, loadedImages]);
28020
28036
  useEffect(() => {
28021
28037
  if (typeof window === "undefined") return;
28022
28038
  const canvas = canvasRef.current;
@@ -28198,7 +28214,7 @@ function PlatformerCanvas({
28198
28214
  ctx.arc(ppx + eyeOffsetX + 7, eyeY, eyeSize, 0, Math.PI * 2);
28199
28215
  ctx.fill();
28200
28216
  }
28201
- });
28217
+ }, [player, platforms, worldWidth, worldHeight, canvasWidth, canvasHeight, followCamera, bgColor, playerSprite, tileSprites, backgroundImage, assetBaseUrl, loadedImages]);
28202
28218
  return /* @__PURE__ */ jsx(
28203
28219
  "canvas",
28204
28220
  {
@@ -30227,7 +30243,7 @@ function useSafeEventBus10() {
30227
30243
  }
30228
30244
  }
30229
30245
  function SortableListInner({
30230
- items: initialItems = EMPTY_ITEMS,
30246
+ items: initialItemsProp = EMPTY_ITEMS,
30231
30247
  renderItem,
30232
30248
  reorderEvent,
30233
30249
  reorderPayload,
@@ -30235,6 +30251,7 @@ function SortableListInner({
30235
30251
  className
30236
30252
  }) {
30237
30253
  const eventBus = useSafeEventBus10();
30254
+ const initialItems = Array.isArray(initialItemsProp) ? initialItemsProp : initialItemsProp ? [initialItemsProp] : [];
30238
30255
  const handleReorder = useCallback(
30239
30256
  (fromIndex, toIndex, item) => {
30240
30257
  eventBus.emit(`UI:${reorderEvent}`, {
@@ -33731,9 +33748,10 @@ var init_ReplyTree = __esm({
33731
33748
  showActions = true,
33732
33749
  className
33733
33750
  }) => {
33751
+ const nodeList = Array.isArray(nodes) ? nodes : nodes ? [nodes] : [];
33734
33752
  const [collapsedSet, setCollapsedSet] = useState(() => {
33735
33753
  const acc = /* @__PURE__ */ new Set();
33736
- collectInitiallyCollapsed(nodes, acc);
33754
+ collectInitiallyCollapsed(nodeList, acc);
33737
33755
  return acc;
33738
33756
  });
33739
33757
  const toggleCollapse = useCallback((id) => {
@@ -33747,10 +33765,10 @@ var init_ReplyTree = __esm({
33747
33765
  return next;
33748
33766
  });
33749
33767
  }, []);
33750
- if (nodes.length === 0) {
33768
+ if (nodeList.length === 0) {
33751
33769
  return /* @__PURE__ */ jsx(Box, { className: cn("text-sm text-muted-foreground", className), children: "No replies yet." });
33752
33770
  }
33753
- return /* @__PURE__ */ jsx(Box, { className: cn("flex flex-col gap-2 min-w-0", className), children: nodes.map((node) => /* @__PURE__ */ jsx(
33771
+ return /* @__PURE__ */ jsx(Box, { className: cn("flex flex-col gap-2 min-w-0", className), children: nodeList.map((node) => /* @__PURE__ */ jsx(
33754
33772
  ReplyTreeNode,
33755
33773
  {
33756
33774
  node,
@@ -10132,7 +10132,7 @@ var init_MapView = __esm({
10132
10132
  shadowSize: [41, 41]
10133
10133
  });
10134
10134
  L.Marker.prototype.options.icon = defaultIcon;
10135
- const { useEffect: useEffect70, useRef: useRef65, useCallback: useCallback114, useState: useState102 } = React85__namespace.default;
10135
+ const { useEffect: useEffect70, useRef: useRef65, useCallback: useCallback114, useState: useState103 } = React85__namespace.default;
10136
10136
  const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
10137
10137
  const { useEventBus: useEventBus2 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
10138
10138
  function MapUpdater({ centerLat, centerLng, zoom }) {
@@ -10177,7 +10177,7 @@ var init_MapView = __esm({
10177
10177
  showAttribution = true
10178
10178
  }) {
10179
10179
  const eventBus = useEventBus2();
10180
- const [clickedPosition, setClickedPosition] = useState102(null);
10180
+ const [clickedPosition, setClickedPosition] = useState103(null);
10181
10181
  const handleMapClick = useCallback114((lat, lng) => {
10182
10182
  if (showClickedPin) {
10183
10183
  setClickedPosition({ lat, lng });
@@ -17686,6 +17686,7 @@ function CalendarGrid({
17686
17686
  swipeRightEvent,
17687
17687
  dayWindow = "auto"
17688
17688
  }) {
17689
+ const evs = Array.isArray(events2) ? events2 : events2 ? [events2] : [];
17689
17690
  const eventBus = useEventBus();
17690
17691
  const longPressTimer = React85.useRef(null);
17691
17692
  const resolvedWeekStart = React85.useMemo(
@@ -17734,7 +17735,7 @@ function CalendarGrid({
17734
17735
  [onEventClick]
17735
17736
  );
17736
17737
  const eventsForDayCount = React85.useCallback(
17737
- (day) => events2.filter(
17738
+ (day) => evs.filter(
17738
17739
  (ev) => new Date(ev.startTime).toDateString() === day.toDateString()
17739
17740
  ).length,
17740
17741
  [events2]
@@ -17849,7 +17850,7 @@ function CalendarGrid({
17849
17850
  }
17850
17851
  ) }),
17851
17852
  visibleDays.map((day) => {
17852
- const slotEvents = events2.filter(
17853
+ const slotEvents = evs.filter(
17853
17854
  (ev) => eventInSlot(ev, day, time)
17854
17855
  );
17855
17856
  const isToday = day.toDateString() === (/* @__PURE__ */ new Date()).toDateString();
@@ -26558,8 +26559,16 @@ function GameCanvas2D({
26558
26559
  drawEventRef.current = drawEvent;
26559
26560
  const emitRef = React85__namespace.useRef(emit);
26560
26561
  emitRef.current = emit;
26562
+ const assetBaseUrlRef = React85__namespace.useRef(assetBaseUrl);
26563
+ assetBaseUrlRef.current = assetBaseUrl;
26564
+ const backgroundImageRef = React85__namespace.useRef(backgroundImage);
26565
+ backgroundImageRef.current = backgroundImage;
26566
+ const widthRef = React85__namespace.useRef(width);
26567
+ widthRef.current = width;
26568
+ const heightRef = React85__namespace.useRef(height);
26569
+ heightRef.current = height;
26561
26570
  const loadImage = React85__namespace.useCallback((url) => {
26562
- const fullUrl = url.startsWith("http") ? url : `${assetBaseUrl}${url}`;
26571
+ const fullUrl = url.startsWith("http") ? url : `${assetBaseUrlRef.current}${url}`;
26563
26572
  const cached = imageCache.current.get(fullUrl);
26564
26573
  if (cached?.complete && cached.naturalWidth > 0) return cached;
26565
26574
  if (!cached) {
@@ -26569,7 +26578,7 @@ function GameCanvas2D({
26569
26578
  imageCache.current.set(fullUrl, img);
26570
26579
  }
26571
26580
  return null;
26572
- }, [assetBaseUrl]);
26581
+ }, []);
26573
26582
  React85__namespace.useEffect(() => {
26574
26583
  const canvas = canvasRef.current;
26575
26584
  if (!canvas) return;
@@ -26591,10 +26600,10 @@ function GameCanvas2D({
26591
26600
  if (tickEventRef.current) {
26592
26601
  emitRef.current(tickEventRef.current, { dt, frame });
26593
26602
  }
26594
- if (backgroundImage) {
26595
- const bgImg = loadImage(backgroundImage);
26603
+ if (backgroundImageRef.current) {
26604
+ const bgImg = loadImage(backgroundImageRef.current);
26596
26605
  if (bgImg) {
26597
- ctx.drawImage(bgImg, 0, 0, width, height);
26606
+ ctx.drawImage(bgImg, 0, 0, widthRef.current, heightRef.current);
26598
26607
  }
26599
26608
  }
26600
26609
  onDrawRef.current?.(ctx, frame);
@@ -26610,7 +26619,7 @@ function GameCanvas2D({
26610
26619
  running = false;
26611
26620
  cancelAnimationFrame(rafRef.current);
26612
26621
  };
26613
- }, [fps]);
26622
+ }, [fps, loadImage]);
26614
26623
  return /* @__PURE__ */ jsxRuntime.jsx(Box, { className: cn("inline-block", className), children: /* @__PURE__ */ jsxRuntime.jsx(
26615
26624
  "canvas",
26616
26625
  {
@@ -27752,15 +27761,22 @@ function PlatformerCanvas({
27752
27761
  const eventBus = useEventBus();
27753
27762
  const keysRef = React85.useRef(/* @__PURE__ */ new Set());
27754
27763
  const imageCache = React85.useRef(/* @__PURE__ */ new Map());
27764
+ const [loadedImages, setLoadedImages] = React85.useState(/* @__PURE__ */ new Set());
27755
27765
  const loadImage = React85.useCallback((url) => {
27756
27766
  const fullUrl = url.startsWith("http") ? url : `${assetBaseUrl}${url}`;
27757
27767
  const cached = imageCache.current.get(fullUrl);
27758
- if (cached?.complete && cached.naturalWidth > 0) return cached;
27768
+ if (cached?.complete && cached.naturalWidth > 0) {
27769
+ if (!loadedImages.has(fullUrl)) {
27770
+ setLoadedImages((prev) => new Set(prev).add(fullUrl));
27771
+ }
27772
+ return cached;
27773
+ }
27759
27774
  if (!cached) {
27760
27775
  const img = new Image();
27761
27776
  img.crossOrigin = "anonymous";
27762
27777
  img.src = fullUrl;
27763
27778
  img.onload = () => {
27779
+ setLoadedImages((prev) => new Set(prev).add(fullUrl));
27764
27780
  updateAssetStatus(fullUrl, "loaded");
27765
27781
  };
27766
27782
  img.onerror = () => {
@@ -27770,7 +27786,7 @@ function PlatformerCanvas({
27770
27786
  updateAssetStatus(fullUrl, "pending");
27771
27787
  }
27772
27788
  return null;
27773
- }, [assetBaseUrl]);
27789
+ }, [assetBaseUrl, loadedImages]);
27774
27790
  React85.useEffect(() => {
27775
27791
  if (typeof window === "undefined") return;
27776
27792
  const canvas = canvasRef.current;
@@ -27952,7 +27968,7 @@ function PlatformerCanvas({
27952
27968
  ctx.arc(ppx + eyeOffsetX + 7, eyeY, eyeSize, 0, Math.PI * 2);
27953
27969
  ctx.fill();
27954
27970
  }
27955
- });
27971
+ }, [player, platforms, worldWidth, worldHeight, canvasWidth, canvasHeight, followCamera, bgColor, playerSprite, tileSprites, backgroundImage, assetBaseUrl, loadedImages]);
27956
27972
  return /* @__PURE__ */ jsxRuntime.jsx(
27957
27973
  "canvas",
27958
27974
  {
@@ -29908,7 +29924,7 @@ function useSafeEventBus10() {
29908
29924
  }
29909
29925
  }
29910
29926
  function SortableListInner({
29911
- items: initialItems = EMPTY_ITEMS,
29927
+ items: initialItemsProp = EMPTY_ITEMS,
29912
29928
  renderItem,
29913
29929
  reorderEvent,
29914
29930
  reorderPayload,
@@ -29916,6 +29932,7 @@ function SortableListInner({
29916
29932
  className
29917
29933
  }) {
29918
29934
  const eventBus = useSafeEventBus10();
29935
+ const initialItems = Array.isArray(initialItemsProp) ? initialItemsProp : initialItemsProp ? [initialItemsProp] : [];
29919
29936
  const handleReorder = React85.useCallback(
29920
29937
  (fromIndex, toIndex, item) => {
29921
29938
  eventBus.emit(`UI:${reorderEvent}`, {
@@ -33347,9 +33364,10 @@ var init_ReplyTree = __esm({
33347
33364
  showActions = true,
33348
33365
  className
33349
33366
  }) => {
33367
+ const nodeList = Array.isArray(nodes) ? nodes : nodes ? [nodes] : [];
33350
33368
  const [collapsedSet, setCollapsedSet] = React85.useState(() => {
33351
33369
  const acc = /* @__PURE__ */ new Set();
33352
- collectInitiallyCollapsed(nodes, acc);
33370
+ collectInitiallyCollapsed(nodeList, acc);
33353
33371
  return acc;
33354
33372
  });
33355
33373
  const toggleCollapse = React85.useCallback((id) => {
@@ -33363,10 +33381,10 @@ var init_ReplyTree = __esm({
33363
33381
  return next;
33364
33382
  });
33365
33383
  }, []);
33366
- if (nodes.length === 0) {
33384
+ if (nodeList.length === 0) {
33367
33385
  return /* @__PURE__ */ jsxRuntime.jsx(Box, { className: cn("text-sm text-muted-foreground", className), children: "No replies yet." });
33368
33386
  }
33369
- return /* @__PURE__ */ jsxRuntime.jsx(Box, { className: cn("flex flex-col gap-2 min-w-0", className), children: nodes.map((node) => /* @__PURE__ */ jsxRuntime.jsx(
33387
+ return /* @__PURE__ */ jsxRuntime.jsx(Box, { className: cn("flex flex-col gap-2 min-w-0", className), children: nodeList.map((node) => /* @__PURE__ */ jsxRuntime.jsx(
33370
33388
  ReplyTreeNode,
33371
33389
  {
33372
33390
  node,
@@ -10083,7 +10083,7 @@ var init_MapView = __esm({
10083
10083
  shadowSize: [41, 41]
10084
10084
  });
10085
10085
  L.Marker.prototype.options.icon = defaultIcon;
10086
- const { useEffect: useEffect70, useRef: useRef65, useCallback: useCallback114, useState: useState102 } = React85__default;
10086
+ const { useEffect: useEffect70, useRef: useRef65, useCallback: useCallback114, useState: useState103 } = React85__default;
10087
10087
  const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
10088
10088
  const { useEventBus: useEventBus2 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
10089
10089
  function MapUpdater({ centerLat, centerLng, zoom }) {
@@ -10128,7 +10128,7 @@ var init_MapView = __esm({
10128
10128
  showAttribution = true
10129
10129
  }) {
10130
10130
  const eventBus = useEventBus2();
10131
- const [clickedPosition, setClickedPosition] = useState102(null);
10131
+ const [clickedPosition, setClickedPosition] = useState103(null);
10132
10132
  const handleMapClick = useCallback114((lat, lng) => {
10133
10133
  if (showClickedPin) {
10134
10134
  setClickedPosition({ lat, lng });
@@ -17637,6 +17637,7 @@ function CalendarGrid({
17637
17637
  swipeRightEvent,
17638
17638
  dayWindow = "auto"
17639
17639
  }) {
17640
+ const evs = Array.isArray(events2) ? events2 : events2 ? [events2] : [];
17640
17641
  const eventBus = useEventBus();
17641
17642
  const longPressTimer = useRef(null);
17642
17643
  const resolvedWeekStart = useMemo(
@@ -17685,7 +17686,7 @@ function CalendarGrid({
17685
17686
  [onEventClick]
17686
17687
  );
17687
17688
  const eventsForDayCount = useCallback(
17688
- (day) => events2.filter(
17689
+ (day) => evs.filter(
17689
17690
  (ev) => new Date(ev.startTime).toDateString() === day.toDateString()
17690
17691
  ).length,
17691
17692
  [events2]
@@ -17800,7 +17801,7 @@ function CalendarGrid({
17800
17801
  }
17801
17802
  ) }),
17802
17803
  visibleDays.map((day) => {
17803
- const slotEvents = events2.filter(
17804
+ const slotEvents = evs.filter(
17804
17805
  (ev) => eventInSlot(ev, day, time)
17805
17806
  );
17806
17807
  const isToday = day.toDateString() === (/* @__PURE__ */ new Date()).toDateString();
@@ -26509,8 +26510,16 @@ function GameCanvas2D({
26509
26510
  drawEventRef.current = drawEvent;
26510
26511
  const emitRef = React85.useRef(emit);
26511
26512
  emitRef.current = emit;
26513
+ const assetBaseUrlRef = React85.useRef(assetBaseUrl);
26514
+ assetBaseUrlRef.current = assetBaseUrl;
26515
+ const backgroundImageRef = React85.useRef(backgroundImage);
26516
+ backgroundImageRef.current = backgroundImage;
26517
+ const widthRef = React85.useRef(width);
26518
+ widthRef.current = width;
26519
+ const heightRef = React85.useRef(height);
26520
+ heightRef.current = height;
26512
26521
  const loadImage = React85.useCallback((url) => {
26513
- const fullUrl = url.startsWith("http") ? url : `${assetBaseUrl}${url}`;
26522
+ const fullUrl = url.startsWith("http") ? url : `${assetBaseUrlRef.current}${url}`;
26514
26523
  const cached = imageCache.current.get(fullUrl);
26515
26524
  if (cached?.complete && cached.naturalWidth > 0) return cached;
26516
26525
  if (!cached) {
@@ -26520,7 +26529,7 @@ function GameCanvas2D({
26520
26529
  imageCache.current.set(fullUrl, img);
26521
26530
  }
26522
26531
  return null;
26523
- }, [assetBaseUrl]);
26532
+ }, []);
26524
26533
  React85.useEffect(() => {
26525
26534
  const canvas = canvasRef.current;
26526
26535
  if (!canvas) return;
@@ -26542,10 +26551,10 @@ function GameCanvas2D({
26542
26551
  if (tickEventRef.current) {
26543
26552
  emitRef.current(tickEventRef.current, { dt, frame });
26544
26553
  }
26545
- if (backgroundImage) {
26546
- const bgImg = loadImage(backgroundImage);
26554
+ if (backgroundImageRef.current) {
26555
+ const bgImg = loadImage(backgroundImageRef.current);
26547
26556
  if (bgImg) {
26548
- ctx.drawImage(bgImg, 0, 0, width, height);
26557
+ ctx.drawImage(bgImg, 0, 0, widthRef.current, heightRef.current);
26549
26558
  }
26550
26559
  }
26551
26560
  onDrawRef.current?.(ctx, frame);
@@ -26561,7 +26570,7 @@ function GameCanvas2D({
26561
26570
  running = false;
26562
26571
  cancelAnimationFrame(rafRef.current);
26563
26572
  };
26564
- }, [fps]);
26573
+ }, [fps, loadImage]);
26565
26574
  return /* @__PURE__ */ jsx(Box, { className: cn("inline-block", className), children: /* @__PURE__ */ jsx(
26566
26575
  "canvas",
26567
26576
  {
@@ -27703,15 +27712,22 @@ function PlatformerCanvas({
27703
27712
  const eventBus = useEventBus();
27704
27713
  const keysRef = useRef(/* @__PURE__ */ new Set());
27705
27714
  const imageCache = useRef(/* @__PURE__ */ new Map());
27715
+ const [loadedImages, setLoadedImages] = useState(/* @__PURE__ */ new Set());
27706
27716
  const loadImage = useCallback((url) => {
27707
27717
  const fullUrl = url.startsWith("http") ? url : `${assetBaseUrl}${url}`;
27708
27718
  const cached = imageCache.current.get(fullUrl);
27709
- if (cached?.complete && cached.naturalWidth > 0) return cached;
27719
+ if (cached?.complete && cached.naturalWidth > 0) {
27720
+ if (!loadedImages.has(fullUrl)) {
27721
+ setLoadedImages((prev) => new Set(prev).add(fullUrl));
27722
+ }
27723
+ return cached;
27724
+ }
27710
27725
  if (!cached) {
27711
27726
  const img = new Image();
27712
27727
  img.crossOrigin = "anonymous";
27713
27728
  img.src = fullUrl;
27714
27729
  img.onload = () => {
27730
+ setLoadedImages((prev) => new Set(prev).add(fullUrl));
27715
27731
  updateAssetStatus(fullUrl, "loaded");
27716
27732
  };
27717
27733
  img.onerror = () => {
@@ -27721,7 +27737,7 @@ function PlatformerCanvas({
27721
27737
  updateAssetStatus(fullUrl, "pending");
27722
27738
  }
27723
27739
  return null;
27724
- }, [assetBaseUrl]);
27740
+ }, [assetBaseUrl, loadedImages]);
27725
27741
  useEffect(() => {
27726
27742
  if (typeof window === "undefined") return;
27727
27743
  const canvas = canvasRef.current;
@@ -27903,7 +27919,7 @@ function PlatformerCanvas({
27903
27919
  ctx.arc(ppx + eyeOffsetX + 7, eyeY, eyeSize, 0, Math.PI * 2);
27904
27920
  ctx.fill();
27905
27921
  }
27906
- });
27922
+ }, [player, platforms, worldWidth, worldHeight, canvasWidth, canvasHeight, followCamera, bgColor, playerSprite, tileSprites, backgroundImage, assetBaseUrl, loadedImages]);
27907
27923
  return /* @__PURE__ */ jsx(
27908
27924
  "canvas",
27909
27925
  {
@@ -29859,7 +29875,7 @@ function useSafeEventBus10() {
29859
29875
  }
29860
29876
  }
29861
29877
  function SortableListInner({
29862
- items: initialItems = EMPTY_ITEMS,
29878
+ items: initialItemsProp = EMPTY_ITEMS,
29863
29879
  renderItem,
29864
29880
  reorderEvent,
29865
29881
  reorderPayload,
@@ -29867,6 +29883,7 @@ function SortableListInner({
29867
29883
  className
29868
29884
  }) {
29869
29885
  const eventBus = useSafeEventBus10();
29886
+ const initialItems = Array.isArray(initialItemsProp) ? initialItemsProp : initialItemsProp ? [initialItemsProp] : [];
29870
29887
  const handleReorder = useCallback(
29871
29888
  (fromIndex, toIndex, item) => {
29872
29889
  eventBus.emit(`UI:${reorderEvent}`, {
@@ -33298,9 +33315,10 @@ var init_ReplyTree = __esm({
33298
33315
  showActions = true,
33299
33316
  className
33300
33317
  }) => {
33318
+ const nodeList = Array.isArray(nodes) ? nodes : nodes ? [nodes] : [];
33301
33319
  const [collapsedSet, setCollapsedSet] = useState(() => {
33302
33320
  const acc = /* @__PURE__ */ new Set();
33303
- collectInitiallyCollapsed(nodes, acc);
33321
+ collectInitiallyCollapsed(nodeList, acc);
33304
33322
  return acc;
33305
33323
  });
33306
33324
  const toggleCollapse = useCallback((id) => {
@@ -33314,10 +33332,10 @@ var init_ReplyTree = __esm({
33314
33332
  return next;
33315
33333
  });
33316
33334
  }, []);
33317
- if (nodes.length === 0) {
33335
+ if (nodeList.length === 0) {
33318
33336
  return /* @__PURE__ */ jsx(Box, { className: cn("text-sm text-muted-foreground", className), children: "No replies yet." });
33319
33337
  }
33320
- return /* @__PURE__ */ jsx(Box, { className: cn("flex flex-col gap-2 min-w-0", className), children: nodes.map((node) => /* @__PURE__ */ jsx(
33338
+ return /* @__PURE__ */ jsx(Box, { className: cn("flex flex-col gap-2 min-w-0", className), children: nodeList.map((node) => /* @__PURE__ */ jsx(
33321
33339
  ReplyTreeNode,
33322
33340
  {
33323
33341
  node,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@almadar/ui",
3
- "version": "5.12.0",
3
+ "version": "5.13.2",
4
4
  "description": "React UI components, hooks, and providers for Almadar",
5
5
  "type": "module",
6
6
  "sideEffects": [
@@ -129,10 +129,10 @@
129
129
  "typecheck": "tsc --noEmit"
130
130
  },
131
131
  "dependencies": {
132
- "@almadar/core": "^9.0.0",
132
+ "@almadar/core": ">=9.8.0",
133
133
  "@almadar/evaluator": ">=2.9.2",
134
134
  "@almadar/logger": "^1.3.0",
135
- "@almadar/patterns": "^2.26.0",
135
+ "@almadar/patterns": ">=2.35.0",
136
136
  "@almadar/runtime": "^6.7.0",
137
137
  "@almadar/std": ">=6.4.1",
138
138
  "@almadar/syntax": ">=1.3.1",
@@ -232,5 +232,8 @@
232
232
  "@types/react": "^19.0.0",
233
233
  "@types/react-dom": "^19.0.0"
234
234
  }
235
+ },
236
+ "overrides": {
237
+ "@almadar/core": "$@almadar/core"
235
238
  }
236
239
  }