@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.
- package/dist/avl/index.cjs +35 -17
- package/dist/avl/index.js +35 -17
- package/dist/components/atoms/Input.d.ts +1 -1
- package/dist/components/index.cjs +35 -17
- package/dist/components/index.js +35 -17
- package/dist/components/molecules/CalendarGrid.d.ts +2 -2
- package/dist/components/molecules/DataGrid.d.ts +8 -2
- package/dist/components/molecules/DataList.d.ts +2 -2
- package/dist/components/molecules/PositionedCanvas.d.ts +2 -2
- package/dist/components/molecules/ReplyTree.d.ts +2 -2
- package/dist/components/molecules/SortableList.d.ts +2 -2
- package/dist/components/molecules/TableView.d.ts +2 -2
- package/dist/components/organisms/DetailPanel.d.ts +3 -0
- package/dist/components/organisms/HeroOrganism.d.ts +2 -0
- package/dist/components/organisms/Timeline.d.ts +2 -2
- package/dist/components/organisms/book/BookViewer.d.ts +3 -0
- package/dist/components/organisms/types.d.ts +2 -2
- package/dist/docs/index.d.cts +1 -1
- package/dist/providers/index.cjs +35 -17
- package/dist/providers/index.js +35 -17
- package/dist/runtime/index.cjs +35 -17
- package/dist/runtime/index.js +35 -17
- package/package.json +6 -3
package/dist/components/index.js
CHANGED
|
@@ -8627,7 +8627,7 @@ var init_MapView = __esm({
|
|
|
8627
8627
|
shadowSize: [41, 41]
|
|
8628
8628
|
});
|
|
8629
8629
|
L.Marker.prototype.options.icon = defaultIcon;
|
|
8630
|
-
const { useEffect: useEffect72, useRef: useRef66, useCallback: useCallback128, useState:
|
|
8630
|
+
const { useEffect: useEffect72, useRef: useRef66, useCallback: useCallback128, useState: useState111 } = React80__default;
|
|
8631
8631
|
const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
|
|
8632
8632
|
const { useEventBus: useEventBus2 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
|
|
8633
8633
|
function MapUpdater({ centerLat, centerLng, zoom }) {
|
|
@@ -8672,7 +8672,7 @@ var init_MapView = __esm({
|
|
|
8672
8672
|
showAttribution = true
|
|
8673
8673
|
}) {
|
|
8674
8674
|
const eventBus = useEventBus2();
|
|
8675
|
-
const [clickedPosition, setClickedPosition] =
|
|
8675
|
+
const [clickedPosition, setClickedPosition] = useState111(null);
|
|
8676
8676
|
const handleMapClick = useCallback128((lat, lng) => {
|
|
8677
8677
|
if (showClickedPin) {
|
|
8678
8678
|
setClickedPosition({ lat, lng });
|
|
@@ -16378,6 +16378,7 @@ function CalendarGrid({
|
|
|
16378
16378
|
swipeRightEvent,
|
|
16379
16379
|
dayWindow = "auto"
|
|
16380
16380
|
}) {
|
|
16381
|
+
const evs = Array.isArray(events2) ? events2 : events2 ? [events2] : [];
|
|
16381
16382
|
const eventBus = useEventBus();
|
|
16382
16383
|
const longPressTimer = useRef(null);
|
|
16383
16384
|
const resolvedWeekStart = useMemo(
|
|
@@ -16426,7 +16427,7 @@ function CalendarGrid({
|
|
|
16426
16427
|
[onEventClick]
|
|
16427
16428
|
);
|
|
16428
16429
|
const eventsForDayCount = useCallback(
|
|
16429
|
-
(day) =>
|
|
16430
|
+
(day) => evs.filter(
|
|
16430
16431
|
(ev) => new Date(ev.startTime).toDateString() === day.toDateString()
|
|
16431
16432
|
).length,
|
|
16432
16433
|
[events2]
|
|
@@ -16541,7 +16542,7 @@ function CalendarGrid({
|
|
|
16541
16542
|
}
|
|
16542
16543
|
) }),
|
|
16543
16544
|
visibleDays.map((day) => {
|
|
16544
|
-
const slotEvents =
|
|
16545
|
+
const slotEvents = evs.filter(
|
|
16545
16546
|
(ev) => eventInSlot(ev, day, time)
|
|
16546
16547
|
);
|
|
16547
16548
|
const isToday = day.toDateString() === (/* @__PURE__ */ new Date()).toDateString();
|
|
@@ -25777,8 +25778,16 @@ function GameCanvas2D({
|
|
|
25777
25778
|
drawEventRef.current = drawEvent;
|
|
25778
25779
|
const emitRef = React80.useRef(emit);
|
|
25779
25780
|
emitRef.current = emit;
|
|
25781
|
+
const assetBaseUrlRef = React80.useRef(assetBaseUrl);
|
|
25782
|
+
assetBaseUrlRef.current = assetBaseUrl;
|
|
25783
|
+
const backgroundImageRef = React80.useRef(backgroundImage);
|
|
25784
|
+
backgroundImageRef.current = backgroundImage;
|
|
25785
|
+
const widthRef = React80.useRef(width);
|
|
25786
|
+
widthRef.current = width;
|
|
25787
|
+
const heightRef = React80.useRef(height);
|
|
25788
|
+
heightRef.current = height;
|
|
25780
25789
|
const loadImage = React80.useCallback((url) => {
|
|
25781
|
-
const fullUrl = url.startsWith("http") ? url : `${
|
|
25790
|
+
const fullUrl = url.startsWith("http") ? url : `${assetBaseUrlRef.current}${url}`;
|
|
25782
25791
|
const cached = imageCache.current.get(fullUrl);
|
|
25783
25792
|
if (cached?.complete && cached.naturalWidth > 0) return cached;
|
|
25784
25793
|
if (!cached) {
|
|
@@ -25788,7 +25797,7 @@ function GameCanvas2D({
|
|
|
25788
25797
|
imageCache.current.set(fullUrl, img);
|
|
25789
25798
|
}
|
|
25790
25799
|
return null;
|
|
25791
|
-
}, [
|
|
25800
|
+
}, []);
|
|
25792
25801
|
React80.useEffect(() => {
|
|
25793
25802
|
const canvas = canvasRef.current;
|
|
25794
25803
|
if (!canvas) return;
|
|
@@ -25810,10 +25819,10 @@ function GameCanvas2D({
|
|
|
25810
25819
|
if (tickEventRef.current) {
|
|
25811
25820
|
emitRef.current(tickEventRef.current, { dt, frame });
|
|
25812
25821
|
}
|
|
25813
|
-
if (
|
|
25814
|
-
const bgImg = loadImage(
|
|
25822
|
+
if (backgroundImageRef.current) {
|
|
25823
|
+
const bgImg = loadImage(backgroundImageRef.current);
|
|
25815
25824
|
if (bgImg) {
|
|
25816
|
-
ctx.drawImage(bgImg, 0, 0,
|
|
25825
|
+
ctx.drawImage(bgImg, 0, 0, widthRef.current, heightRef.current);
|
|
25817
25826
|
}
|
|
25818
25827
|
}
|
|
25819
25828
|
onDrawRef.current?.(ctx, frame);
|
|
@@ -25829,7 +25838,7 @@ function GameCanvas2D({
|
|
|
25829
25838
|
running = false;
|
|
25830
25839
|
cancelAnimationFrame(rafRef.current);
|
|
25831
25840
|
};
|
|
25832
|
-
}, [fps]);
|
|
25841
|
+
}, [fps, loadImage]);
|
|
25833
25842
|
return /* @__PURE__ */ jsx(Box, { className: cn("inline-block", className), children: /* @__PURE__ */ jsx(
|
|
25834
25843
|
"canvas",
|
|
25835
25844
|
{
|
|
@@ -27023,15 +27032,22 @@ function PlatformerCanvas({
|
|
|
27023
27032
|
const eventBus = useEventBus();
|
|
27024
27033
|
const keysRef = useRef(/* @__PURE__ */ new Set());
|
|
27025
27034
|
const imageCache = useRef(/* @__PURE__ */ new Map());
|
|
27035
|
+
const [loadedImages, setLoadedImages] = useState(/* @__PURE__ */ new Set());
|
|
27026
27036
|
const loadImage = useCallback((url) => {
|
|
27027
27037
|
const fullUrl = url.startsWith("http") ? url : `${assetBaseUrl}${url}`;
|
|
27028
27038
|
const cached = imageCache.current.get(fullUrl);
|
|
27029
|
-
if (cached?.complete && cached.naturalWidth > 0)
|
|
27039
|
+
if (cached?.complete && cached.naturalWidth > 0) {
|
|
27040
|
+
if (!loadedImages.has(fullUrl)) {
|
|
27041
|
+
setLoadedImages((prev) => new Set(prev).add(fullUrl));
|
|
27042
|
+
}
|
|
27043
|
+
return cached;
|
|
27044
|
+
}
|
|
27030
27045
|
if (!cached) {
|
|
27031
27046
|
const img = new Image();
|
|
27032
27047
|
img.crossOrigin = "anonymous";
|
|
27033
27048
|
img.src = fullUrl;
|
|
27034
27049
|
img.onload = () => {
|
|
27050
|
+
setLoadedImages((prev) => new Set(prev).add(fullUrl));
|
|
27035
27051
|
updateAssetStatus(fullUrl, "loaded");
|
|
27036
27052
|
};
|
|
27037
27053
|
img.onerror = () => {
|
|
@@ -27041,7 +27057,7 @@ function PlatformerCanvas({
|
|
|
27041
27057
|
updateAssetStatus(fullUrl, "pending");
|
|
27042
27058
|
}
|
|
27043
27059
|
return null;
|
|
27044
|
-
}, [assetBaseUrl]);
|
|
27060
|
+
}, [assetBaseUrl, loadedImages]);
|
|
27045
27061
|
useEffect(() => {
|
|
27046
27062
|
if (typeof window === "undefined") return;
|
|
27047
27063
|
const canvas = canvasRef.current;
|
|
@@ -27223,7 +27239,7 @@ function PlatformerCanvas({
|
|
|
27223
27239
|
ctx.arc(ppx + eyeOffsetX + 7, eyeY, eyeSize, 0, Math.PI * 2);
|
|
27224
27240
|
ctx.fill();
|
|
27225
27241
|
}
|
|
27226
|
-
});
|
|
27242
|
+
}, [player, platforms, worldWidth, worldHeight, canvasWidth, canvasHeight, followCamera, bgColor, playerSprite, tileSprites, backgroundImage, assetBaseUrl, loadedImages]);
|
|
27227
27243
|
return /* @__PURE__ */ jsx(
|
|
27228
27244
|
"canvas",
|
|
27229
27245
|
{
|
|
@@ -29274,7 +29290,7 @@ function useSafeEventBus10() {
|
|
|
29274
29290
|
}
|
|
29275
29291
|
}
|
|
29276
29292
|
function SortableListInner({
|
|
29277
|
-
items:
|
|
29293
|
+
items: initialItemsProp = EMPTY_ITEMS,
|
|
29278
29294
|
renderItem,
|
|
29279
29295
|
reorderEvent,
|
|
29280
29296
|
reorderPayload,
|
|
@@ -29282,6 +29298,7 @@ function SortableListInner({
|
|
|
29282
29298
|
className
|
|
29283
29299
|
}) {
|
|
29284
29300
|
const eventBus = useSafeEventBus10();
|
|
29301
|
+
const initialItems = Array.isArray(initialItemsProp) ? initialItemsProp : initialItemsProp ? [initialItemsProp] : [];
|
|
29285
29302
|
const handleReorder = useCallback(
|
|
29286
29303
|
(fromIndex, toIndex, item) => {
|
|
29287
29304
|
eventBus.emit(`UI:${reorderEvent}`, {
|
|
@@ -32778,9 +32795,10 @@ var init_ReplyTree = __esm({
|
|
|
32778
32795
|
showActions = true,
|
|
32779
32796
|
className
|
|
32780
32797
|
}) => {
|
|
32798
|
+
const nodeList = Array.isArray(nodes) ? nodes : nodes ? [nodes] : [];
|
|
32781
32799
|
const [collapsedSet, setCollapsedSet] = useState(() => {
|
|
32782
32800
|
const acc = /* @__PURE__ */ new Set();
|
|
32783
|
-
collectInitiallyCollapsed(
|
|
32801
|
+
collectInitiallyCollapsed(nodeList, acc);
|
|
32784
32802
|
return acc;
|
|
32785
32803
|
});
|
|
32786
32804
|
const toggleCollapse = useCallback((id) => {
|
|
@@ -32794,10 +32812,10 @@ var init_ReplyTree = __esm({
|
|
|
32794
32812
|
return next;
|
|
32795
32813
|
});
|
|
32796
32814
|
}, []);
|
|
32797
|
-
if (
|
|
32815
|
+
if (nodeList.length === 0) {
|
|
32798
32816
|
return /* @__PURE__ */ jsx(Box, { className: cn("text-sm text-muted-foreground", className), children: "No replies yet." });
|
|
32799
32817
|
}
|
|
32800
|
-
return /* @__PURE__ */ jsx(Box, { className: cn("flex flex-col gap-2 min-w-0", className), children:
|
|
32818
|
+
return /* @__PURE__ */ jsx(Box, { className: cn("flex flex-col gap-2 min-w-0", className), children: nodeList.map((node) => /* @__PURE__ */ jsx(
|
|
32801
32819
|
ReplyTreeNode,
|
|
32802
32820
|
{
|
|
32803
32821
|
node,
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* Composes DayCell and TimeSlotCell atoms into a 7-day grid.
|
|
7
7
|
*/
|
|
8
8
|
import React from "react";
|
|
9
|
-
import type { EventEmit, EventPayload } from "@almadar/core";
|
|
9
|
+
import type { EventEmit, EventPayload, EntityCollection } from "@almadar/core";
|
|
10
10
|
export interface CalendarEvent {
|
|
11
11
|
id: string;
|
|
12
12
|
title: string;
|
|
@@ -26,7 +26,7 @@ export interface CalendarGridProps {
|
|
|
26
26
|
/** Time slot labels (defaults to 09:00-17:00) */
|
|
27
27
|
timeSlots?: string[];
|
|
28
28
|
/** Events to display on the grid */
|
|
29
|
-
events?: CalendarEvent
|
|
29
|
+
events?: EntityCollection<CalendarEvent>;
|
|
30
30
|
/** Called when a time slot is clicked */
|
|
31
31
|
onSlotClick?: (day: Date, time: string) => void;
|
|
32
32
|
/** Called when a day header is clicked */
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* Uses atoms only internally: Box, VStack, HStack, Typography, Badge, Button, Icon.
|
|
12
12
|
*/
|
|
13
13
|
import React from 'react';
|
|
14
|
-
import type { EntityRow, EventKey } from '@almadar/core';
|
|
14
|
+
import type { EntityRow, EventKey, EntityCollection } from '@almadar/core';
|
|
15
15
|
import { type DataDndProps } from './useDataDnd';
|
|
16
16
|
export interface DataGridField {
|
|
17
17
|
/** Entity field name (dot-notation supported) */
|
|
@@ -54,8 +54,14 @@ export interface DataGridProps<T extends EntityRow = EntityRow> extends DataDndP
|
|
|
54
54
|
* without widening. The generic `T` lets consumers pass a narrower
|
|
55
55
|
* entity (e.g. `CartItem`) and have the `children` render function
|
|
56
56
|
* receive cards typed to that exact shape.
|
|
57
|
+
*
|
|
58
|
+
* Declared as the pattern's data INLET via `EntityCollection<T>` (the inlet
|
|
59
|
+
* half of the circuit, symmetric with the `EventKey` outlet props below):
|
|
60
|
+
* pattern-sync tags it `kind:"entity", cardinality:"collection"` so consumers
|
|
61
|
+
* bind the domain entity without name-matching the prop. Structurally still
|
|
62
|
+
* `T | readonly T[]` — see the brand's doc.
|
|
57
63
|
*/
|
|
58
|
-
entity: T
|
|
64
|
+
entity: EntityCollection<T>;
|
|
59
65
|
/**
|
|
60
66
|
* Field definitions for rendering each card. The pattern contract in
|
|
61
67
|
* `@almadar/patterns` documents `columns` as the wire-format alias the
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* Uses atoms only internally: Box, VStack, HStack, Typography, Badge, Button, Icon.
|
|
12
12
|
*/
|
|
13
13
|
import React from 'react';
|
|
14
|
-
import type { EntityRow, EventKey } from "@almadar/core";
|
|
14
|
+
import type { EntityRow, EntityCollection, EventKey } from "@almadar/core";
|
|
15
15
|
import { type DataDndProps } from './useDataDnd';
|
|
16
16
|
export interface DataListField {
|
|
17
17
|
/** Entity field name (dot-notation supported) */
|
|
@@ -45,7 +45,7 @@ export interface DataListProps<T extends EntityRow = EntityRow> extends DataDndP
|
|
|
45
45
|
* entity (e.g. `CartItem`) and have the `children` render function
|
|
46
46
|
* receive items of that exact shape.
|
|
47
47
|
*/
|
|
48
|
-
entity: T
|
|
48
|
+
entity: EntityCollection<T>;
|
|
49
49
|
/**
|
|
50
50
|
* Field definitions for rendering each row. The pattern contract in
|
|
51
51
|
* `@almadar/patterns` documents `columns` as the wire-format alias the
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import type { EventEmit,
|
|
2
|
+
import type { EventEmit, EntityCollection } from "@almadar/core";
|
|
3
3
|
export type CanvasItemStatus = 'empty' | 'seated' | 'ordered' | 'awaiting-bill' | 'cleaning';
|
|
4
4
|
export type CanvasItemShape = 'round' | 'rectangle' | 'square';
|
|
5
5
|
export interface CanvasItem {
|
|
@@ -20,7 +20,7 @@ export interface PositionedCanvasProps {
|
|
|
20
20
|
* molecule narrows non-array values to `[]` and validates element shape at
|
|
21
21
|
* render time via the `id` / `x` / `y` guards.
|
|
22
22
|
*/
|
|
23
|
-
items:
|
|
23
|
+
items: EntityCollection<CanvasItem>;
|
|
24
24
|
width?: number;
|
|
25
25
|
height?: number;
|
|
26
26
|
selectedId?: string | null;
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* Composes the VoteStack molecule + Avatar/Typography/Button atoms.
|
|
6
6
|
*/
|
|
7
7
|
import React from "react";
|
|
8
|
-
import type { EventEmit } from "@almadar/core";
|
|
8
|
+
import type { EventEmit, EntityCollection } from "@almadar/core";
|
|
9
9
|
import { type VoteValue } from "../molecules/VoteStack";
|
|
10
10
|
export interface ReplyNode {
|
|
11
11
|
id: string;
|
|
@@ -19,7 +19,7 @@ export interface ReplyNode {
|
|
|
19
19
|
collapsed?: boolean;
|
|
20
20
|
}
|
|
21
21
|
export interface ReplyTreeProps {
|
|
22
|
-
nodes: ReplyNode
|
|
22
|
+
nodes: EntityCollection<ReplyNode>;
|
|
23
23
|
maxDepth?: number;
|
|
24
24
|
onVote?: (nodeId: string, vote: VoteValue) => void;
|
|
25
25
|
onReply?: (parentNodeId: string) => void;
|
|
@@ -6,9 +6,9 @@
|
|
|
6
6
|
* Shows a drop indicator line at the target position during drag.
|
|
7
7
|
*/
|
|
8
8
|
import React from 'react';
|
|
9
|
-
import type { EventKey, EventPayload, EventPayloadValue } from "@almadar/core";
|
|
9
|
+
import type { EntityCollection, EventKey, EventPayload, EventPayloadValue } from "@almadar/core";
|
|
10
10
|
export interface SortableListProps<T extends EventPayloadValue = EventPayload> {
|
|
11
|
-
items: T
|
|
11
|
+
items: EntityCollection<T>;
|
|
12
12
|
renderItem: (item: T, index: number) => React.ReactNode;
|
|
13
13
|
reorderEvent: EventKey;
|
|
14
14
|
reorderPayload?: EventPayload;
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* Icon, Checkbox, Divider.
|
|
13
13
|
*/
|
|
14
14
|
import React from 'react';
|
|
15
|
-
import type { EntityRow, EventKey } from '@almadar/core';
|
|
15
|
+
import type { EntityRow, EventKey, EntityCollection } from '@almadar/core';
|
|
16
16
|
import { type DataDndProps } from './useDataDnd';
|
|
17
17
|
export interface TableViewColumn {
|
|
18
18
|
/** Stable column key (React key + default value lookup). */
|
|
@@ -52,7 +52,7 @@ export interface TableViewItemAction {
|
|
|
52
52
|
}
|
|
53
53
|
export interface TableViewProps<T extends EntityRow = EntityRow> extends DataDndProps {
|
|
54
54
|
/** Schema entity data — single record or collection. */
|
|
55
|
-
entity: T
|
|
55
|
+
entity: EntityCollection<T>;
|
|
56
56
|
/** Column definitions. The compiler emits `columns`; `fields` is the alias. */
|
|
57
57
|
columns?: readonly TableViewColumn[];
|
|
58
58
|
/** Alias for `columns`. */
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
* See EntityDisplayProps in ./types.ts for base prop contract.
|
|
8
8
|
*/
|
|
9
9
|
import React from "react";
|
|
10
|
+
import type { EntityRecord, EntityRow } from "@almadar/core";
|
|
10
11
|
import type { LucideIcon } from "lucide-react";
|
|
11
12
|
import type { EntityDisplayProps } from "./types";
|
|
12
13
|
export interface DetailField {
|
|
@@ -44,6 +45,8 @@ export type FieldDef = string | {
|
|
|
44
45
|
type: string;
|
|
45
46
|
};
|
|
46
47
|
export interface DetailPanelProps extends EntityDisplayProps {
|
|
48
|
+
/** RECORD-cardinality override: renders ONE record (see body collapse below). */
|
|
49
|
+
entity?: EntityRecord<EntityRow>;
|
|
47
50
|
title?: string;
|
|
48
51
|
subtitle?: string;
|
|
49
52
|
status?: {
|
|
@@ -10,9 +10,11 @@
|
|
|
10
10
|
* - Never listens to events
|
|
11
11
|
*/
|
|
12
12
|
import React from 'react';
|
|
13
|
+
import type { EntityRecord } from '@almadar/core';
|
|
13
14
|
import type { EntityDisplayProps } from './types';
|
|
14
15
|
import type { HeroEntity } from './marketing-types';
|
|
15
16
|
export interface HeroOrganismProps extends EntityDisplayProps<HeroEntity> {
|
|
17
|
+
entity?: EntityRecord<HeroEntity>;
|
|
16
18
|
children?: React.ReactNode;
|
|
17
19
|
}
|
|
18
20
|
export declare const HeroOrganism: React.FC<HeroOrganismProps>;
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
*/
|
|
13
13
|
import React from "react";
|
|
14
14
|
import type { EventKey } from "@almadar/core";
|
|
15
|
-
import type { EntityRow } from "@almadar/core";
|
|
15
|
+
import type { EntityCollection, EntityRow } from "@almadar/core";
|
|
16
16
|
import type { LucideIcon } from "lucide-react";
|
|
17
17
|
export type TimelineItemStatus = "complete" | "active" | "pending" | "error";
|
|
18
18
|
/**
|
|
@@ -55,7 +55,7 @@ export interface TimelineProps {
|
|
|
55
55
|
* TimelineItem fields (`icon`, callbacks) cannot round-trip through the
|
|
56
56
|
* event bus, so decorative stories that need them pass `items` directly.
|
|
57
57
|
*/
|
|
58
|
-
entity?: EntityRow
|
|
58
|
+
entity?: EntityCollection<EntityRow>;
|
|
59
59
|
/** Timeline title */
|
|
60
60
|
title?: string;
|
|
61
61
|
/** Timeline items */
|
|
@@ -17,9 +17,12 @@
|
|
|
17
17
|
* - Listens: UI:BOOK_START, UI:BOOK_NAVIGATE, UI:BOOK_PAGE_PREV/NEXT, UI:BOOK_PRINT, UI:BOOK_SHOW_TOC
|
|
18
18
|
*/
|
|
19
19
|
import React from 'react';
|
|
20
|
+
import type { EntityRecord, EntityRow } from '@almadar/core';
|
|
20
21
|
import type { EntityDisplayProps } from '../types';
|
|
21
22
|
import type { BookFieldMap } from './types';
|
|
22
23
|
export interface BookViewerProps extends EntityDisplayProps {
|
|
24
|
+
/** Renders ONE record (the book), not a collection */
|
|
25
|
+
entity?: EntityRecord<EntityRow>;
|
|
23
26
|
/** Initial page index (default: 0 = cover) */
|
|
24
27
|
initialPage?: number;
|
|
25
28
|
/** Field name translation map — a BookFieldMap object or locale key ("ar") */
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* Exception: Form manages local `formData` state for field input tracking.
|
|
8
8
|
* This is the ONE allowed exception — documented here.
|
|
9
9
|
*/
|
|
10
|
-
import type { EntityRow } from '@almadar/core';
|
|
10
|
+
import type { EntityRow, EntityInlet } from '@almadar/core';
|
|
11
11
|
export declare const EntityDisplayEvents: {
|
|
12
12
|
readonly SORT: "SORT";
|
|
13
13
|
readonly PAGINATE: "PAGINATE";
|
|
@@ -61,7 +61,7 @@ export interface EntityDisplayProps<T extends EntityRow = EntityRow> {
|
|
|
61
61
|
* extend `EntityRow`. They surface `EntityDisplayProps<T>` constraint errors.
|
|
62
62
|
* Tracked as a Phase 7 follow-up in `docs/Almadar_Entity_V2_Plan.md` §10.
|
|
63
63
|
*/
|
|
64
|
-
entity?: T
|
|
64
|
+
entity?: EntityInlet<T>;
|
|
65
65
|
/** Additional CSS classes */
|
|
66
66
|
className?: string;
|
|
67
67
|
/** Loading state indicator */
|
package/dist/docs/index.d.cts
CHANGED
|
@@ -318,7 +318,7 @@ interface InputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, "
|
|
|
318
318
|
/** onChange handler - accepts events from input, select, or textarea */
|
|
319
319
|
onChange?: React.ChangeEventHandler<HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement>;
|
|
320
320
|
}
|
|
321
|
-
declare const Input: React.ForwardRefExoticComponent<InputProps & React.RefAttributes<
|
|
321
|
+
declare const Input: React.ForwardRefExoticComponent<InputProps & React.RefAttributes<HTMLSelectElement | HTMLInputElement | HTMLTextAreaElement>>;
|
|
322
322
|
|
|
323
323
|
/**
|
|
324
324
|
* DocSidebar Molecule Component
|
package/dist/providers/index.cjs
CHANGED
|
@@ -10244,7 +10244,7 @@ var init_MapView = __esm({
|
|
|
10244
10244
|
shadowSize: [41, 41]
|
|
10245
10245
|
});
|
|
10246
10246
|
L.Marker.prototype.options.icon = defaultIcon;
|
|
10247
|
-
const { useEffect: useEffect69, useRef: useRef65, useCallback: useCallback114, useState:
|
|
10247
|
+
const { useEffect: useEffect69, useRef: useRef65, useCallback: useCallback114, useState: useState100 } = React86__namespace.default;
|
|
10248
10248
|
const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
|
|
10249
10249
|
const { useEventBus: useEventBus2 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
|
|
10250
10250
|
function MapUpdater({ centerLat, centerLng, zoom }) {
|
|
@@ -10289,7 +10289,7 @@ var init_MapView = __esm({
|
|
|
10289
10289
|
showAttribution = true
|
|
10290
10290
|
}) {
|
|
10291
10291
|
const eventBus = useEventBus2();
|
|
10292
|
-
const [clickedPosition, setClickedPosition] =
|
|
10292
|
+
const [clickedPosition, setClickedPosition] = useState100(null);
|
|
10293
10293
|
const handleMapClick = useCallback114((lat, lng) => {
|
|
10294
10294
|
if (showClickedPin) {
|
|
10295
10295
|
setClickedPosition({ lat, lng });
|
|
@@ -17903,6 +17903,7 @@ function CalendarGrid({
|
|
|
17903
17903
|
swipeRightEvent,
|
|
17904
17904
|
dayWindow = "auto"
|
|
17905
17905
|
}) {
|
|
17906
|
+
const evs = Array.isArray(events2) ? events2 : events2 ? [events2] : [];
|
|
17906
17907
|
const eventBus = useEventBus();
|
|
17907
17908
|
const longPressTimer = React86.useRef(null);
|
|
17908
17909
|
const resolvedWeekStart = React86.useMemo(
|
|
@@ -17951,7 +17952,7 @@ function CalendarGrid({
|
|
|
17951
17952
|
[onEventClick]
|
|
17952
17953
|
);
|
|
17953
17954
|
const eventsForDayCount = React86.useCallback(
|
|
17954
|
-
(day) =>
|
|
17955
|
+
(day) => evs.filter(
|
|
17955
17956
|
(ev) => new Date(ev.startTime).toDateString() === day.toDateString()
|
|
17956
17957
|
).length,
|
|
17957
17958
|
[events2]
|
|
@@ -18066,7 +18067,7 @@ function CalendarGrid({
|
|
|
18066
18067
|
}
|
|
18067
18068
|
) }),
|
|
18068
18069
|
visibleDays.map((day) => {
|
|
18069
|
-
const slotEvents =
|
|
18070
|
+
const slotEvents = evs.filter(
|
|
18070
18071
|
(ev) => eventInSlot(ev, day, time)
|
|
18071
18072
|
);
|
|
18072
18073
|
const isToday = day.toDateString() === (/* @__PURE__ */ new Date()).toDateString();
|
|
@@ -26853,8 +26854,16 @@ function GameCanvas2D({
|
|
|
26853
26854
|
drawEventRef.current = drawEvent;
|
|
26854
26855
|
const emitRef = React86__namespace.useRef(emit);
|
|
26855
26856
|
emitRef.current = emit;
|
|
26857
|
+
const assetBaseUrlRef = React86__namespace.useRef(assetBaseUrl);
|
|
26858
|
+
assetBaseUrlRef.current = assetBaseUrl;
|
|
26859
|
+
const backgroundImageRef = React86__namespace.useRef(backgroundImage);
|
|
26860
|
+
backgroundImageRef.current = backgroundImage;
|
|
26861
|
+
const widthRef = React86__namespace.useRef(width);
|
|
26862
|
+
widthRef.current = width;
|
|
26863
|
+
const heightRef = React86__namespace.useRef(height);
|
|
26864
|
+
heightRef.current = height;
|
|
26856
26865
|
const loadImage = React86__namespace.useCallback((url) => {
|
|
26857
|
-
const fullUrl = url.startsWith("http") ? url : `${
|
|
26866
|
+
const fullUrl = url.startsWith("http") ? url : `${assetBaseUrlRef.current}${url}`;
|
|
26858
26867
|
const cached = imageCache.current.get(fullUrl);
|
|
26859
26868
|
if (cached?.complete && cached.naturalWidth > 0) return cached;
|
|
26860
26869
|
if (!cached) {
|
|
@@ -26864,7 +26873,7 @@ function GameCanvas2D({
|
|
|
26864
26873
|
imageCache.current.set(fullUrl, img);
|
|
26865
26874
|
}
|
|
26866
26875
|
return null;
|
|
26867
|
-
}, [
|
|
26876
|
+
}, []);
|
|
26868
26877
|
React86__namespace.useEffect(() => {
|
|
26869
26878
|
const canvas = canvasRef.current;
|
|
26870
26879
|
if (!canvas) return;
|
|
@@ -26886,10 +26895,10 @@ function GameCanvas2D({
|
|
|
26886
26895
|
if (tickEventRef.current) {
|
|
26887
26896
|
emitRef.current(tickEventRef.current, { dt, frame });
|
|
26888
26897
|
}
|
|
26889
|
-
if (
|
|
26890
|
-
const bgImg = loadImage(
|
|
26898
|
+
if (backgroundImageRef.current) {
|
|
26899
|
+
const bgImg = loadImage(backgroundImageRef.current);
|
|
26891
26900
|
if (bgImg) {
|
|
26892
|
-
ctx.drawImage(bgImg, 0, 0,
|
|
26901
|
+
ctx.drawImage(bgImg, 0, 0, widthRef.current, heightRef.current);
|
|
26893
26902
|
}
|
|
26894
26903
|
}
|
|
26895
26904
|
onDrawRef.current?.(ctx, frame);
|
|
@@ -26905,7 +26914,7 @@ function GameCanvas2D({
|
|
|
26905
26914
|
running = false;
|
|
26906
26915
|
cancelAnimationFrame(rafRef.current);
|
|
26907
26916
|
};
|
|
26908
|
-
}, [fps]);
|
|
26917
|
+
}, [fps, loadImage]);
|
|
26909
26918
|
return /* @__PURE__ */ jsxRuntime.jsx(Box, { className: cn("inline-block", className), children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
26910
26919
|
"canvas",
|
|
26911
26920
|
{
|
|
@@ -28047,15 +28056,22 @@ function PlatformerCanvas({
|
|
|
28047
28056
|
const eventBus = useEventBus();
|
|
28048
28057
|
const keysRef = React86.useRef(/* @__PURE__ */ new Set());
|
|
28049
28058
|
const imageCache = React86.useRef(/* @__PURE__ */ new Map());
|
|
28059
|
+
const [loadedImages, setLoadedImages] = React86.useState(/* @__PURE__ */ new Set());
|
|
28050
28060
|
const loadImage = React86.useCallback((url) => {
|
|
28051
28061
|
const fullUrl = url.startsWith("http") ? url : `${assetBaseUrl}${url}`;
|
|
28052
28062
|
const cached = imageCache.current.get(fullUrl);
|
|
28053
|
-
if (cached?.complete && cached.naturalWidth > 0)
|
|
28063
|
+
if (cached?.complete && cached.naturalWidth > 0) {
|
|
28064
|
+
if (!loadedImages.has(fullUrl)) {
|
|
28065
|
+
setLoadedImages((prev) => new Set(prev).add(fullUrl));
|
|
28066
|
+
}
|
|
28067
|
+
return cached;
|
|
28068
|
+
}
|
|
28054
28069
|
if (!cached) {
|
|
28055
28070
|
const img = new Image();
|
|
28056
28071
|
img.crossOrigin = "anonymous";
|
|
28057
28072
|
img.src = fullUrl;
|
|
28058
28073
|
img.onload = () => {
|
|
28074
|
+
setLoadedImages((prev) => new Set(prev).add(fullUrl));
|
|
28059
28075
|
updateAssetStatus(fullUrl, "loaded");
|
|
28060
28076
|
};
|
|
28061
28077
|
img.onerror = () => {
|
|
@@ -28065,7 +28081,7 @@ function PlatformerCanvas({
|
|
|
28065
28081
|
updateAssetStatus(fullUrl, "pending");
|
|
28066
28082
|
}
|
|
28067
28083
|
return null;
|
|
28068
|
-
}, [assetBaseUrl]);
|
|
28084
|
+
}, [assetBaseUrl, loadedImages]);
|
|
28069
28085
|
React86.useEffect(() => {
|
|
28070
28086
|
if (typeof window === "undefined") return;
|
|
28071
28087
|
const canvas = canvasRef.current;
|
|
@@ -28247,7 +28263,7 @@ function PlatformerCanvas({
|
|
|
28247
28263
|
ctx.arc(ppx + eyeOffsetX + 7, eyeY, eyeSize, 0, Math.PI * 2);
|
|
28248
28264
|
ctx.fill();
|
|
28249
28265
|
}
|
|
28250
|
-
});
|
|
28266
|
+
}, [player, platforms, worldWidth, worldHeight, canvasWidth, canvasHeight, followCamera, bgColor, playerSprite, tileSprites, backgroundImage, assetBaseUrl, loadedImages]);
|
|
28251
28267
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
28252
28268
|
"canvas",
|
|
28253
28269
|
{
|
|
@@ -30276,7 +30292,7 @@ function useSafeEventBus10() {
|
|
|
30276
30292
|
}
|
|
30277
30293
|
}
|
|
30278
30294
|
function SortableListInner({
|
|
30279
|
-
items:
|
|
30295
|
+
items: initialItemsProp = EMPTY_ITEMS,
|
|
30280
30296
|
renderItem,
|
|
30281
30297
|
reorderEvent,
|
|
30282
30298
|
reorderPayload,
|
|
@@ -30284,6 +30300,7 @@ function SortableListInner({
|
|
|
30284
30300
|
className
|
|
30285
30301
|
}) {
|
|
30286
30302
|
const eventBus = useSafeEventBus10();
|
|
30303
|
+
const initialItems = Array.isArray(initialItemsProp) ? initialItemsProp : initialItemsProp ? [initialItemsProp] : [];
|
|
30287
30304
|
const handleReorder = React86.useCallback(
|
|
30288
30305
|
(fromIndex, toIndex, item) => {
|
|
30289
30306
|
eventBus.emit(`UI:${reorderEvent}`, {
|
|
@@ -33780,9 +33797,10 @@ var init_ReplyTree = __esm({
|
|
|
33780
33797
|
showActions = true,
|
|
33781
33798
|
className
|
|
33782
33799
|
}) => {
|
|
33800
|
+
const nodeList = Array.isArray(nodes) ? nodes : nodes ? [nodes] : [];
|
|
33783
33801
|
const [collapsedSet, setCollapsedSet] = React86.useState(() => {
|
|
33784
33802
|
const acc = /* @__PURE__ */ new Set();
|
|
33785
|
-
collectInitiallyCollapsed(
|
|
33803
|
+
collectInitiallyCollapsed(nodeList, acc);
|
|
33786
33804
|
return acc;
|
|
33787
33805
|
});
|
|
33788
33806
|
const toggleCollapse = React86.useCallback((id) => {
|
|
@@ -33796,10 +33814,10 @@ var init_ReplyTree = __esm({
|
|
|
33796
33814
|
return next;
|
|
33797
33815
|
});
|
|
33798
33816
|
}, []);
|
|
33799
|
-
if (
|
|
33817
|
+
if (nodeList.length === 0) {
|
|
33800
33818
|
return /* @__PURE__ */ jsxRuntime.jsx(Box, { className: cn("text-sm text-muted-foreground", className), children: "No replies yet." });
|
|
33801
33819
|
}
|
|
33802
|
-
return /* @__PURE__ */ jsxRuntime.jsx(Box, { className: cn("flex flex-col gap-2 min-w-0", className), children:
|
|
33820
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Box, { className: cn("flex flex-col gap-2 min-w-0", className), children: nodeList.map((node) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
33803
33821
|
ReplyTreeNode,
|
|
33804
33822
|
{
|
|
33805
33823
|
node,
|