@almadar/ui 5.134.0 → 5.136.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.
- package/dist/{TraitProvider-Ch79cUcb.d.cts → EntityBindingContext-CD9ZoXb4.d.cts} +30 -2
- package/dist/{TraitProvider-Ch79cUcb.d.ts → EntityBindingContext-CD9ZoXb4.d.ts} +30 -2
- package/dist/avl/index.cjs +819 -429
- package/dist/avl/index.js +820 -430
- package/dist/{cn-Dm0VrLRG.d.ts → cn-CCaph5o9.d.ts} +1 -1
- package/dist/{cn-D3H9UzCW.d.cts → cn-CL0kdshO.d.cts} +1 -1
- package/dist/components/index.cjs +1649 -1482
- package/dist/components/index.d.cts +105 -202
- package/dist/components/index.d.ts +105 -202
- package/dist/components/index.js +705 -533
- package/dist/lib/drawable/three/index.cjs +16 -0
- package/dist/lib/drawable/three/index.d.cts +1 -1
- package/dist/lib/drawable/three/index.d.ts +1 -1
- package/dist/lib/drawable/three/index.js +16 -0
- package/dist/lib/index.cjs +28 -0
- package/dist/lib/index.d.cts +21 -3
- package/dist/lib/index.d.ts +21 -3
- package/dist/lib/index.js +27 -1
- package/dist/marketing/index.cjs +1 -0
- package/dist/marketing/index.js +1 -0
- package/dist/{paintDispatch-BXJgISot.d.cts → paintDispatch-DXygiK7M.d.cts} +39 -10
- package/dist/{paintDispatch-BXJgISot.d.ts → paintDispatch-DXygiK7M.d.ts} +39 -10
- package/dist/providers/index.cjs +701 -323
- package/dist/providers/index.d.cts +3 -3
- package/dist/providers/index.d.ts +3 -3
- package/dist/providers/index.js +698 -322
- package/dist/runtime/index.cjs +819 -429
- package/dist/runtime/index.d.cts +5 -2
- package/dist/runtime/index.d.ts +5 -2
- package/dist/runtime/index.js +820 -430
- package/package.json +6 -5
package/dist/runtime/index.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import * as React83 from 'react';
|
|
2
2
|
import React83__default, { createContext, useContext, useMemo, useRef, useEffect, useCallback, Suspense, useState, useSyncExternalStore, useLayoutEffect, lazy, useId } from 'react';
|
|
3
|
-
import { EventBusContext, useTraitScopeChain, useEntitySchemaOptional, useEntitySchema, getAllPages, matchPathAmong, OrbitalProvider, TraitScopeProvider, ServerBridgeProvider, useCurrentPagePath, useGameAudioContextOptional, VerificationProvider, EntitySchemaProvider, OrbitalThemeProvider, useServerBridge } from '@almadar/ui/providers';
|
|
3
|
+
import { EventBusContext, useTraitScopeChain, useEntitySchemaOptional, useEntityBindingSnapshot, useTraitScope, useEntitySchema, getAllPages, matchPathAmong, OrbitalProvider, TraitScopeProvider, ServerBridgeProvider, useCurrentPagePath, useGameAudioContextOptional, VerificationProvider, EntitySchemaProvider, OrbitalThemeProvider, useServerBridge, EntityBindingContext } from '@almadar/ui/providers';
|
|
4
4
|
export { EntitySchemaProvider, ServerBridgeProvider, TraitContext, TraitProvider, useEntitySchema, useEntitySchemaOptional, useServerBridge, useTrait, useTraitContext } from '@almadar/ui/providers';
|
|
5
5
|
import { createLogger, setNamespaceLevel, isLogLevelEnabled } from '@almadar/logger';
|
|
6
|
+
import { StateMachineManager, collectDeclaredConfigDefaults, resolveCallSitePayloadCaptures, createServerEffectHandlers, EffectExecutor, createContextFromBindings, createTickScheduler, isValidCronExpression, parseDurationString, InMemoryPersistence, normalizeCallSiteConfigToValues, interpolateValue } from '@almadar/runtime';
|
|
7
|
+
import { mergeEntityFrame, isCircuitEvent, applyListenPayloadMapping, schemaToIR, getPage, clearSchemaCache as clearSchemaCache$1, walkSExpr, buildResolvedTraitConfigs, isRenderBindingMarker, isInlineTrait, containsEntityBinding, isSExpr, isEventPayloadValue, RENDER_BINDING_MARKER } from '@almadar/core';
|
|
6
8
|
import { clsx } from 'clsx';
|
|
7
9
|
import { twMerge } from 'tailwind-merge';
|
|
8
10
|
import * as LucideIcons2 from 'lucide-react';
|
|
@@ -69,14 +71,13 @@ import ReactMarkdown from 'react-markdown';
|
|
|
69
71
|
import remarkGfm from 'remark-gfm';
|
|
70
72
|
import remarkMath from 'remark-math';
|
|
71
73
|
import rehypeKatex from 'rehype-katex';
|
|
72
|
-
import { mergeEntityFrame, isCircuitEvent, applyListenPayloadMapping, schemaToIR, getPage, clearSchemaCache as clearSchemaCache$1, walkSExpr, buildResolvedTraitConfigs, isInlineTrait, isSExpr, isEventPayloadValue } from '@almadar/core';
|
|
73
74
|
import { DndContext, pointerWithin, rectIntersection, closestCorners, useSensors, useSensor, PointerSensor, KeyboardSensor, useDroppable } from '@dnd-kit/core';
|
|
74
75
|
import { useSortable, arrayMove, sortableKeyboardCoordinates, SortableContext, rectSortingStrategy, verticalListSortingStrategy } from '@dnd-kit/sortable';
|
|
75
76
|
import { CSS } from '@dnd-kit/utilities';
|
|
77
|
+
import { ordered, lib } from 'emojilib';
|
|
76
78
|
import { useNodeId, ReactFlowProvider, Handle, Position } from '@xyflow/react';
|
|
77
79
|
import { forceSimulation, forceLink, forceManyBody, forceCollide, forceX, forceY } from 'd3-force';
|
|
78
80
|
import { isDrawHostPattern, getPatternDefinition, getComponentForPattern as getComponentForPattern$1 } from '@almadar/core/patterns';
|
|
79
|
-
import { StateMachineManager, collectDeclaredConfigDefaults, resolveCallSitePayloadCaptures, createServerEffectHandlers, EffectExecutor, createContextFromBindings, createTickScheduler, isValidCronExpression, parseDurationString, InMemoryPersistence, normalizeCallSiteConfigToValues } from '@almadar/runtime';
|
|
80
81
|
import { isKnownStdOperator } from '@almadar/std/registry';
|
|
81
82
|
import { OrbitalServerRuntime } from '@almadar/runtime/OrbitalServerRuntime';
|
|
82
83
|
|
|
@@ -812,6 +813,75 @@ var init_useTapReveal = __esm({
|
|
|
812
813
|
"hooks/useTapReveal.ts"() {
|
|
813
814
|
}
|
|
814
815
|
});
|
|
816
|
+
function resolveMarkerExpression(expression, entity, config, state) {
|
|
817
|
+
const ctx = createContextFromBindings({
|
|
818
|
+
entity,
|
|
819
|
+
payload: {},
|
|
820
|
+
state,
|
|
821
|
+
...config !== void 0 ? { config } : {}
|
|
822
|
+
});
|
|
823
|
+
return interpolateValue(expression, ctx);
|
|
824
|
+
}
|
|
825
|
+
function isPlainObject(value) {
|
|
826
|
+
if (value === null || value === void 0 || typeof value !== "object") return false;
|
|
827
|
+
if (Array.isArray(value)) return false;
|
|
828
|
+
if (React83__default.isValidElement(value)) return false;
|
|
829
|
+
if (value instanceof Date) return false;
|
|
830
|
+
if (typeof value === "function") return false;
|
|
831
|
+
return true;
|
|
832
|
+
}
|
|
833
|
+
function walkValue(value, scopeTrait, entity, config, state) {
|
|
834
|
+
if (isRenderBindingMarker(value)) {
|
|
835
|
+
return { resolved: resolveMarkerExpression(value.expression, entity, config, state), changed: true };
|
|
836
|
+
}
|
|
837
|
+
if (Array.isArray(value)) {
|
|
838
|
+
const out = [];
|
|
839
|
+
let changed = false;
|
|
840
|
+
for (const item of value) {
|
|
841
|
+
const element = item;
|
|
842
|
+
const wasMarker = isRenderBindingMarker(element);
|
|
843
|
+
const { resolved, changed: itemChanged } = walkValue(element, scopeTrait, entity, config, state);
|
|
844
|
+
if (wasMarker && Array.isArray(resolved)) {
|
|
845
|
+
out.push(...resolved);
|
|
846
|
+
changed = true;
|
|
847
|
+
continue;
|
|
848
|
+
}
|
|
849
|
+
out.push(resolved);
|
|
850
|
+
if (itemChanged) changed = true;
|
|
851
|
+
}
|
|
852
|
+
return changed ? { resolved: out, changed: true } : { resolved: value, changed: false };
|
|
853
|
+
}
|
|
854
|
+
if (isPlainObject(value)) {
|
|
855
|
+
const sourceTrait = value._sourceTrait;
|
|
856
|
+
if (typeof sourceTrait === "string" && sourceTrait !== scopeTrait) {
|
|
857
|
+
return { resolved: value, changed: false };
|
|
858
|
+
}
|
|
859
|
+
const out = {};
|
|
860
|
+
let changed = false;
|
|
861
|
+
for (const [key, item] of Object.entries(value)) {
|
|
862
|
+
const { resolved, changed: itemChanged } = walkValue(item, scopeTrait, entity, config, state);
|
|
863
|
+
out[key] = resolved;
|
|
864
|
+
if (itemChanged) changed = true;
|
|
865
|
+
}
|
|
866
|
+
return changed ? { resolved: out, changed: true } : { resolved: value, changed: false };
|
|
867
|
+
}
|
|
868
|
+
return { resolved: value, changed: false };
|
|
869
|
+
}
|
|
870
|
+
function resolveRenderBindingMarkers(props, scopeTrait, entity, config, state) {
|
|
871
|
+
const out = {};
|
|
872
|
+
let changed = false;
|
|
873
|
+
for (const [key, value] of Object.entries(props)) {
|
|
874
|
+
const { resolved, changed: propChanged } = walkValue(value, scopeTrait, entity, config, state);
|
|
875
|
+
out[key] = resolved;
|
|
876
|
+
if (propChanged) changed = true;
|
|
877
|
+
}
|
|
878
|
+
return changed ? out : props;
|
|
879
|
+
}
|
|
880
|
+
var init_resolve_render_bindings = __esm({
|
|
881
|
+
"lib/resolve-render-bindings.ts"() {
|
|
882
|
+
"use client";
|
|
883
|
+
}
|
|
884
|
+
});
|
|
815
885
|
function cn(...inputs) {
|
|
816
886
|
return twMerge(clsx(inputs));
|
|
817
887
|
}
|
|
@@ -1272,9 +1342,13 @@ function getAtlas(url, onReady) {
|
|
|
1272
1342
|
onReady();
|
|
1273
1343
|
}).catch(() => {
|
|
1274
1344
|
atlasCache.set(url, null);
|
|
1345
|
+
onReady();
|
|
1275
1346
|
});
|
|
1276
1347
|
return void 0;
|
|
1277
1348
|
}
|
|
1349
|
+
function atlasFailed(url) {
|
|
1350
|
+
return atlasCache.get(url) === null;
|
|
1351
|
+
}
|
|
1278
1352
|
function subRectFor(atlas, sprite) {
|
|
1279
1353
|
if (isTilesheet(atlas)) {
|
|
1280
1354
|
let col;
|
|
@@ -1695,6 +1769,32 @@ function formatValue(value, format) {
|
|
|
1695
1769
|
return String(value);
|
|
1696
1770
|
}
|
|
1697
1771
|
}
|
|
1772
|
+
function compareCellValues(a, b) {
|
|
1773
|
+
const aEmpty = a === null || a === void 0 || a === "";
|
|
1774
|
+
const bEmpty = b === null || b === void 0 || b === "";
|
|
1775
|
+
if (aEmpty || bEmpty) return aEmpty && bEmpty ? 0 : aEmpty ? 1 : -1;
|
|
1776
|
+
if (typeof a === "number" && typeof b === "number") return a - b;
|
|
1777
|
+
if (typeof a === "boolean" && typeof b === "boolean") return Number(a) - Number(b);
|
|
1778
|
+
const aNum = Number(a);
|
|
1779
|
+
const bNum = Number(b);
|
|
1780
|
+
if (Number.isFinite(aNum) && Number.isFinite(bNum)) return aNum - bNum;
|
|
1781
|
+
const aTime = dateLikeTime(a);
|
|
1782
|
+
const bTime = dateLikeTime(b);
|
|
1783
|
+
if (aTime !== null && bTime !== null) return aTime - bTime;
|
|
1784
|
+
return String(a).localeCompare(String(b));
|
|
1785
|
+
}
|
|
1786
|
+
function dateLikeTime(value) {
|
|
1787
|
+
if (value instanceof Date) return value.getTime();
|
|
1788
|
+
const text = String(value);
|
|
1789
|
+
if (!/\d/.test(text) || !/[-/:T]/.test(text)) return null;
|
|
1790
|
+
const time = Date.parse(text);
|
|
1791
|
+
return Number.isNaN(time) ? null : time;
|
|
1792
|
+
}
|
|
1793
|
+
function sortRows(rows, field, direction = "asc") {
|
|
1794
|
+
if (!field) return rows;
|
|
1795
|
+
const dir = direction === "desc" ? -1 : 1;
|
|
1796
|
+
return [...rows].sort((a, b) => dir * compareCellValues(a?.[field], b?.[field]));
|
|
1797
|
+
}
|
|
1698
1798
|
var init_format = __esm({
|
|
1699
1799
|
"lib/format.ts"() {
|
|
1700
1800
|
}
|
|
@@ -3517,6 +3617,20 @@ var init_Input = __esm({
|
|
|
3517
3617
|
const { t } = useTranslate();
|
|
3518
3618
|
const eventBus = useEventBus();
|
|
3519
3619
|
const type = inputType || htmlType || "text";
|
|
3620
|
+
const isDeclarative = typeof onChange === "string";
|
|
3621
|
+
const [localValue, setLocalValue] = React83__default.useState(value);
|
|
3622
|
+
const pendingEchoRef = React83__default.useRef(/* @__PURE__ */ new Set());
|
|
3623
|
+
React83__default.useEffect(() => {
|
|
3624
|
+
if (!isDeclarative) return;
|
|
3625
|
+
const incoming = value == null ? "" : String(value);
|
|
3626
|
+
if (pendingEchoRef.current.has(incoming)) {
|
|
3627
|
+
pendingEchoRef.current.delete(incoming);
|
|
3628
|
+
return;
|
|
3629
|
+
}
|
|
3630
|
+
pendingEchoRef.current.clear();
|
|
3631
|
+
setLocalValue(value);
|
|
3632
|
+
}, [value, isDeclarative]);
|
|
3633
|
+
const displayValue = isDeclarative ? localValue : value;
|
|
3520
3634
|
const resolveIconNode = (i, cls) => {
|
|
3521
3635
|
if (!i) return null;
|
|
3522
3636
|
if (typeof i === "string") return /* @__PURE__ */ jsx(Icon, { name: i, className: cls });
|
|
@@ -3526,7 +3640,7 @@ var init_Input = __esm({
|
|
|
3526
3640
|
const iconCls = "h-icon-default w-icon-default";
|
|
3527
3641
|
const IconComponent = typeof iconProp === "string" ? resolveIcon(iconProp) : iconProp;
|
|
3528
3642
|
const resolvedLeftIcon = (leftIcon ? resolveIconNode(leftIcon, iconCls) : null) || IconComponent && /* @__PURE__ */ jsx(IconComponent, { className: iconCls });
|
|
3529
|
-
const showClearButton = clearable &&
|
|
3643
|
+
const showClearButton = clearable && displayValue && String(displayValue).length > 0;
|
|
3530
3644
|
const isMultiline = type === "textarea";
|
|
3531
3645
|
const baseClassName = cn(
|
|
3532
3646
|
"block w-full rounded-sm transition-all duration-fast",
|
|
@@ -3545,6 +3659,10 @@ var init_Input = __esm({
|
|
|
3545
3659
|
if (typeof onChange === "string") {
|
|
3546
3660
|
const target = e.target;
|
|
3547
3661
|
const payload = type === "checkbox" ? { checked: target.checked } : { value: target.value };
|
|
3662
|
+
if (type !== "checkbox") {
|
|
3663
|
+
pendingEchoRef.current.add(target.value);
|
|
3664
|
+
setLocalValue(target.value);
|
|
3665
|
+
}
|
|
3548
3666
|
eventBus.emit(`UI:${onChange}`, payload);
|
|
3549
3667
|
} else {
|
|
3550
3668
|
onChange?.(e);
|
|
@@ -3575,7 +3693,7 @@ var init_Input = __esm({
|
|
|
3575
3693
|
"select",
|
|
3576
3694
|
{
|
|
3577
3695
|
ref,
|
|
3578
|
-
value,
|
|
3696
|
+
value: displayValue,
|
|
3579
3697
|
onChange: handleChange,
|
|
3580
3698
|
className: cn(baseClassName, "appearance-none pr-10", className),
|
|
3581
3699
|
...props,
|
|
@@ -3595,7 +3713,7 @@ var init_Input = __esm({
|
|
|
3595
3713
|
"textarea",
|
|
3596
3714
|
{
|
|
3597
3715
|
ref,
|
|
3598
|
-
value,
|
|
3716
|
+
value: displayValue,
|
|
3599
3717
|
onChange: handleChange,
|
|
3600
3718
|
rows,
|
|
3601
3719
|
className: baseClassName,
|
|
@@ -3634,7 +3752,7 @@ var init_Input = __esm({
|
|
|
3634
3752
|
{
|
|
3635
3753
|
ref,
|
|
3636
3754
|
type,
|
|
3637
|
-
value,
|
|
3755
|
+
value: displayValue,
|
|
3638
3756
|
onChange: handleChange,
|
|
3639
3757
|
onKeyDown: handleKeyDown,
|
|
3640
3758
|
className: baseClassName,
|
|
@@ -7521,46 +7639,45 @@ var init_useImageCache = __esm({
|
|
|
7521
7639
|
});
|
|
7522
7640
|
|
|
7523
7641
|
// lib/isometric.ts
|
|
7524
|
-
function isoToScreen(tileX, tileY,
|
|
7525
|
-
const
|
|
7526
|
-
const
|
|
7642
|
+
function isoToScreen(tileX, tileY, cellWidth, baseOffsetX, layout = "isometric") {
|
|
7643
|
+
const w = cellWidth;
|
|
7644
|
+
const fh = cellWidth / 2;
|
|
7527
7645
|
if (layout === "hex") {
|
|
7528
|
-
const screenX2 = tileX *
|
|
7529
|
-
const screenY2 = tileY * (
|
|
7646
|
+
const screenX2 = tileX * w + (tileY & 1) * (w / 2) + baseOffsetX;
|
|
7647
|
+
const screenY2 = tileY * (fh * 0.75);
|
|
7530
7648
|
return { x: screenX2, y: screenY2 };
|
|
7531
7649
|
}
|
|
7532
7650
|
if (layout === "flat") {
|
|
7533
|
-
const screenX2 = tileX *
|
|
7534
|
-
const screenY2 = tileY *
|
|
7651
|
+
const screenX2 = tileX * w + baseOffsetX;
|
|
7652
|
+
const screenY2 = tileY * w;
|
|
7535
7653
|
return { x: screenX2, y: screenY2 };
|
|
7536
7654
|
}
|
|
7537
|
-
const screenX = (tileX - tileY) * (
|
|
7538
|
-
const screenY = (tileX + tileY) * (
|
|
7655
|
+
const screenX = (tileX - tileY) * (w / 2) + baseOffsetX;
|
|
7656
|
+
const screenY = (tileX + tileY) * (fh / 2);
|
|
7539
7657
|
return { x: screenX, y: screenY };
|
|
7540
7658
|
}
|
|
7541
|
-
function screenToIso(screenX, screenY,
|
|
7542
|
-
const
|
|
7543
|
-
const
|
|
7659
|
+
function screenToIso(screenX, screenY, cellWidth, baseOffsetX, layout = "isometric") {
|
|
7660
|
+
const w = cellWidth;
|
|
7661
|
+
const fh = cellWidth / 2;
|
|
7544
7662
|
if (layout === "hex") {
|
|
7545
|
-
const row = Math.round(screenY / (
|
|
7546
|
-
const col = Math.round((screenX - (row & 1) * (
|
|
7663
|
+
const row = Math.round(screenY / (fh * 0.75));
|
|
7664
|
+
const col = Math.round((screenX - (row & 1) * (w / 2) - baseOffsetX) / w);
|
|
7547
7665
|
return { x: col, y: row };
|
|
7548
7666
|
}
|
|
7549
7667
|
if (layout === "flat") {
|
|
7550
|
-
const col = Math.round((screenX - baseOffsetX) /
|
|
7551
|
-
const row = Math.round(screenY /
|
|
7668
|
+
const col = Math.round((screenX - baseOffsetX) / w);
|
|
7669
|
+
const row = Math.round(screenY / w);
|
|
7552
7670
|
return { x: col, y: row };
|
|
7553
7671
|
}
|
|
7554
7672
|
const adjustedX = screenX - baseOffsetX;
|
|
7555
|
-
const tileX = (adjustedX / (
|
|
7556
|
-
const tileY = (screenY / (
|
|
7673
|
+
const tileX = (adjustedX / (w / 2) + screenY / (fh / 2)) / 2;
|
|
7674
|
+
const tileY = (screenY / (fh / 2) - adjustedX / (w / 2)) / 2;
|
|
7557
7675
|
return { x: Math.round(tileX), y: Math.round(tileY) };
|
|
7558
7676
|
}
|
|
7559
|
-
var TILE_WIDTH,
|
|
7677
|
+
var TILE_WIDTH, DIAMOND_TOP_Y, BACKGROUND_FALLBACK_COLOR, MINIMAP_TERRAIN_COLORS;
|
|
7560
7678
|
var init_isometric = __esm({
|
|
7561
7679
|
"lib/isometric.ts"() {
|
|
7562
7680
|
TILE_WIDTH = 256;
|
|
7563
|
-
FLOOR_HEIGHT = 128;
|
|
7564
7681
|
DIAMOND_TOP_Y = 374;
|
|
7565
7682
|
BACKGROUND_FALLBACK_COLOR = "#1a1a2e";
|
|
7566
7683
|
MINIMAP_TERRAIN_COLORS = {
|
|
@@ -8045,210 +8162,6 @@ var init_ChoiceButton = __esm({
|
|
|
8045
8162
|
ChoiceButton.displayName = "ChoiceButton";
|
|
8046
8163
|
}
|
|
8047
8164
|
});
|
|
8048
|
-
function SvgStage({
|
|
8049
|
-
cols,
|
|
8050
|
-
rows,
|
|
8051
|
-
tileSize = 32,
|
|
8052
|
-
background = "var(--color-background)",
|
|
8053
|
-
tileClickEvent,
|
|
8054
|
-
tileHoverEvent,
|
|
8055
|
-
tileLeaveEvent,
|
|
8056
|
-
keyMap,
|
|
8057
|
-
keyUpMap,
|
|
8058
|
-
className,
|
|
8059
|
-
children
|
|
8060
|
-
}) {
|
|
8061
|
-
const eventBus = useEventBus();
|
|
8062
|
-
const svgRef = useRef(null);
|
|
8063
|
-
const pointerDownRef = useRef(null);
|
|
8064
|
-
const cellFromClient = useCallback((clientX, clientY) => {
|
|
8065
|
-
const svg = svgRef.current;
|
|
8066
|
-
if (!svg) return null;
|
|
8067
|
-
const rect = svg.getBoundingClientRect();
|
|
8068
|
-
if (rect.width === 0 || rect.height === 0) return null;
|
|
8069
|
-
const vbW = cols * tileSize;
|
|
8070
|
-
const vbH = rows * tileSize;
|
|
8071
|
-
const meet = Math.min(rect.width / vbW, rect.height / vbH);
|
|
8072
|
-
const offsetX = (rect.width - vbW * meet) / 2;
|
|
8073
|
-
const offsetY = (rect.height - vbH * meet) / 2;
|
|
8074
|
-
const svgX = (clientX - rect.left - offsetX) / meet;
|
|
8075
|
-
const svgY = (clientY - rect.top - offsetY) / meet;
|
|
8076
|
-
return {
|
|
8077
|
-
x: Math.min(Math.max(Math.floor(svgX / tileSize), 0), cols - 1),
|
|
8078
|
-
y: Math.min(Math.max(Math.floor(svgY / tileSize), 0), rows - 1)
|
|
8079
|
-
};
|
|
8080
|
-
}, [cols, rows, tileSize]);
|
|
8081
|
-
const handlePointerDown = useCallback((e) => {
|
|
8082
|
-
pointerDownRef.current = { clientX: e.clientX, clientY: e.clientY };
|
|
8083
|
-
}, []);
|
|
8084
|
-
const handlePointerUp = useCallback((e) => {
|
|
8085
|
-
const down = pointerDownRef.current;
|
|
8086
|
-
pointerDownRef.current = null;
|
|
8087
|
-
if (!tileClickEvent) return;
|
|
8088
|
-
if (down && Math.hypot(e.clientX - down.clientX, e.clientY - down.clientY) > 5) return;
|
|
8089
|
-
const cell = cellFromClient(e.clientX, e.clientY);
|
|
8090
|
-
if (cell) eventBus.emit(`UI:${tileClickEvent}`, cell);
|
|
8091
|
-
}, [cellFromClient, tileClickEvent, eventBus]);
|
|
8092
|
-
const handlePointerMove = useCallback((e) => {
|
|
8093
|
-
if (!tileHoverEvent) return;
|
|
8094
|
-
const cell = cellFromClient(e.clientX, e.clientY);
|
|
8095
|
-
if (cell) eventBus.emit(`UI:${tileHoverEvent}`, cell);
|
|
8096
|
-
}, [cellFromClient, tileHoverEvent, eventBus]);
|
|
8097
|
-
const handlePointerLeave = useCallback(() => {
|
|
8098
|
-
pointerDownRef.current = null;
|
|
8099
|
-
if (tileLeaveEvent) eventBus.emit(`UI:${tileLeaveEvent}`, {});
|
|
8100
|
-
}, [tileLeaveEvent, eventBus]);
|
|
8101
|
-
useEffect(() => {
|
|
8102
|
-
if (!keyMap && !keyUpMap) return;
|
|
8103
|
-
const onDown = (e) => {
|
|
8104
|
-
const ev = keyMap?.[e.code];
|
|
8105
|
-
if (ev) {
|
|
8106
|
-
eventBus.emit(`UI:${ev}`, {});
|
|
8107
|
-
e.preventDefault();
|
|
8108
|
-
}
|
|
8109
|
-
};
|
|
8110
|
-
const onUp = (e) => {
|
|
8111
|
-
const ev = keyUpMap?.[e.code];
|
|
8112
|
-
if (ev) eventBus.emit(`UI:${ev}`, {});
|
|
8113
|
-
};
|
|
8114
|
-
window.addEventListener("keydown", onDown);
|
|
8115
|
-
window.addEventListener("keyup", onUp);
|
|
8116
|
-
return () => {
|
|
8117
|
-
window.removeEventListener("keydown", onDown);
|
|
8118
|
-
window.removeEventListener("keyup", onUp);
|
|
8119
|
-
};
|
|
8120
|
-
}, [keyMap, keyUpMap, eventBus]);
|
|
8121
|
-
useEffect(() => {
|
|
8122
|
-
if (!keyMap && !keyUpMap) return;
|
|
8123
|
-
svgRef.current?.focus();
|
|
8124
|
-
}, [keyMap, keyUpMap]);
|
|
8125
|
-
const stageContext = useMemo(() => ({ tileSize }), [tileSize]);
|
|
8126
|
-
return /* @__PURE__ */ jsxs(
|
|
8127
|
-
"svg",
|
|
8128
|
-
{
|
|
8129
|
-
ref: svgRef,
|
|
8130
|
-
"data-testid": "svg-stage",
|
|
8131
|
-
viewBox: `0 0 ${cols * tileSize} ${rows * tileSize}`,
|
|
8132
|
-
preserveAspectRatio: "xMidYMid meet",
|
|
8133
|
-
className: cn("block h-full w-full", className),
|
|
8134
|
-
tabIndex: keyMap || keyUpMap ? 0 : void 0,
|
|
8135
|
-
onPointerDown: handlePointerDown,
|
|
8136
|
-
onPointerMove: handlePointerMove,
|
|
8137
|
-
onPointerUp: handlePointerUp,
|
|
8138
|
-
onPointerLeave: handlePointerLeave,
|
|
8139
|
-
children: [
|
|
8140
|
-
/* @__PURE__ */ jsx("rect", { width: cols * tileSize, height: rows * tileSize, fill: background }),
|
|
8141
|
-
/* @__PURE__ */ jsx(SvgStageContext.Provider, { value: stageContext, children })
|
|
8142
|
-
]
|
|
8143
|
-
}
|
|
8144
|
-
);
|
|
8145
|
-
}
|
|
8146
|
-
var SvgStageContext;
|
|
8147
|
-
var init_SvgStage = __esm({
|
|
8148
|
-
"components/game/molecules/SvgStage.tsx"() {
|
|
8149
|
-
"use client";
|
|
8150
|
-
init_cn();
|
|
8151
|
-
init_useEventBus();
|
|
8152
|
-
SvgStageContext = React83.createContext({ tileSize: 1 });
|
|
8153
|
-
SvgStage.displayName = "SvgStage";
|
|
8154
|
-
}
|
|
8155
|
-
});
|
|
8156
|
-
function SvgDrawShape({
|
|
8157
|
-
shape,
|
|
8158
|
-
x,
|
|
8159
|
-
y,
|
|
8160
|
-
width,
|
|
8161
|
-
height,
|
|
8162
|
-
radius,
|
|
8163
|
-
radiusY,
|
|
8164
|
-
points,
|
|
8165
|
-
d,
|
|
8166
|
-
x2,
|
|
8167
|
-
y2,
|
|
8168
|
-
fill,
|
|
8169
|
-
stroke,
|
|
8170
|
-
strokeWidth,
|
|
8171
|
-
opacity,
|
|
8172
|
-
className
|
|
8173
|
-
}) {
|
|
8174
|
-
const { tileSize } = useContext(SvgStageContext);
|
|
8175
|
-
const cell = (v) => v === void 0 ? void 0 : v * tileSize;
|
|
8176
|
-
const paint = {
|
|
8177
|
-
fill: fill ?? (stroke === void 0 ? "var(--color-primary)" : "none"),
|
|
8178
|
-
stroke,
|
|
8179
|
-
strokeWidth,
|
|
8180
|
-
opacity,
|
|
8181
|
-
className
|
|
8182
|
-
};
|
|
8183
|
-
return /* @__PURE__ */ jsxs("g", { transform: `translate(${x * tileSize} ${y * tileSize})`, children: [
|
|
8184
|
-
shape === "rect" && /* @__PURE__ */ jsx("rect", { width: cell(width), height: cell(height), ...paint }),
|
|
8185
|
-
shape === "circle" && /* @__PURE__ */ jsx("circle", { r: cell(radius), ...paint }),
|
|
8186
|
-
shape === "ellipse" && /* @__PURE__ */ jsx("ellipse", { rx: cell(radius), ry: cell(radiusY ?? radius), ...paint }),
|
|
8187
|
-
shape === "polygon" && /* @__PURE__ */ jsx("polygon", { points, ...paint }),
|
|
8188
|
-
shape === "polyline" && /* @__PURE__ */ jsx("polyline", { points, ...paint }),
|
|
8189
|
-
shape === "path" && /* @__PURE__ */ jsx("path", { d, ...paint }),
|
|
8190
|
-
shape === "line" && /* @__PURE__ */ jsx("line", { x2: cell(x2), y2: cell(y2), ...paint })
|
|
8191
|
-
] });
|
|
8192
|
-
}
|
|
8193
|
-
var init_SvgDrawShape = __esm({
|
|
8194
|
-
"components/game/atoms/SvgDrawShape.tsx"() {
|
|
8195
|
-
"use client";
|
|
8196
|
-
init_SvgStage();
|
|
8197
|
-
SvgDrawShape.displayName = "SvgDrawShape";
|
|
8198
|
-
}
|
|
8199
|
-
});
|
|
8200
|
-
function SvgDrawGroup({
|
|
8201
|
-
x = 0,
|
|
8202
|
-
y = 0,
|
|
8203
|
-
scale,
|
|
8204
|
-
rotate,
|
|
8205
|
-
opacity,
|
|
8206
|
-
className,
|
|
8207
|
-
children
|
|
8208
|
-
}) {
|
|
8209
|
-
const { tileSize } = useContext(SvgStageContext);
|
|
8210
|
-
const transforms = [`translate(${x * tileSize} ${y * tileSize})`];
|
|
8211
|
-
if (rotate !== void 0) transforms.push(`rotate(${rotate})`);
|
|
8212
|
-
if (scale !== void 0) transforms.push(`scale(${scale})`);
|
|
8213
|
-
return /* @__PURE__ */ jsx("g", { transform: transforms.join(" "), opacity, className, children });
|
|
8214
|
-
}
|
|
8215
|
-
var init_SvgDrawGroup = __esm({
|
|
8216
|
-
"components/game/atoms/SvgDrawGroup.tsx"() {
|
|
8217
|
-
"use client";
|
|
8218
|
-
init_SvgStage();
|
|
8219
|
-
SvgDrawGroup.displayName = "SvgDrawGroup";
|
|
8220
|
-
}
|
|
8221
|
-
});
|
|
8222
|
-
function SvgDrawText({
|
|
8223
|
-
x,
|
|
8224
|
-
y,
|
|
8225
|
-
text,
|
|
8226
|
-
size = 12,
|
|
8227
|
-
fill = "var(--color-foreground)",
|
|
8228
|
-
anchor = "middle",
|
|
8229
|
-
className
|
|
8230
|
-
}) {
|
|
8231
|
-
const { tileSize } = useContext(SvgStageContext);
|
|
8232
|
-
return /* @__PURE__ */ jsx(
|
|
8233
|
-
"text",
|
|
8234
|
-
{
|
|
8235
|
-
x: x * tileSize,
|
|
8236
|
-
y: y * tileSize,
|
|
8237
|
-
fontSize: size,
|
|
8238
|
-
fill,
|
|
8239
|
-
textAnchor: anchor,
|
|
8240
|
-
className,
|
|
8241
|
-
children: text
|
|
8242
|
-
}
|
|
8243
|
-
);
|
|
8244
|
-
}
|
|
8245
|
-
var init_SvgDrawText = __esm({
|
|
8246
|
-
"components/game/atoms/SvgDrawText.tsx"() {
|
|
8247
|
-
"use client";
|
|
8248
|
-
init_SvgStage();
|
|
8249
|
-
SvgDrawText.displayName = "SvgDrawText";
|
|
8250
|
-
}
|
|
8251
|
-
});
|
|
8252
8165
|
function ControlGrid({
|
|
8253
8166
|
kind,
|
|
8254
8167
|
buttons = DEFAULT_BUTTONS,
|
|
@@ -8952,6 +8865,7 @@ function MiniMap({
|
|
|
8952
8865
|
const cached = imgCacheRef.current.get(url);
|
|
8953
8866
|
if (cached) return cached.complete ? cached : null;
|
|
8954
8867
|
const img = new Image();
|
|
8868
|
+
img.crossOrigin = "anonymous";
|
|
8955
8869
|
img.src = url;
|
|
8956
8870
|
img.onload = () => {
|
|
8957
8871
|
const canvas = canvasRef.current;
|
|
@@ -9119,7 +9033,7 @@ function useCamera(initial) {
|
|
|
9119
9033
|
const handleWheel = useCallback((e, drawFn) => {
|
|
9120
9034
|
e.preventDefault();
|
|
9121
9035
|
const zoomDelta = e.deltaY > 0 ? 0.9 : 1.1;
|
|
9122
|
-
cameraRef.current.zoom = Math.max(
|
|
9036
|
+
cameraRef.current.zoom = Math.max(MIN_ZOOM, Math.min(MAX_ZOOM, cameraRef.current.zoom * zoomDelta));
|
|
9123
9037
|
drawFn?.();
|
|
9124
9038
|
}, []);
|
|
9125
9039
|
const handlePointerDown = useCallback((e) => {
|
|
@@ -9140,7 +9054,7 @@ function useCamera(initial) {
|
|
|
9140
9054
|
const zoomAtPoint = useCallback((factor, centerX, centerY, viewportSize, drawFn) => {
|
|
9141
9055
|
const cam = cameraRef.current;
|
|
9142
9056
|
const oldZoom = cam.zoom;
|
|
9143
|
-
const newZoom = Math.max(
|
|
9057
|
+
const newZoom = Math.max(MIN_ZOOM, Math.min(MAX_ZOOM, oldZoom * factor));
|
|
9144
9058
|
if (newZoom === oldZoom) {
|
|
9145
9059
|
drawFn?.();
|
|
9146
9060
|
return;
|
|
@@ -9192,9 +9106,12 @@ function useCamera(initial) {
|
|
|
9192
9106
|
lerpToTarget
|
|
9193
9107
|
};
|
|
9194
9108
|
}
|
|
9109
|
+
var MIN_ZOOM, MAX_ZOOM;
|
|
9195
9110
|
var init_useCamera = __esm({
|
|
9196
9111
|
"hooks/useCamera.ts"() {
|
|
9197
9112
|
"use client";
|
|
9113
|
+
MIN_ZOOM = 0.05;
|
|
9114
|
+
MAX_ZOOM = 10;
|
|
9198
9115
|
}
|
|
9199
9116
|
});
|
|
9200
9117
|
|
|
@@ -9208,6 +9125,7 @@ function getOrLoadImage(url, onReady) {
|
|
|
9208
9125
|
return null;
|
|
9209
9126
|
}
|
|
9210
9127
|
const img = new Image();
|
|
9128
|
+
img.crossOrigin = "anonymous";
|
|
9211
9129
|
const entry = { img, status: "pending", onReady };
|
|
9212
9130
|
cache.set(url, entry);
|
|
9213
9131
|
updateAssetStatus(url, "pending");
|
|
@@ -9219,10 +9137,14 @@ function getOrLoadImage(url, onReady) {
|
|
|
9219
9137
|
img.onerror = () => {
|
|
9220
9138
|
entry.status = "failed";
|
|
9221
9139
|
updateAssetStatus(url, "failed");
|
|
9140
|
+
entry.onReady?.();
|
|
9222
9141
|
};
|
|
9223
9142
|
img.src = url;
|
|
9224
9143
|
return null;
|
|
9225
9144
|
}
|
|
9145
|
+
function getImageStatus(url) {
|
|
9146
|
+
return cache.get(url)?.status;
|
|
9147
|
+
}
|
|
9226
9148
|
var cache;
|
|
9227
9149
|
var init_imageCache = __esm({
|
|
9228
9150
|
"lib/imageCache.ts"() {
|
|
@@ -9331,6 +9253,15 @@ function createWebPainter(ctx, onAssetLoad) {
|
|
|
9331
9253
|
ctx.lineWidth = lineWidth;
|
|
9332
9254
|
ctx.stroke();
|
|
9333
9255
|
},
|
|
9256
|
+
fillPath(d, color) {
|
|
9257
|
+
ctx.fillStyle = color;
|
|
9258
|
+
ctx.fill(new Path2D(d));
|
|
9259
|
+
},
|
|
9260
|
+
strokePath(d, color, lineWidth = 1) {
|
|
9261
|
+
ctx.strokeStyle = color;
|
|
9262
|
+
ctx.lineWidth = lineWidth;
|
|
9263
|
+
ctx.stroke(new Path2D(d));
|
|
9264
|
+
},
|
|
9334
9265
|
text(str, x, y, style) {
|
|
9335
9266
|
if (style.font) ctx.font = style.font;
|
|
9336
9267
|
ctx.fillStyle = style.color;
|
|
@@ -9352,12 +9283,13 @@ var init_webPainter2d = __esm({
|
|
|
9352
9283
|
|
|
9353
9284
|
// lib/drawable/projector.ts
|
|
9354
9285
|
function create2DProjector(opts) {
|
|
9355
|
-
const {
|
|
9356
|
-
const
|
|
9357
|
-
const
|
|
9358
|
-
const
|
|
9286
|
+
const { baseOffsetX, layout } = opts;
|
|
9287
|
+
const tw = opts.tileWidth ?? TILE_WIDTH;
|
|
9288
|
+
const tileWidth = layout === "free" ? 1 : tw;
|
|
9289
|
+
const floorHeight = layout === "free" ? 1 : tw / 2;
|
|
9290
|
+
const diamondTopY = layout === "free" ? 0 : opts.diamondTopY ?? tw * (DIAMOND_TOP_Y / TILE_WIDTH);
|
|
9359
9291
|
const squareGrid = layout === "flat" || layout === "free";
|
|
9360
|
-
const project = (pos) => layout === "free" ? { x: pos.x, y: pos.y } : isoToScreen(pos.x, pos.y,
|
|
9292
|
+
const project = (pos) => layout === "free" ? { x: pos.x, y: pos.y } : isoToScreen(pos.x, pos.y, tw, baseOffsetX, layout);
|
|
9361
9293
|
const anchorPoint = (pos, anchor) => {
|
|
9362
9294
|
const base = project(pos);
|
|
9363
9295
|
if (anchor === "top-left") return base;
|
|
@@ -9388,7 +9320,7 @@ function create2DProjector(opts) {
|
|
|
9388
9320
|
{ x: base.x, y: topY + floorHeight / 2 }
|
|
9389
9321
|
];
|
|
9390
9322
|
};
|
|
9391
|
-
return { project, anchorPoint, cellPath, tileWidth, floorHeight, diamondTopY,
|
|
9323
|
+
return { project, anchorPoint, cellPath, tileWidth, floorHeight, diamondTopY, squareGrid, worldPixelDirect: layout === "free" };
|
|
9392
9324
|
}
|
|
9393
9325
|
var init_projector = __esm({
|
|
9394
9326
|
"lib/drawable/projector.ts"() {
|
|
@@ -9404,32 +9336,67 @@ var init_contract = __esm({
|
|
|
9404
9336
|
"lib/drawable/contract.ts"() {
|
|
9405
9337
|
}
|
|
9406
9338
|
});
|
|
9407
|
-
|
|
9408
|
-
|
|
9339
|
+
function warnMissingOnce(reason, node) {
|
|
9340
|
+
const key = `${reason}:${node.asset.url}:${String(node.asset.atlas)}:${String(node.asset.sprite)}`;
|
|
9341
|
+
if (loggedMissing.has(key)) return;
|
|
9342
|
+
loggedMissing.add(key);
|
|
9343
|
+
spriteLog.warn("draw-sprite asset unresolvable \u2014 painting fallback square", { reason, url: node.asset.url, atlas: node.asset.atlas, sprite: node.asset.sprite });
|
|
9344
|
+
}
|
|
9345
|
+
function paintFallbackSquare(painter, node, dctx, reason) {
|
|
9346
|
+
warnMissingOnce(reason, node);
|
|
9347
|
+
const tw = dctx.projector.tileWidth;
|
|
9348
|
+
const natural = dctx.projector.worldPixelDirect ? FALLBACK_WORLD_PX : tw;
|
|
9349
|
+
const w = node.width !== void 0 ? node.width * tw : natural;
|
|
9350
|
+
const h = node.height !== void 0 ? node.height * tw : natural;
|
|
9351
|
+
const anchor = node.anchor ?? "top-left";
|
|
9352
|
+
const p = dctx.projector.anchorPoint(node.position, anchor);
|
|
9353
|
+
const dx = anchor === "top-left" ? p.x : p.x - w / 2;
|
|
9354
|
+
const dy = anchor === "ground" ? p.y - h : anchor === "center" ? p.y - h / 2 : p.y;
|
|
9355
|
+
painter.save();
|
|
9356
|
+
if (node.opacity !== void 0 && node.opacity !== 1) painter.setAlpha(node.opacity);
|
|
9357
|
+
painter.fillRect(dx, dy, w, h, "#9b8f7f");
|
|
9358
|
+
painter.strokeRect(dx, dy, w, h, "#5e564b", Math.max(1, tw / 32));
|
|
9359
|
+
painter.restore();
|
|
9360
|
+
}
|
|
9409
9361
|
function DrawSprite(_props) {
|
|
9410
9362
|
return null;
|
|
9411
9363
|
}
|
|
9412
|
-
var paintSprite;
|
|
9364
|
+
var spriteLog, loggedMissing, FALLBACK_WORLD_PX, paintSprite;
|
|
9413
9365
|
var init_DrawSprite = __esm({
|
|
9414
9366
|
"components/game/atoms/DrawSprite.tsx"() {
|
|
9415
9367
|
"use client";
|
|
9416
9368
|
init_atlasSlice();
|
|
9369
|
+
init_imageCache();
|
|
9417
9370
|
init_contract();
|
|
9371
|
+
spriteLog = createLogger("almadar:ui:draw-sprite");
|
|
9372
|
+
loggedMissing = /* @__PURE__ */ new Set();
|
|
9373
|
+
FALLBACK_WORLD_PX = 32;
|
|
9418
9374
|
paintSprite = (painter, node, dctx) => {
|
|
9419
9375
|
if (!node.asset?.url || !isValidScenePos(node.position)) return;
|
|
9420
9376
|
const tex = painter.resolveTexture(node.asset.url);
|
|
9421
|
-
if (!tex)
|
|
9377
|
+
if (!tex) {
|
|
9378
|
+
if (getImageStatus(node.asset.url) === "failed") paintFallbackSquare(painter, node, dctx, "texture-failed");
|
|
9379
|
+
return;
|
|
9380
|
+
}
|
|
9422
9381
|
let src = typeof node.frame === "object" ? node.frame : void 0;
|
|
9423
9382
|
if (!src && isAtlasAsset(node.asset)) {
|
|
9424
9383
|
const atlas = getAtlas(node.asset.atlas, dctx.invalidate);
|
|
9425
|
-
if (!atlas)
|
|
9384
|
+
if (!atlas) {
|
|
9385
|
+
if (atlasFailed(node.asset.atlas)) paintFallbackSquare(painter, node, dctx, "atlas-failed");
|
|
9386
|
+
return;
|
|
9387
|
+
}
|
|
9426
9388
|
const r = subRectFor(atlas, node.asset.sprite);
|
|
9427
|
-
if (!r)
|
|
9389
|
+
if (!r) {
|
|
9390
|
+
paintFallbackSquare(painter, node, dctx, "sprite-missing");
|
|
9391
|
+
return;
|
|
9392
|
+
}
|
|
9428
9393
|
src = { x: r.sx, y: r.sy, w: r.sw, h: r.sh };
|
|
9429
9394
|
}
|
|
9430
9395
|
const tw = dctx.projector.tileWidth;
|
|
9431
|
-
const
|
|
9432
|
-
const
|
|
9396
|
+
const fallbackW = dctx.projector.worldPixelDirect ? src ? src.w : tex.width : tw;
|
|
9397
|
+
const fallbackH = dctx.projector.worldPixelDirect ? src ? src.h : tex.height : tw;
|
|
9398
|
+
const w = node.width !== void 0 ? node.width * tw : fallbackW;
|
|
9399
|
+
const h = node.height !== void 0 ? node.height * tw : fallbackH;
|
|
9433
9400
|
const anchor = node.anchor ?? "top-left";
|
|
9434
9401
|
const p = dctx.projector.anchorPoint(node.position, anchor);
|
|
9435
9402
|
const dx = anchor === "top-left" ? p.x : p.x - w / 2;
|
|
@@ -9506,6 +9473,16 @@ var init_DrawShape = __esm({
|
|
|
9506
9473
|
if (node.stroke) painter.strokePoly(pts, node.stroke, node.strokeWidth ?? 1, true);
|
|
9507
9474
|
break;
|
|
9508
9475
|
}
|
|
9476
|
+
case "path": {
|
|
9477
|
+
if (!node.d) break;
|
|
9478
|
+
const base = dctx.projector.project(node.position);
|
|
9479
|
+
const tw = dctx.projector.tileWidth;
|
|
9480
|
+
painter.translate(base.x, base.y);
|
|
9481
|
+
painter.scale(tw, tw);
|
|
9482
|
+
if (node.fill) painter.fillPath(node.d, node.fill);
|
|
9483
|
+
if (node.stroke) painter.strokePath(node.d, node.stroke, (node.strokeWidth ?? 1) / tw);
|
|
9484
|
+
break;
|
|
9485
|
+
}
|
|
9509
9486
|
}
|
|
9510
9487
|
painter.restore();
|
|
9511
9488
|
};
|
|
@@ -9597,6 +9574,19 @@ function paintDrawable(painter, node, dctx) {
|
|
|
9597
9574
|
case "draw-text":
|
|
9598
9575
|
paintText(painter, node, dctx);
|
|
9599
9576
|
break;
|
|
9577
|
+
case "draw-group": {
|
|
9578
|
+
if (!isValidScenePos(node.position)) break;
|
|
9579
|
+
if (!Array.isArray(node.items)) break;
|
|
9580
|
+
const p = dctx.projector.project(node.position);
|
|
9581
|
+
painter.save();
|
|
9582
|
+
painter.translate(p.x, p.y);
|
|
9583
|
+
if (node.scale !== void 0) painter.scale(node.scale, node.scale);
|
|
9584
|
+
if (node.rotate !== void 0) painter.rotate(node.rotate);
|
|
9585
|
+
if (node.opacity !== void 0 && node.opacity !== 1) painter.setAlpha(node.opacity);
|
|
9586
|
+
for (const item of node.items) paintDrawable(painter, item, dctx);
|
|
9587
|
+
painter.restore();
|
|
9588
|
+
break;
|
|
9589
|
+
}
|
|
9600
9590
|
case "draw-sprite-layer":
|
|
9601
9591
|
paintSpriteLayer(painter, node, dctx);
|
|
9602
9592
|
break;
|
|
@@ -9610,6 +9600,7 @@ function paintDrawable(painter, node, dctx) {
|
|
|
9610
9600
|
}
|
|
9611
9601
|
var init_paintDispatch = __esm({
|
|
9612
9602
|
"lib/drawable/paintDispatch.ts"() {
|
|
9603
|
+
init_contract();
|
|
9613
9604
|
init_DrawSprite();
|
|
9614
9605
|
init_DrawShape();
|
|
9615
9606
|
init_DrawText();
|
|
@@ -9627,6 +9618,7 @@ function collectDrawnItems(nodes) {
|
|
|
9627
9618
|
case "draw-sprite":
|
|
9628
9619
|
case "draw-shape":
|
|
9629
9620
|
case "draw-text":
|
|
9621
|
+
case "draw-group":
|
|
9630
9622
|
if (isValidScenePos(n.position)) out.push({ pos: n.position, id: n.id });
|
|
9631
9623
|
break;
|
|
9632
9624
|
case "draw-sprite-layer":
|
|
@@ -9670,6 +9662,8 @@ function Canvas2D({
|
|
|
9670
9662
|
keyUpMap,
|
|
9671
9663
|
camera = "pan-zoom",
|
|
9672
9664
|
scale = 0.4,
|
|
9665
|
+
tileWidth,
|
|
9666
|
+
fit = false,
|
|
9673
9667
|
showMinimap = true,
|
|
9674
9668
|
followTarget,
|
|
9675
9669
|
cameraPos,
|
|
@@ -9712,9 +9706,32 @@ function Canvas2D({
|
|
|
9712
9706
|
observer2.observe(el);
|
|
9713
9707
|
return () => observer2.disconnect();
|
|
9714
9708
|
}, []);
|
|
9715
|
-
const
|
|
9716
|
-
const
|
|
9717
|
-
const
|
|
9709
|
+
const [atlasVersion, setAtlasVersion] = useState(0);
|
|
9710
|
+
const bumpAtlas = useCallback(() => setAtlasVersion((v) => v + 1), []);
|
|
9711
|
+
const detectedTileWidth = useMemo(() => {
|
|
9712
|
+
for (const n of drawables ?? []) {
|
|
9713
|
+
const refs = [];
|
|
9714
|
+
if (n.type === "draw-sprite") refs.push(n.asset);
|
|
9715
|
+
else if (n.type === "draw-sprite-layer") for (const it of n.items) refs.push(it.asset);
|
|
9716
|
+
for (const a of refs) {
|
|
9717
|
+
if (a && isAtlasAsset(a) && a.atlas) {
|
|
9718
|
+
const atlas = getAtlas(a.atlas, bumpAtlas);
|
|
9719
|
+
if (atlas) {
|
|
9720
|
+
if ("tileWidth" in atlas) return atlas.tileWidth;
|
|
9721
|
+
if ("subTextures" in atlas) {
|
|
9722
|
+
const first = Object.values(atlas.subTextures)[0];
|
|
9723
|
+
if (first && typeof first.width === "number") return first.width;
|
|
9724
|
+
}
|
|
9725
|
+
}
|
|
9726
|
+
}
|
|
9727
|
+
}
|
|
9728
|
+
}
|
|
9729
|
+
return void 0;
|
|
9730
|
+
}, [drawables, atlasVersion]);
|
|
9731
|
+
const nativeTileW = tileWidth ?? detectedTileWidth ?? TILE_WIDTH;
|
|
9732
|
+
const scaledTileWidth = nativeTileW;
|
|
9733
|
+
const scaledFloorHeight = nativeTileW / 2;
|
|
9734
|
+
const scaledDiamondTopY = nativeTileW * (DIAMOND_TOP_Y / TILE_WIDTH);
|
|
9718
9735
|
const drawnItems = useMemo(() => collectDrawnItems(drawables ?? []), [drawables]);
|
|
9719
9736
|
const scenePositions = useMemo(() => drawnItems.map((i) => i.pos), [drawnItems]);
|
|
9720
9737
|
const hitIndex = useMemo(() => buildHitIndex(drawnItems), [drawnItems]);
|
|
@@ -9732,14 +9749,36 @@ function Canvas2D({
|
|
|
9732
9749
|
if (isFree || projection === "flat" || projection === "side") return 0;
|
|
9733
9750
|
return (gridExtent.height - 1) * (scaledTileWidth / 2);
|
|
9734
9751
|
}, [isFree, projection, gridExtent.height, scaledTileWidth]);
|
|
9752
|
+
const effectiveZoom = useMemo(() => {
|
|
9753
|
+
if (isFree || projection === "side") return scale;
|
|
9754
|
+
if (!fit) {
|
|
9755
|
+
const z2 = TILE_WIDTH * scale * scale / nativeTileW;
|
|
9756
|
+
return Number.isFinite(z2) && z2 > 0 ? z2 : scale;
|
|
9757
|
+
}
|
|
9758
|
+
if (!viewportSize.width || gridExtent.width < 2 || gridExtent.height < 2) return scale;
|
|
9759
|
+
let boardW;
|
|
9760
|
+
let boardH;
|
|
9761
|
+
if (projection === "flat") {
|
|
9762
|
+
boardW = gridExtent.width * nativeTileW;
|
|
9763
|
+
boardH = gridExtent.height * nativeTileW;
|
|
9764
|
+
} else if (projection === "hex") {
|
|
9765
|
+
boardW = (gridExtent.width + 0.5) * nativeTileW;
|
|
9766
|
+
boardH = gridExtent.height * (nativeTileW / 2) * 0.75 + nativeTileW / 2;
|
|
9767
|
+
} else {
|
|
9768
|
+
boardW = (gridExtent.width + gridExtent.height) * (nativeTileW / 2);
|
|
9769
|
+
boardH = (gridExtent.width + gridExtent.height) * (nativeTileW / 4);
|
|
9770
|
+
}
|
|
9771
|
+
const z = Math.min(viewportSize.width * 0.85 / boardW, viewportSize.height * 0.85 / boardH);
|
|
9772
|
+
return Number.isFinite(z) && z > 0 ? z : scale;
|
|
9773
|
+
}, [isFree, projection, fit, viewportSize, gridExtent, nativeTileW, scale]);
|
|
9735
9774
|
const projector = useMemo(
|
|
9736
|
-
() => create2DProjector({
|
|
9737
|
-
[
|
|
9775
|
+
() => create2DProjector({ tileWidth: nativeTileW, baseOffsetX, layout }),
|
|
9776
|
+
[nativeTileW, baseOffsetX, layout]
|
|
9738
9777
|
);
|
|
9739
9778
|
const unproject = useCallback((screenX, screenY) => {
|
|
9740
9779
|
if (projection === "free" || projection === "side") return { x: Math.round(screenX), y: Math.round(screenY) };
|
|
9741
|
-
return screenToIso(screenX, screenY,
|
|
9742
|
-
}, [projection,
|
|
9780
|
+
return screenToIso(screenX, screenY, nativeTileW, baseOffsetX, projection);
|
|
9781
|
+
}, [projection, nativeTileW, baseOffsetX]);
|
|
9743
9782
|
const bgUrls = useMemo(() => backgroundImage ? [backgroundImage.url] : [], [backgroundImage]);
|
|
9744
9783
|
const { getImage, pendingCount: _imagePendingCount } = useImageCache(bgUrls);
|
|
9745
9784
|
useEffect(() => {
|
|
@@ -9766,9 +9805,7 @@ function Canvas2D({
|
|
|
9766
9805
|
zoomAtPoint,
|
|
9767
9806
|
screenToWorld,
|
|
9768
9807
|
lerpToTarget
|
|
9769
|
-
} = useCamera({ zoom:
|
|
9770
|
-
const [atlasVersion, setAtlasVersion] = useState(0);
|
|
9771
|
-
const bumpAtlas = useCallback(() => setAtlasVersion((v) => v + 1), []);
|
|
9808
|
+
} = useCamera({ zoom: effectiveZoom });
|
|
9772
9809
|
const miniMapTiles = useMemo(() => {
|
|
9773
9810
|
if (!showMinimap) return [];
|
|
9774
9811
|
const color = MINIMAP_TERRAIN_COLORS.default;
|
|
@@ -9843,6 +9880,13 @@ function Canvas2D({
|
|
|
9843
9880
|
useEffect(() => {
|
|
9844
9881
|
draw();
|
|
9845
9882
|
}, [_imagePendingCount, draw]);
|
|
9883
|
+
const userZoomedRef = useRef(false);
|
|
9884
|
+
useEffect(() => {
|
|
9885
|
+
if (userZoomedRef.current) return;
|
|
9886
|
+
if (cameraRef.current.zoom === effectiveZoom) return;
|
|
9887
|
+
cameraRef.current.zoom = effectiveZoom;
|
|
9888
|
+
draw();
|
|
9889
|
+
}, [effectiveZoom, cameraRef, draw]);
|
|
9846
9890
|
useEffect(() => {
|
|
9847
9891
|
draw();
|
|
9848
9892
|
}, [atlasVersion, draw]);
|
|
@@ -9899,7 +9943,9 @@ function Canvas2D({
|
|
|
9899
9943
|
if (tileLeaveEvent) eventBus.emit(`UI:${tileLeaveEvent}`, {});
|
|
9900
9944
|
}, [handleMouseLeave, tileLeaveEvent, eventBus]);
|
|
9901
9945
|
const applyZoom = useCallback((factor, centerX, centerY) => {
|
|
9902
|
-
if (enableCamera)
|
|
9946
|
+
if (!enableCamera) return;
|
|
9947
|
+
userZoomedRef.current = true;
|
|
9948
|
+
zoomAtPoint(factor, centerX, centerY, viewportSize, () => draw());
|
|
9903
9949
|
}, [enableCamera, zoomAtPoint, viewportSize, draw]);
|
|
9904
9950
|
const applyPanDelta = useCallback((dx, dy) => {
|
|
9905
9951
|
if (enableCamera) panBy(dx, dy, () => draw());
|
|
@@ -10084,6 +10130,8 @@ function Canvas({
|
|
|
10084
10130
|
isLoading,
|
|
10085
10131
|
unitScale,
|
|
10086
10132
|
showMinimap,
|
|
10133
|
+
fit,
|
|
10134
|
+
tileWidth,
|
|
10087
10135
|
backgroundImage,
|
|
10088
10136
|
backgroundColor,
|
|
10089
10137
|
worldWidth,
|
|
@@ -10141,6 +10189,8 @@ function Canvas({
|
|
|
10141
10189
|
projection,
|
|
10142
10190
|
camera: to2DCamera(camera?.mode),
|
|
10143
10191
|
...zoom !== void 0 ? { scale: zoom } : {},
|
|
10192
|
+
...fit !== void 0 ? { fit } : {},
|
|
10193
|
+
...tileWidth !== void 0 ? { tileWidth } : {},
|
|
10144
10194
|
...camera?.target !== void 0 ? { followTarget: camera.target } : {},
|
|
10145
10195
|
...camera?.pos !== void 0 ? { cameraPos: camera.pos } : {},
|
|
10146
10196
|
showMinimap,
|
|
@@ -10167,32 +10217,6 @@ var init_Canvas = __esm({
|
|
|
10167
10217
|
Canvas.displayName = "Canvas";
|
|
10168
10218
|
}
|
|
10169
10219
|
});
|
|
10170
|
-
function SvgDrawShapeLayer({
|
|
10171
|
-
items,
|
|
10172
|
-
fill,
|
|
10173
|
-
stroke,
|
|
10174
|
-
strokeWidth,
|
|
10175
|
-
opacity
|
|
10176
|
-
}) {
|
|
10177
|
-
return /* @__PURE__ */ jsx("g", { children: items.map(({ id, ...shape }) => /* @__PURE__ */ jsx(
|
|
10178
|
-
SvgDrawShape,
|
|
10179
|
-
{
|
|
10180
|
-
...shape,
|
|
10181
|
-
fill: shape.fill ?? fill,
|
|
10182
|
-
stroke: shape.stroke ?? stroke,
|
|
10183
|
-
strokeWidth: shape.strokeWidth ?? strokeWidth,
|
|
10184
|
-
opacity: shape.opacity ?? opacity
|
|
10185
|
-
},
|
|
10186
|
-
id
|
|
10187
|
-
)) });
|
|
10188
|
-
}
|
|
10189
|
-
var init_SvgDrawShapeLayer = __esm({
|
|
10190
|
-
"components/game/molecules/SvgDrawShapeLayer.tsx"() {
|
|
10191
|
-
"use client";
|
|
10192
|
-
init_SvgDrawShape();
|
|
10193
|
-
SvgDrawShapeLayer.displayName = "SvgDrawShapeLayer";
|
|
10194
|
-
}
|
|
10195
|
-
});
|
|
10196
10220
|
function GameAudioToggle({
|
|
10197
10221
|
size = "sm",
|
|
10198
10222
|
className,
|
|
@@ -23378,6 +23402,8 @@ function DataList({
|
|
|
23378
23402
|
hasMore,
|
|
23379
23403
|
children,
|
|
23380
23404
|
pageSize = 5,
|
|
23405
|
+
sortBy,
|
|
23406
|
+
sortDirection,
|
|
23381
23407
|
renderItem: schemaRenderItem,
|
|
23382
23408
|
dragGroup,
|
|
23383
23409
|
accepts,
|
|
@@ -23406,7 +23432,11 @@ function DataList({
|
|
|
23406
23432
|
dndItemIdField,
|
|
23407
23433
|
dndRoot
|
|
23408
23434
|
});
|
|
23409
|
-
const
|
|
23435
|
+
const orderedData = dnd.orderedItems;
|
|
23436
|
+
const allData = React83__default.useMemo(
|
|
23437
|
+
() => sortRows(orderedData, sortBy, sortDirection),
|
|
23438
|
+
[orderedData, sortBy, sortDirection]
|
|
23439
|
+
);
|
|
23410
23440
|
const data = pageSize > 0 ? allData.slice(0, visibleCount) : allData;
|
|
23411
23441
|
const hasMoreLocal = pageSize > 0 && visibleCount < allData.length;
|
|
23412
23442
|
const hasRenderProp = typeof children === "function";
|
|
@@ -23443,7 +23473,7 @@ function DataList({
|
|
|
23443
23473
|
};
|
|
23444
23474
|
eventBus.emit(`UI:${action.event}`, payload);
|
|
23445
23475
|
};
|
|
23446
|
-
const renderItemActions = (itemData) => {
|
|
23476
|
+
const renderItemActions = (itemData, onPrimary = false) => {
|
|
23447
23477
|
if (!itemActions || itemActions.length === 0) return null;
|
|
23448
23478
|
const inline = maxInlineActions != null ? itemActions.slice(0, maxInlineActions) : itemActions;
|
|
23449
23479
|
const overflow = maxInlineActions != null ? itemActions.slice(maxInlineActions) : [];
|
|
@@ -23456,7 +23486,12 @@ function DataList({
|
|
|
23456
23486
|
onClick: handleActionClick(action, itemData),
|
|
23457
23487
|
"data-testid": `action-${action.event}`,
|
|
23458
23488
|
"data-row-id": String(itemData.id),
|
|
23459
|
-
className: cn(
|
|
23489
|
+
className: cn(
|
|
23490
|
+
action.variant === "danger" && "text-error hover:bg-error/10",
|
|
23491
|
+
// Must sit on the Button itself: the variant's own text colour
|
|
23492
|
+
// beats an inherited one from the row wrapper.
|
|
23493
|
+
onPrimary && "!text-primary-foreground hover:bg-primary-foreground/15"
|
|
23494
|
+
),
|
|
23460
23495
|
children: [
|
|
23461
23496
|
action.icon && renderIconInput2(action.icon, { size: "xs", className: "mr-1" }),
|
|
23462
23497
|
action.label
|
|
@@ -23556,7 +23591,11 @@ function DataList({
|
|
|
23556
23591
|
metaFields.length > 0 && /* @__PURE__ */ jsx(HStack, { gap: "xs", className: "mt-1 flex-wrap", children: metaFields.map((f3) => {
|
|
23557
23592
|
const v = getNestedValue(itemData, f3.name);
|
|
23558
23593
|
if (v === void 0 || v === null || v === "") return null;
|
|
23559
|
-
return f3.variant === "badge" ?
|
|
23594
|
+
return f3.variant === "badge" ? (
|
|
23595
|
+
// `format` applies here too — a boolean field badged
|
|
23596
|
+
// without it renders the raw "false" instead of "No".
|
|
23597
|
+
/* @__PURE__ */ jsx(Badge, { variant: statusVariant3(String(v)), children: formatValue2(v, f3.format) }, f3.name)
|
|
23598
|
+
) : /* @__PURE__ */ jsx(
|
|
23560
23599
|
Typography,
|
|
23561
23600
|
{
|
|
23562
23601
|
variant: "caption",
|
|
@@ -23575,7 +23614,7 @@ function DataList({
|
|
|
23575
23614
|
children: formatDate(timestamp)
|
|
23576
23615
|
}
|
|
23577
23616
|
) : /* @__PURE__ */ jsx("span", {}),
|
|
23578
|
-
renderItemActions(itemData)
|
|
23617
|
+
renderItemActions(itemData, isSent)
|
|
23579
23618
|
] })
|
|
23580
23619
|
]
|
|
23581
23620
|
}
|
|
@@ -23668,7 +23707,7 @@ function DataList({
|
|
|
23668
23707
|
if (val === void 0 || val === null) return null;
|
|
23669
23708
|
return /* @__PURE__ */ jsxs(HStack, { gap: "xs", className: "items-center flex-shrink-0", children: [
|
|
23670
23709
|
field.icon && renderIconInput2(field.icon, { size: "xs" }),
|
|
23671
|
-
/* @__PURE__ */ jsx(Badge, { variant: statusVariant3(String(val)), children:
|
|
23710
|
+
/* @__PURE__ */ jsx(Badge, { variant: statusVariant3(String(val)), children: formatValue2(val, field.format) })
|
|
23672
23711
|
] }, field.name);
|
|
23673
23712
|
})
|
|
23674
23713
|
] }),
|
|
@@ -23907,6 +23946,182 @@ var init_FormSection = __esm({
|
|
|
23907
23946
|
FormActions.displayName = "FormActions";
|
|
23908
23947
|
}
|
|
23909
23948
|
});
|
|
23949
|
+
var ALL_CATEGORY, MAX_RENDERED, GridPicker;
|
|
23950
|
+
var init_GridPicker = __esm({
|
|
23951
|
+
"components/core/molecules/GridPicker.tsx"() {
|
|
23952
|
+
"use client";
|
|
23953
|
+
init_cn();
|
|
23954
|
+
init_Input();
|
|
23955
|
+
init_Badge();
|
|
23956
|
+
init_Stack();
|
|
23957
|
+
ALL_CATEGORY = "__all__";
|
|
23958
|
+
MAX_RENDERED = 300;
|
|
23959
|
+
GridPicker = ({
|
|
23960
|
+
items,
|
|
23961
|
+
value,
|
|
23962
|
+
onChange,
|
|
23963
|
+
categories,
|
|
23964
|
+
searchPlaceholder,
|
|
23965
|
+
renderThumbnail,
|
|
23966
|
+
cellSize = 32,
|
|
23967
|
+
className
|
|
23968
|
+
}) => {
|
|
23969
|
+
const [search, setSearch] = useState("");
|
|
23970
|
+
const [activeCategory, setActiveCategory] = useState(ALL_CATEGORY);
|
|
23971
|
+
const gridRef = useRef(null);
|
|
23972
|
+
const categoryChips = useMemo(() => {
|
|
23973
|
+
if (categories !== void 0) return categories;
|
|
23974
|
+
const seen = [];
|
|
23975
|
+
for (const item of items) {
|
|
23976
|
+
if (!seen.includes(item.category)) seen.push(item.category);
|
|
23977
|
+
}
|
|
23978
|
+
return seen;
|
|
23979
|
+
}, [categories, items]);
|
|
23980
|
+
const filtered = useMemo(() => {
|
|
23981
|
+
const needle = search.trim().toLowerCase();
|
|
23982
|
+
return items.filter((item) => {
|
|
23983
|
+
const matchesCategory = activeCategory === ALL_CATEGORY || item.category === activeCategory;
|
|
23984
|
+
const matchesSearch = needle === "" || item.label.toLowerCase().includes(needle) || item.keywords !== void 0 && item.keywords.some((k) => k.toLowerCase().includes(needle));
|
|
23985
|
+
return matchesCategory && matchesSearch;
|
|
23986
|
+
});
|
|
23987
|
+
}, [items, search, activeCategory]);
|
|
23988
|
+
const visible = useMemo(() => filtered.slice(0, MAX_RENDERED), [filtered]);
|
|
23989
|
+
const truncated = filtered.length - visible.length;
|
|
23990
|
+
const select = useCallback(
|
|
23991
|
+
(item) => {
|
|
23992
|
+
onChange(item.id);
|
|
23993
|
+
},
|
|
23994
|
+
[onChange]
|
|
23995
|
+
);
|
|
23996
|
+
const handleKeyDown = useCallback(
|
|
23997
|
+
(e, index) => {
|
|
23998
|
+
const cells = gridRef.current?.querySelectorAll(
|
|
23999
|
+
"[data-gridpicker-cell]"
|
|
24000
|
+
);
|
|
24001
|
+
if (cells === void 0 || cells.length === 0) return;
|
|
24002
|
+
const columns = (() => {
|
|
24003
|
+
const grid = gridRef.current;
|
|
24004
|
+
if (grid === null) return 1;
|
|
24005
|
+
const style = window.getComputedStyle(grid);
|
|
24006
|
+
const cols = style.gridTemplateColumns.split(" ").filter(Boolean).length;
|
|
24007
|
+
return cols > 0 ? cols : 1;
|
|
24008
|
+
})();
|
|
24009
|
+
let next = -1;
|
|
24010
|
+
if (e.key === "ArrowRight") next = index + 1;
|
|
24011
|
+
else if (e.key === "ArrowLeft") next = index - 1;
|
|
24012
|
+
else if (e.key === "ArrowDown") next = index + columns;
|
|
24013
|
+
else if (e.key === "ArrowUp") next = index - columns;
|
|
24014
|
+
else if (e.key === "Enter" || e.key === " ") {
|
|
24015
|
+
e.preventDefault();
|
|
24016
|
+
select(filtered[index]);
|
|
24017
|
+
return;
|
|
24018
|
+
} else {
|
|
24019
|
+
return;
|
|
24020
|
+
}
|
|
24021
|
+
e.preventDefault();
|
|
24022
|
+
if (next >= 0 && next < cells.length) {
|
|
24023
|
+
cells[next].focus();
|
|
24024
|
+
}
|
|
24025
|
+
},
|
|
24026
|
+
[filtered, select]
|
|
24027
|
+
);
|
|
24028
|
+
return /* @__PURE__ */ jsxs(VStack, { gap: "sm", className: cn("w-full", className), children: [
|
|
24029
|
+
/* @__PURE__ */ jsx(
|
|
24030
|
+
Input,
|
|
24031
|
+
{
|
|
24032
|
+
type: "search",
|
|
24033
|
+
icon: "search",
|
|
24034
|
+
value: search,
|
|
24035
|
+
placeholder: searchPlaceholder,
|
|
24036
|
+
clearable: true,
|
|
24037
|
+
onClear: () => setSearch(""),
|
|
24038
|
+
onChange: (e) => setSearch(e.target.value)
|
|
24039
|
+
}
|
|
24040
|
+
),
|
|
24041
|
+
categoryChips.length > 0 && /* @__PURE__ */ jsxs(HStack, { gap: "xs", wrap: true, children: [
|
|
24042
|
+
/* @__PURE__ */ jsx(
|
|
24043
|
+
Badge,
|
|
24044
|
+
{
|
|
24045
|
+
variant: activeCategory === ALL_CATEGORY ? "primary" : "neutral",
|
|
24046
|
+
size: "sm",
|
|
24047
|
+
role: "button",
|
|
24048
|
+
tabIndex: 0,
|
|
24049
|
+
"aria-pressed": activeCategory === ALL_CATEGORY,
|
|
24050
|
+
className: "cursor-pointer",
|
|
24051
|
+
onClick: () => setActiveCategory(ALL_CATEGORY),
|
|
24052
|
+
onKeyDown: (e) => {
|
|
24053
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
24054
|
+
e.preventDefault();
|
|
24055
|
+
setActiveCategory(ALL_CATEGORY);
|
|
24056
|
+
}
|
|
24057
|
+
},
|
|
24058
|
+
children: "All"
|
|
24059
|
+
}
|
|
24060
|
+
),
|
|
24061
|
+
categoryChips.map((category) => /* @__PURE__ */ jsx(
|
|
24062
|
+
Badge,
|
|
24063
|
+
{
|
|
24064
|
+
variant: activeCategory === category ? "primary" : "neutral",
|
|
24065
|
+
size: "sm",
|
|
24066
|
+
role: "button",
|
|
24067
|
+
tabIndex: 0,
|
|
24068
|
+
"aria-pressed": activeCategory === category,
|
|
24069
|
+
className: "cursor-pointer",
|
|
24070
|
+
onClick: () => setActiveCategory(category),
|
|
24071
|
+
onKeyDown: (e) => {
|
|
24072
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
24073
|
+
e.preventDefault();
|
|
24074
|
+
setActiveCategory(category);
|
|
24075
|
+
}
|
|
24076
|
+
},
|
|
24077
|
+
children: category
|
|
24078
|
+
},
|
|
24079
|
+
category
|
|
24080
|
+
))
|
|
24081
|
+
] }),
|
|
24082
|
+
/* @__PURE__ */ jsx(
|
|
24083
|
+
"div",
|
|
24084
|
+
{
|
|
24085
|
+
ref: gridRef,
|
|
24086
|
+
role: "listbox",
|
|
24087
|
+
className: "grid gap-1 overflow-y-auto max-h-64 p-1",
|
|
24088
|
+
style: {
|
|
24089
|
+
gridTemplateColumns: `repeat(auto-fill, minmax(${cellSize}px, 1fr))`
|
|
24090
|
+
},
|
|
24091
|
+
children: visible.map((item, index) => {
|
|
24092
|
+
const selected = item.id === value;
|
|
24093
|
+
return /* @__PURE__ */ jsx(
|
|
24094
|
+
"button",
|
|
24095
|
+
{
|
|
24096
|
+
type: "button",
|
|
24097
|
+
role: "option",
|
|
24098
|
+
"aria-selected": selected,
|
|
24099
|
+
"aria-label": item.label,
|
|
24100
|
+
title: item.label,
|
|
24101
|
+
"data-gridpicker-cell": true,
|
|
24102
|
+
tabIndex: selected || value === void 0 && index === 0 ? 0 : -1,
|
|
24103
|
+
onClick: () => select(item),
|
|
24104
|
+
onKeyDown: (e) => handleKeyDown(e, index),
|
|
24105
|
+
className: cn(
|
|
24106
|
+
"flex items-center justify-center rounded-sm",
|
|
24107
|
+
"transition-colors hover:bg-muted",
|
|
24108
|
+
"focus:outline-none focus:ring-1 focus:ring-ring",
|
|
24109
|
+
selected && "bg-primary/10 ring-1 ring-primary"
|
|
24110
|
+
),
|
|
24111
|
+
style: { width: cellSize, height: cellSize },
|
|
24112
|
+
children: renderThumbnail(item)
|
|
24113
|
+
},
|
|
24114
|
+
item.id
|
|
24115
|
+
);
|
|
24116
|
+
})
|
|
24117
|
+
}
|
|
24118
|
+
),
|
|
24119
|
+
truncated > 0 && /* @__PURE__ */ jsx("div", { className: "px-1 text-xs text-muted-foreground", children: `+${truncated} more \u2014 refine your search` })
|
|
24120
|
+
] });
|
|
24121
|
+
};
|
|
24122
|
+
GridPicker.displayName = "GridPicker";
|
|
24123
|
+
}
|
|
24124
|
+
});
|
|
23910
24125
|
function fileIcon(name) {
|
|
23911
24126
|
const ext = name.split(".").pop()?.toLowerCase() ?? "";
|
|
23912
24127
|
switch (ext) {
|
|
@@ -24871,9 +25086,16 @@ var init_Popover = __esm({
|
|
|
24871
25086
|
position = "bottom",
|
|
24872
25087
|
trigger = "click",
|
|
24873
25088
|
showArrow = true,
|
|
25089
|
+
open,
|
|
25090
|
+
onOpenChange,
|
|
24874
25091
|
className
|
|
24875
25092
|
}) => {
|
|
24876
|
-
const [
|
|
25093
|
+
const [uncontrolledOpen, setUncontrolledOpen] = useState(false);
|
|
25094
|
+
const isOpen = open !== void 0 ? open : uncontrolledOpen;
|
|
25095
|
+
const setIsOpen = (next) => {
|
|
25096
|
+
if (open === void 0) setUncontrolledOpen(next);
|
|
25097
|
+
onOpenChange?.(next);
|
|
25098
|
+
};
|
|
24877
25099
|
const [triggerRect, setTriggerRect] = useState(null);
|
|
24878
25100
|
const [popoverWidth, setPopoverWidth] = useState(0);
|
|
24879
25101
|
const triggerRef = useRef(null);
|
|
@@ -24906,6 +25128,23 @@ var init_Popover = __esm({
|
|
|
24906
25128
|
updatePosition();
|
|
24907
25129
|
}
|
|
24908
25130
|
}, [isOpen]);
|
|
25131
|
+
useEffect(() => {
|
|
25132
|
+
if (!isOpen) return;
|
|
25133
|
+
let raf = 0;
|
|
25134
|
+
let lastTop = Number.NaN;
|
|
25135
|
+
let lastLeft = Number.NaN;
|
|
25136
|
+
const track = () => {
|
|
25137
|
+
const rect = triggerRef.current?.getBoundingClientRect();
|
|
25138
|
+
if (rect && (rect.top !== lastTop || rect.left !== lastLeft)) {
|
|
25139
|
+
lastTop = rect.top;
|
|
25140
|
+
lastLeft = rect.left;
|
|
25141
|
+
updatePosition();
|
|
25142
|
+
}
|
|
25143
|
+
raf = requestAnimationFrame(track);
|
|
25144
|
+
};
|
|
25145
|
+
raf = requestAnimationFrame(track);
|
|
25146
|
+
return () => cancelAnimationFrame(raf);
|
|
25147
|
+
}, [isOpen]);
|
|
24909
25148
|
useEffect(() => {
|
|
24910
25149
|
if (!mounted) setPopoverWidth(0);
|
|
24911
25150
|
}, [mounted]);
|
|
@@ -26254,6 +26493,80 @@ var init_FlipCard = __esm({
|
|
|
26254
26493
|
FlipCard.displayName = "FlipCard";
|
|
26255
26494
|
}
|
|
26256
26495
|
});
|
|
26496
|
+
var EMOJI_ITEMS, EmojiPicker;
|
|
26497
|
+
var init_EmojiPicker = __esm({
|
|
26498
|
+
"components/core/molecules/EmojiPicker.tsx"() {
|
|
26499
|
+
"use client";
|
|
26500
|
+
init_useEventBus();
|
|
26501
|
+
init_Button();
|
|
26502
|
+
init_GridPicker();
|
|
26503
|
+
init_Popover();
|
|
26504
|
+
EMOJI_ITEMS = (() => {
|
|
26505
|
+
const items = [];
|
|
26506
|
+
for (const name of ordered) {
|
|
26507
|
+
const entry = lib[name];
|
|
26508
|
+
if (entry === void 0 || entry.char === null || entry.char === "") continue;
|
|
26509
|
+
items.push({
|
|
26510
|
+
id: entry.char,
|
|
26511
|
+
label: name.replace(/_/g, " "),
|
|
26512
|
+
category: entry.category.replace(/_/g, " "),
|
|
26513
|
+
keywords: entry.keywords
|
|
26514
|
+
});
|
|
26515
|
+
}
|
|
26516
|
+
return items;
|
|
26517
|
+
})();
|
|
26518
|
+
EmojiPicker = ({
|
|
26519
|
+
pickEvent,
|
|
26520
|
+
position = "top",
|
|
26521
|
+
triggerIcon = "smile",
|
|
26522
|
+
triggerLabel = "Add emoji",
|
|
26523
|
+
className
|
|
26524
|
+
}) => {
|
|
26525
|
+
const eventBus = useEventBus();
|
|
26526
|
+
const [open, setOpen] = useState(false);
|
|
26527
|
+
const handlePick = (glyph) => {
|
|
26528
|
+
if (pickEvent !== void 0) {
|
|
26529
|
+
const payload = { emoji: glyph };
|
|
26530
|
+
eventBus.emit(`UI:${pickEvent}`, payload);
|
|
26531
|
+
}
|
|
26532
|
+
setOpen(false);
|
|
26533
|
+
};
|
|
26534
|
+
return /* @__PURE__ */ jsx(
|
|
26535
|
+
Popover,
|
|
26536
|
+
{
|
|
26537
|
+
position,
|
|
26538
|
+
trigger: "click",
|
|
26539
|
+
showArrow: false,
|
|
26540
|
+
open,
|
|
26541
|
+
onOpenChange: setOpen,
|
|
26542
|
+
content: /* @__PURE__ */ jsx(
|
|
26543
|
+
GridPicker,
|
|
26544
|
+
{
|
|
26545
|
+
items: EMOJI_ITEMS,
|
|
26546
|
+
onChange: handlePick,
|
|
26547
|
+
searchPlaceholder: "Search emoji\u2026",
|
|
26548
|
+
renderThumbnail: (item) => /* @__PURE__ */ jsx("span", { className: "text-xl leading-none", "aria-hidden": "true", children: item.id }),
|
|
26549
|
+
cellSize: 32,
|
|
26550
|
+
className: "w-80"
|
|
26551
|
+
}
|
|
26552
|
+
),
|
|
26553
|
+
children: /* @__PURE__ */ jsx(
|
|
26554
|
+
Button,
|
|
26555
|
+
{
|
|
26556
|
+
variant: "ghost",
|
|
26557
|
+
icon: triggerIcon,
|
|
26558
|
+
"aria-label": triggerLabel,
|
|
26559
|
+
title: triggerLabel,
|
|
26560
|
+
className,
|
|
26561
|
+
"data-testid": "emoji-picker-trigger"
|
|
26562
|
+
}
|
|
26563
|
+
)
|
|
26564
|
+
}
|
|
26565
|
+
);
|
|
26566
|
+
};
|
|
26567
|
+
EmojiPicker.displayName = "EmojiPicker";
|
|
26568
|
+
}
|
|
26569
|
+
});
|
|
26257
26570
|
function toISODate(d) {
|
|
26258
26571
|
return d.toISOString().slice(0, 10);
|
|
26259
26572
|
}
|
|
@@ -27206,13 +27519,13 @@ var init_MapView = __esm({
|
|
|
27206
27519
|
shadowSize: [41, 41]
|
|
27207
27520
|
});
|
|
27208
27521
|
L.Marker.prototype.options.icon = defaultIcon;
|
|
27209
|
-
const { useEffect:
|
|
27522
|
+
const { useEffect: useEffect59, useRef: useRef61, useCallback: useCallback89, useState: useState91 } = React83__default;
|
|
27210
27523
|
const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
|
|
27211
27524
|
const { useEventBus: useEventBus2 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
|
|
27212
27525
|
function MapUpdater({ centerLat, centerLng, zoom }) {
|
|
27213
27526
|
const map = useMap();
|
|
27214
27527
|
const prevRef = useRef61({ centerLat, centerLng, zoom });
|
|
27215
|
-
|
|
27528
|
+
useEffect59(() => {
|
|
27216
27529
|
const prev = prevRef.current;
|
|
27217
27530
|
if (prev.centerLat !== centerLat || prev.centerLng !== centerLng || prev.zoom !== zoom) {
|
|
27218
27531
|
map.setView([centerLat, centerLng], zoom);
|
|
@@ -27223,7 +27536,7 @@ var init_MapView = __esm({
|
|
|
27223
27536
|
}
|
|
27224
27537
|
function MapClickHandler({ onMapClick }) {
|
|
27225
27538
|
const map = useMap();
|
|
27226
|
-
|
|
27539
|
+
useEffect59(() => {
|
|
27227
27540
|
if (!onMapClick) return;
|
|
27228
27541
|
const handler = (e) => {
|
|
27229
27542
|
onMapClick(e.latlng.lat, e.latlng.lng);
|
|
@@ -27251,7 +27564,7 @@ var init_MapView = __esm({
|
|
|
27251
27564
|
showAttribution = true
|
|
27252
27565
|
}) {
|
|
27253
27566
|
const eventBus = useEventBus2();
|
|
27254
|
-
const [clickedPosition, setClickedPosition] =
|
|
27567
|
+
const [clickedPosition, setClickedPosition] = useState91(null);
|
|
27255
27568
|
const handleMapClick = useCallback89((lat, lng) => {
|
|
27256
27569
|
if (showClickedPin) {
|
|
27257
27570
|
setClickedPosition({ lat, lng });
|
|
@@ -28076,6 +28389,7 @@ function TableView({
|
|
|
28076
28389
|
fields,
|
|
28077
28390
|
itemActions,
|
|
28078
28391
|
maxInlineActions,
|
|
28392
|
+
itemClickEvent,
|
|
28079
28393
|
selectable = false,
|
|
28080
28394
|
selectEvent,
|
|
28081
28395
|
selectedIds,
|
|
@@ -28120,9 +28434,9 @@ function TableView({
|
|
|
28120
28434
|
dndItemIdField,
|
|
28121
28435
|
dndRoot
|
|
28122
28436
|
});
|
|
28123
|
-
const
|
|
28124
|
-
const data = pageSize > 0 ?
|
|
28125
|
-
const hasMore = pageSize > 0 && visibleCount <
|
|
28437
|
+
const ordered2 = dnd.orderedItems;
|
|
28438
|
+
const data = pageSize > 0 ? ordered2.slice(0, visibleCount) : ordered2;
|
|
28439
|
+
const hasMore = pageSize > 0 && visibleCount < ordered2.length;
|
|
28126
28440
|
const hasRenderProp = typeof children === "function";
|
|
28127
28441
|
const idField = dndItemIdField ?? "id";
|
|
28128
28442
|
const isCoarsePointer = useMediaQuery("(pointer: coarse)");
|
|
@@ -28175,6 +28489,14 @@ function TableView({
|
|
|
28175
28489
|
};
|
|
28176
28490
|
eventBus.emit(`UI:${action.event}`, payload);
|
|
28177
28491
|
};
|
|
28492
|
+
const handleRowClick = (row) => () => {
|
|
28493
|
+
if (!itemClickEvent) return;
|
|
28494
|
+
const payload = {
|
|
28495
|
+
id: row.id,
|
|
28496
|
+
row
|
|
28497
|
+
};
|
|
28498
|
+
eventBus.emit(`UI:${itemClickEvent}`, payload);
|
|
28499
|
+
};
|
|
28178
28500
|
const colFloors = React83__default.useMemo(
|
|
28179
28501
|
() => colDefs.map((col) => {
|
|
28180
28502
|
const longest = data.reduce((widest, row) => {
|
|
@@ -28251,10 +28573,12 @@ function TableView({
|
|
|
28251
28573
|
role: "row",
|
|
28252
28574
|
"data-entity-row": true,
|
|
28253
28575
|
"data-entity-id": id,
|
|
28576
|
+
onClick: itemClickEvent ? handleRowClick(row) : void 0,
|
|
28254
28577
|
style: !hasRenderProp ? { gridTemplateColumns } : void 0,
|
|
28255
28578
|
className: cn(
|
|
28256
28579
|
"group items-center gap-3 transition-colors duration-fast",
|
|
28257
28580
|
hasRenderProp ? "flex" : "grid",
|
|
28581
|
+
itemClickEvent && "cursor-pointer",
|
|
28258
28582
|
lk.rowPad,
|
|
28259
28583
|
lk.divider && "border-b border-[var(--color-border)]",
|
|
28260
28584
|
lk.striped && index % 2 === 1 && "bg-[var(--color-surface-subtle)]",
|
|
@@ -28262,7 +28586,7 @@ function TableView({
|
|
|
28262
28586
|
look === "bordered" && "[&>*]:border-r [&>*]:border-[var(--color-border)] [&>*:last-child]:border-r-0"
|
|
28263
28587
|
),
|
|
28264
28588
|
children: [
|
|
28265
|
-
selectable && /* @__PURE__ */ jsx(Box, { className: "flex items-center", children: /* @__PURE__ */ jsx(
|
|
28589
|
+
selectable && /* @__PURE__ */ jsx(Box, { className: "flex items-center", onClick: itemClickEvent ? (e) => e.stopPropagation() : void 0, children: /* @__PURE__ */ jsx(
|
|
28266
28590
|
Checkbox,
|
|
28267
28591
|
{
|
|
28268
28592
|
checked: selected.has(id),
|
|
@@ -28287,6 +28611,7 @@ function TableView({
|
|
|
28287
28611
|
HStack,
|
|
28288
28612
|
{
|
|
28289
28613
|
gap: "xs",
|
|
28614
|
+
onClick: itemClickEvent ? (e) => e.stopPropagation() : void 0,
|
|
28290
28615
|
className: cn(
|
|
28291
28616
|
// Pinned: the fixed column tracks routinely overflow the caller's
|
|
28292
28617
|
// scroll container, which used to leave the actions off-screen.
|
|
@@ -28356,7 +28681,7 @@ function TableView({
|
|
|
28356
28681
|
/* @__PURE__ */ jsx(Icon, { name: "chevron-down", size: "xs", className: "mr-1" }),
|
|
28357
28682
|
t("common.showMore"),
|
|
28358
28683
|
" (",
|
|
28359
|
-
t("common.remaining", { count:
|
|
28684
|
+
t("common.remaining", { count: ordered2.length - visibleCount }),
|
|
28360
28685
|
")"
|
|
28361
28686
|
] }) })
|
|
28362
28687
|
]
|
|
@@ -37657,6 +37982,16 @@ var init_DetailPanel = __esm({
|
|
|
37657
37982
|
DetailPanel.displayName = "DetailPanel";
|
|
37658
37983
|
}
|
|
37659
37984
|
});
|
|
37985
|
+
|
|
37986
|
+
// components/game/atoms/DrawGroup.tsx
|
|
37987
|
+
function DrawGroup(_props) {
|
|
37988
|
+
return null;
|
|
37989
|
+
}
|
|
37990
|
+
var init_DrawGroup = __esm({
|
|
37991
|
+
"components/game/atoms/DrawGroup.tsx"() {
|
|
37992
|
+
"use client";
|
|
37993
|
+
}
|
|
37994
|
+
});
|
|
37660
37995
|
function extractTitle(children) {
|
|
37661
37996
|
if (!React83__default.isValidElement(children)) return void 0;
|
|
37662
37997
|
const props = children.props;
|
|
@@ -43379,6 +43714,7 @@ var init_component_registry_generated = __esm({
|
|
|
43379
43714
|
init_DocSidebar();
|
|
43380
43715
|
init_DocTOC();
|
|
43381
43716
|
init_DocumentViewer();
|
|
43717
|
+
init_DrawGroup();
|
|
43382
43718
|
init_DrawShape();
|
|
43383
43719
|
init_DrawShapeLayer();
|
|
43384
43720
|
init_DrawSprite();
|
|
@@ -43388,6 +43724,7 @@ var init_component_registry_generated = __esm({
|
|
|
43388
43724
|
init_Drawer();
|
|
43389
43725
|
init_DrawerSlot();
|
|
43390
43726
|
init_EdgeDecoration();
|
|
43727
|
+
init_EmojiPicker();
|
|
43391
43728
|
init_EmptyState();
|
|
43392
43729
|
init_ErrorBoundary();
|
|
43393
43730
|
init_ErrorState();
|
|
@@ -43522,10 +43859,6 @@ var init_component_registry_generated = __esm({
|
|
|
43522
43859
|
init_SubagentTracePanel();
|
|
43523
43860
|
init_SvgBranch();
|
|
43524
43861
|
init_SvgConnection();
|
|
43525
|
-
init_SvgDrawGroup();
|
|
43526
|
-
init_SvgDrawShape();
|
|
43527
|
-
init_SvgDrawShapeLayer();
|
|
43528
|
-
init_SvgDrawText();
|
|
43529
43862
|
init_SvgFlow();
|
|
43530
43863
|
init_SvgGrid();
|
|
43531
43864
|
init_SvgLobe();
|
|
@@ -43536,7 +43869,6 @@ var init_component_registry_generated = __esm({
|
|
|
43536
43869
|
init_SvgRing();
|
|
43537
43870
|
init_SvgShield();
|
|
43538
43871
|
init_SvgStack();
|
|
43539
|
-
init_SvgStage();
|
|
43540
43872
|
init_SwipeableRow();
|
|
43541
43873
|
init_Switch();
|
|
43542
43874
|
init_TabbedContainer();
|
|
@@ -43650,6 +43982,7 @@ var init_component_registry_generated = __esm({
|
|
|
43650
43982
|
"DocSidebar": DocSidebar,
|
|
43651
43983
|
"DocTOC": DocTOC,
|
|
43652
43984
|
"DocumentViewer": DocumentViewer,
|
|
43985
|
+
"DrawGroup": DrawGroup,
|
|
43653
43986
|
"DrawShape": DrawShape,
|
|
43654
43987
|
"DrawShapeLayer": DrawShapeLayer,
|
|
43655
43988
|
"DrawSprite": DrawSprite,
|
|
@@ -43659,6 +43992,7 @@ var init_component_registry_generated = __esm({
|
|
|
43659
43992
|
"Drawer": Drawer,
|
|
43660
43993
|
"DrawerSlot": DrawerSlot,
|
|
43661
43994
|
"EdgeDecoration": EdgeDecoration,
|
|
43995
|
+
"EmojiPicker": EmojiPicker,
|
|
43662
43996
|
"EmptyState": EmptyState,
|
|
43663
43997
|
"ErrorBoundary": ErrorBoundary,
|
|
43664
43998
|
"ErrorState": ErrorState,
|
|
@@ -43798,10 +44132,6 @@ var init_component_registry_generated = __esm({
|
|
|
43798
44132
|
"SubagentTracePanel": SubagentTracePanel,
|
|
43799
44133
|
"SvgBranch": SvgBranch,
|
|
43800
44134
|
"SvgConnection": SvgConnection,
|
|
43801
|
-
"SvgDrawGroup": SvgDrawGroup,
|
|
43802
|
-
"SvgDrawShape": SvgDrawShape,
|
|
43803
|
-
"SvgDrawShapeLayer": SvgDrawShapeLayer,
|
|
43804
|
-
"SvgDrawText": SvgDrawText,
|
|
43805
44135
|
"SvgFlow": SvgFlow,
|
|
43806
44136
|
"SvgGrid": SvgGrid,
|
|
43807
44137
|
"SvgLobe": SvgLobe,
|
|
@@ -43812,7 +44142,6 @@ var init_component_registry_generated = __esm({
|
|
|
43812
44142
|
"SvgRing": SvgRing,
|
|
43813
44143
|
"SvgShield": SvgShield,
|
|
43814
44144
|
"SvgStack": SvgStack,
|
|
43815
|
-
"SvgStage": SvgStage,
|
|
43816
44145
|
"SwipeableRow": SwipeableRow,
|
|
43817
44146
|
"Switch": Switch,
|
|
43818
44147
|
"TabbedContainer": TabbedContainer,
|
|
@@ -44091,7 +44420,19 @@ function UISlotComponent({
|
|
|
44091
44420
|
const suspenseConfig = useContext(SuspenseConfigContext);
|
|
44092
44421
|
const contained = useContext(SlotContainedContext);
|
|
44093
44422
|
const schemaCtx = useEntitySchemaOptional();
|
|
44094
|
-
const
|
|
44423
|
+
const rawContent = slots[slot];
|
|
44424
|
+
const binding = useEntityBindingSnapshot(rawContent?.sourceTrait);
|
|
44425
|
+
const content = useMemo(() => {
|
|
44426
|
+
if (!rawContent) return rawContent;
|
|
44427
|
+
const resolvedProps = resolveRenderBindingMarkers(
|
|
44428
|
+
rawContent.props,
|
|
44429
|
+
rawContent.sourceTrait,
|
|
44430
|
+
binding.entity,
|
|
44431
|
+
binding.config,
|
|
44432
|
+
binding.state
|
|
44433
|
+
);
|
|
44434
|
+
return resolvedProps === rawContent.props ? rawContent : { ...rawContent, props: resolvedProps };
|
|
44435
|
+
}, [rawContent, binding.entity, binding.config, binding.state]);
|
|
44095
44436
|
if (children !== void 0) {
|
|
44096
44437
|
if (pattern === "clear") {
|
|
44097
44438
|
return null;
|
|
@@ -44435,6 +44776,7 @@ function isPlainConfigObject(value) {
|
|
|
44435
44776
|
return proto === Object.prototype || proto === null;
|
|
44436
44777
|
}
|
|
44437
44778
|
function substituteTraitRefsDeep(value, pathKey) {
|
|
44779
|
+
if (isRenderBindingMarker(value)) return value;
|
|
44438
44780
|
if (typeof value === "string") {
|
|
44439
44781
|
const match = TRAIT_BINDING_RE.exec(value);
|
|
44440
44782
|
if (match) {
|
|
@@ -44507,7 +44849,14 @@ function SlotContentRenderer({
|
|
|
44507
44849
|
onDismiss,
|
|
44508
44850
|
patternPath
|
|
44509
44851
|
}) {
|
|
44510
|
-
const
|
|
44852
|
+
const ambientScope = useTraitScope();
|
|
44853
|
+
const bindingTrait = content.sourceTrait ?? ambientScope?.trait;
|
|
44854
|
+
const binding = useEntityBindingSnapshot(bindingTrait);
|
|
44855
|
+
const liveProps = useMemo(
|
|
44856
|
+
() => resolveRenderBindingMarkers(content.props, bindingTrait, binding.entity, binding.config, binding.state),
|
|
44857
|
+
[content.props, bindingTrait, binding.entity, binding.config, binding.state]
|
|
44858
|
+
);
|
|
44859
|
+
const entityProp = liveProps.entity;
|
|
44511
44860
|
if (content.pattern === "form-section") {
|
|
44512
44861
|
slotLog.debug("SlotContentRenderer:form-section-render", {
|
|
44513
44862
|
contentId: content.id,
|
|
@@ -44538,7 +44887,7 @@ function SlotContentRenderer({
|
|
|
44538
44887
|
const orbitalName = schemaCtx && content.sourceTrait !== void 0 ? schemaCtx.orbitalsByTrait.get(content.sourceTrait) : void 0;
|
|
44539
44888
|
const PatternComponent = getComponentForPattern(content.pattern);
|
|
44540
44889
|
if (PatternComponent) {
|
|
44541
|
-
const childrenConfig =
|
|
44890
|
+
const childrenConfig = liveProps.children;
|
|
44542
44891
|
const isSingleChild = typeof childrenConfig === "string" || typeof childrenConfig === "object" && childrenConfig !== null && !Array.isArray(childrenConfig) && "type" in childrenConfig;
|
|
44543
44892
|
const hasChildren = PATTERNS_WITH_CHILDREN.has(content.pattern) || Array.isArray(childrenConfig) && childrenConfig.length > 0 || isSingleChild;
|
|
44544
44893
|
const isDrawHost = isDrawHostPattern(content.pattern);
|
|
@@ -44549,9 +44898,9 @@ function SlotContentRenderer({
|
|
|
44549
44898
|
fromState: content.fromState,
|
|
44550
44899
|
entity: content.entity
|
|
44551
44900
|
}) : void 0;
|
|
44552
|
-
const incomingChildren =
|
|
44901
|
+
const incomingChildren = liveProps.children;
|
|
44553
44902
|
const childrenIsRenderFn = typeof incomingChildren === "function";
|
|
44554
|
-
const { children: _childrenConfig, ...restPropsNoChildren } =
|
|
44903
|
+
const { children: _childrenConfig, ...restPropsNoChildren } = liveProps;
|
|
44555
44904
|
const restProps = childrenIsRenderFn ? { ...restPropsNoChildren, children: incomingChildren } : restPropsNoChildren;
|
|
44556
44905
|
const nodeSlotOverrides = {};
|
|
44557
44906
|
for (const slotKey of CONTENT_NODE_SLOTS) {
|
|
@@ -44660,7 +45009,7 @@ function SlotContentRenderer({
|
|
|
44660
45009
|
"data-orb-path": patternPath ?? "root",
|
|
44661
45010
|
"data-orb-pattern": content.pattern,
|
|
44662
45011
|
"data-orb-orbital": orbitalName,
|
|
44663
|
-
children:
|
|
45012
|
+
children: liveProps.children ?? /* @__PURE__ */ jsxs(Box, { className: "p-4 text-sm text-muted-foreground border border-dashed border-border rounded", children: [
|
|
44664
45013
|
"Unknown pattern: ",
|
|
44665
45014
|
content.pattern,
|
|
44666
45015
|
content.sourceTrait && /* @__PURE__ */ jsxs(Typography, { variant: "small", className: "ml-2", children: [
|
|
@@ -44732,6 +45081,7 @@ var scopeWrapLog, TRAIT_BINDING_RE, SuspenseConfigContext, SlotContainedContext,
|
|
|
44732
45081
|
var init_UISlotRenderer = __esm({
|
|
44733
45082
|
"components/core/organisms/UISlotRenderer.tsx"() {
|
|
44734
45083
|
"use client";
|
|
45084
|
+
init_resolve_render_bindings();
|
|
44735
45085
|
init_Modal();
|
|
44736
45086
|
init_Drawer();
|
|
44737
45087
|
init_Toast();
|
|
@@ -44978,6 +45328,9 @@ function resolveLambdaBindings(body, params, item, index) {
|
|
|
44978
45328
|
const arr = body;
|
|
44979
45329
|
const substituted = arr.map((b) => recur(b));
|
|
44980
45330
|
if (isOperatorCall(substituted) && isSExpr(substituted)) {
|
|
45331
|
+
if (containsEntityBinding(substituted)) {
|
|
45332
|
+
return substituted;
|
|
45333
|
+
}
|
|
44981
45334
|
const evaluated = evaluate(substituted, createMinimalContext());
|
|
44982
45335
|
return isEventPayloadValue(evaluated) ? evaluated : String(evaluated);
|
|
44983
45336
|
}
|
|
@@ -44999,9 +45352,37 @@ function getSlotContentRenderer2() {
|
|
|
44999
45352
|
_slotContentRenderer2 = mod.SlotContentRenderer;
|
|
45000
45353
|
return _slotContentRenderer2;
|
|
45001
45354
|
}
|
|
45355
|
+
function deferLambdaEntityExprs(value) {
|
|
45356
|
+
if (typeof value === "string") {
|
|
45357
|
+
if (containsEntityBinding(value)) {
|
|
45358
|
+
const marker = { [RENDER_BINDING_MARKER]: true, expression: value };
|
|
45359
|
+
return marker;
|
|
45360
|
+
}
|
|
45361
|
+
return value;
|
|
45362
|
+
}
|
|
45363
|
+
if (Array.isArray(value)) {
|
|
45364
|
+
if (isFnFormLambda(value)) return value;
|
|
45365
|
+
const arr = value;
|
|
45366
|
+
if (isOperatorCall(arr) && isSExpr(arr) && containsEntityBinding(arr)) {
|
|
45367
|
+
const marker = { [RENDER_BINDING_MARKER]: true, expression: arr };
|
|
45368
|
+
return marker;
|
|
45369
|
+
}
|
|
45370
|
+
return arr.map((v) => deferLambdaEntityExprs(v));
|
|
45371
|
+
}
|
|
45372
|
+
if (value !== null && typeof value === "object" && !React83__default.isValidElement(value) && !(value instanceof Date) && typeof value !== "function" && !isRenderBindingMarker(value)) {
|
|
45373
|
+
const out = {};
|
|
45374
|
+
for (const [k, v] of Object.entries(value)) {
|
|
45375
|
+
out[k] = deferLambdaEntityExprs(v);
|
|
45376
|
+
}
|
|
45377
|
+
return out;
|
|
45378
|
+
}
|
|
45379
|
+
return value;
|
|
45380
|
+
}
|
|
45002
45381
|
function makeLambdaFn(params, lambdaBody, callerKey) {
|
|
45003
45382
|
return (item, index) => {
|
|
45004
|
-
const resolvedBody =
|
|
45383
|
+
const resolvedBody = deferLambdaEntityExprs(
|
|
45384
|
+
resolveLambdaBindings(lambdaBody, params, item, index)
|
|
45385
|
+
);
|
|
45005
45386
|
if (resolvedBody === null || typeof resolvedBody !== "object" || Array.isArray(resolvedBody) || typeof resolvedBody === "function" || React83__default.isValidElement(resolvedBody) || resolvedBody instanceof Date) {
|
|
45006
45387
|
return null;
|
|
45007
45388
|
}
|
|
@@ -45026,6 +45407,7 @@ function makeLambdaFn(params, lambdaBody, callerKey) {
|
|
|
45026
45407
|
}
|
|
45027
45408
|
function convertNode(node, callerKey) {
|
|
45028
45409
|
if (node === null || node === void 0) return node;
|
|
45410
|
+
if (isRenderBindingMarker(node)) return node;
|
|
45029
45411
|
if (Array.isArray(node)) {
|
|
45030
45412
|
if (isFnFormLambda(node)) {
|
|
45031
45413
|
const arr2 = node;
|
|
@@ -45078,6 +45460,7 @@ var tickLog = createLogger("almadar:ui:tick-effects");
|
|
|
45078
45460
|
setNamespaceLevel("almadar:ui:tick-effects", "WARN");
|
|
45079
45461
|
var sharedEntityLog = createLogger("almadar:ui:shared-entity");
|
|
45080
45462
|
setNamespaceLevel("almadar:ui:shared-entity", "WARN");
|
|
45463
|
+
var EMPTY_BINDING_SNAPSHOT = {};
|
|
45081
45464
|
var SYNC_TICK_OPERATORS = /* @__PURE__ */ new Set([
|
|
45082
45465
|
"set",
|
|
45083
45466
|
"emit",
|
|
@@ -45098,11 +45481,6 @@ var SYNC_TICK_OPERATORS = /* @__PURE__ */ new Set([
|
|
|
45098
45481
|
"do",
|
|
45099
45482
|
"when"
|
|
45100
45483
|
]);
|
|
45101
|
-
var REACTIVE_REPAINT_PATTERN_TYPES = /* @__PURE__ */ new Set([
|
|
45102
|
-
"canvas",
|
|
45103
|
-
"game-hud",
|
|
45104
|
-
"game-shell"
|
|
45105
|
-
]);
|
|
45106
45484
|
var LIFECYCLE_EVENTS = ["INIT", "LOAD", "$MOUNT"];
|
|
45107
45485
|
function toTraitDefinition(binding) {
|
|
45108
45486
|
return {
|
|
@@ -45143,6 +45521,27 @@ function classifySharedTick(tick) {
|
|
|
45143
45521
|
if (renders) return "renderer";
|
|
45144
45522
|
return "neither";
|
|
45145
45523
|
}
|
|
45524
|
+
function buildTraitRenderConfig(binding, traitConfigsByName, payload) {
|
|
45525
|
+
const declaredDefaults = collectDeclaredConfigDefaults(binding.trait);
|
|
45526
|
+
const resolvedDefaults = traitConfigsByName?.[binding.trait.name];
|
|
45527
|
+
const callSiteConfig = getBindingConfig(binding);
|
|
45528
|
+
const callSiteOverrides = callSiteConfig ? resolveCallSitePayloadCaptures(
|
|
45529
|
+
Object.fromEntries(
|
|
45530
|
+
Object.entries(callSiteConfig).filter(
|
|
45531
|
+
([, v]) => !containsConfigForward(v)
|
|
45532
|
+
)
|
|
45533
|
+
),
|
|
45534
|
+
payload
|
|
45535
|
+
) : void 0;
|
|
45536
|
+
if (declaredDefaults || resolvedDefaults || callSiteOverrides) {
|
|
45537
|
+
return {
|
|
45538
|
+
...declaredDefaults ?? {},
|
|
45539
|
+
...resolvedDefaults ?? {},
|
|
45540
|
+
...callSiteOverrides ?? {}
|
|
45541
|
+
};
|
|
45542
|
+
}
|
|
45543
|
+
return void 0;
|
|
45544
|
+
}
|
|
45146
45545
|
function createSharedEntityWriter(binding, tick, traitStatesRef, emit) {
|
|
45147
45546
|
return (scratch) => {
|
|
45148
45547
|
const traitName = binding.trait.name;
|
|
@@ -45363,8 +45762,24 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
45363
45762
|
}, [traitStates]);
|
|
45364
45763
|
const traitSnapshotDataRef = useRef(/* @__PURE__ */ new Map());
|
|
45365
45764
|
const traitFieldStatesRef = useRef(/* @__PURE__ */ new Map());
|
|
45366
|
-
const
|
|
45367
|
-
const
|
|
45765
|
+
const bridgeEchoPendingRef = useRef(/* @__PURE__ */ new Map());
|
|
45766
|
+
const bindingSnapshotsRef = useRef(/* @__PURE__ */ new Map());
|
|
45767
|
+
const bindingListenersRef = useRef(/* @__PURE__ */ new Map());
|
|
45768
|
+
const publishBindingSnapshot = useCallback((traitName, row) => {
|
|
45769
|
+
bindingSnapshotsRef.current.set(traitName, { ...row });
|
|
45770
|
+
const listeners7 = bindingListenersRef.current.get(traitName);
|
|
45771
|
+
if (!listeners7) return;
|
|
45772
|
+
listeners7.forEach((callback) => {
|
|
45773
|
+
try {
|
|
45774
|
+
callback();
|
|
45775
|
+
} catch (error) {
|
|
45776
|
+
stateLog.error("binding-snapshot listener error", {
|
|
45777
|
+
traitName,
|
|
45778
|
+
error: error instanceof Error ? error.message : String(error)
|
|
45779
|
+
});
|
|
45780
|
+
}
|
|
45781
|
+
});
|
|
45782
|
+
}, []);
|
|
45368
45783
|
useEffect(() => {
|
|
45369
45784
|
const mgr = managerRef.current;
|
|
45370
45785
|
const bindings = traitBindingsRef.current;
|
|
@@ -45492,15 +45907,6 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
45492
45907
|
const existing = pendingSlots.get(slot) || [];
|
|
45493
45908
|
existing.push({ pattern, props: props || {} });
|
|
45494
45909
|
pendingSlots.set(slot, existing);
|
|
45495
|
-
const patternType = pattern?.type;
|
|
45496
|
-
if (patternType !== void 0 && REACTIVE_REPAINT_PATTERN_TYPES.has(patternType)) {
|
|
45497
|
-
const rawForSlot = effects.filter(
|
|
45498
|
-
(e) => Array.isArray(e) && (e[0] === "render-ui" || e[0] === "render") && e[1] === slot
|
|
45499
|
-
);
|
|
45500
|
-
if (rawForSlot.length > 0) {
|
|
45501
|
-
lastCanvasRenderUiRef.current.set(traitName, rawForSlot);
|
|
45502
|
-
}
|
|
45503
|
-
}
|
|
45504
45910
|
},
|
|
45505
45911
|
clearSlot: (slot) => {
|
|
45506
45912
|
pendingSlots.set(slot, []);
|
|
@@ -45572,11 +45978,13 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
45572
45978
|
};
|
|
45573
45979
|
}
|
|
45574
45980
|
const sharedWrites = [];
|
|
45981
|
+
let didWrite = false;
|
|
45575
45982
|
const baseSet = handlers.set;
|
|
45576
45983
|
handlers = {
|
|
45577
45984
|
...handlers,
|
|
45578
45985
|
set: async (targetId, field, value) => {
|
|
45579
45986
|
if (baseSet) await baseSet(targetId, field, value);
|
|
45987
|
+
didWrite = true;
|
|
45580
45988
|
if (sharedKey !== void 0) {
|
|
45581
45989
|
sharedWrites.push({ field, value });
|
|
45582
45990
|
}
|
|
@@ -45593,23 +46001,9 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
45593
46001
|
payload: payload || {},
|
|
45594
46002
|
state: previousState
|
|
45595
46003
|
};
|
|
45596
|
-
const
|
|
45597
|
-
|
|
45598
|
-
|
|
45599
|
-
const callSiteOverrides = callSiteConfig ? resolveCallSitePayloadCaptures(
|
|
45600
|
-
Object.fromEntries(
|
|
45601
|
-
Object.entries(callSiteConfig).filter(
|
|
45602
|
-
([, v]) => !containsConfigForward(v)
|
|
45603
|
-
)
|
|
45604
|
-
),
|
|
45605
|
-
payload || {}
|
|
45606
|
-
) : void 0;
|
|
45607
|
-
if (declaredDefaults || resolvedDefaults || callSiteOverrides) {
|
|
45608
|
-
bindingCtx.config = {
|
|
45609
|
-
...declaredDefaults ?? {},
|
|
45610
|
-
...resolvedDefaults ?? {},
|
|
45611
|
-
...callSiteOverrides ?? {}
|
|
45612
|
-
};
|
|
46004
|
+
const renderConfig = buildTraitRenderConfig(binding, traitConfigsByName, payload || {});
|
|
46005
|
+
if (renderConfig !== void 0) {
|
|
46006
|
+
bindingCtx.config = renderConfig;
|
|
45613
46007
|
}
|
|
45614
46008
|
if (traitName === "Authority" || traitName === "Hero") {
|
|
45615
46009
|
sharedEntityLog.debug("executeTransitionEffects config tiles", {
|
|
@@ -45643,7 +46037,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
45643
46037
|
effectHeads: effects.map((e) => Array.isArray(e) ? String(e[0]) : "??")
|
|
45644
46038
|
});
|
|
45645
46039
|
}
|
|
45646
|
-
const executor = new EffectExecutor({ handlers: trackingHandlers, bindings: bindingCtx, context: effectContext });
|
|
46040
|
+
const executor = new EffectExecutor({ handlers: trackingHandlers, bindings: bindingCtx, context: effectContext, deferRenderBindings: true });
|
|
45647
46041
|
try {
|
|
45648
46042
|
await executor.executeAll(effects);
|
|
45649
46043
|
if (traitName === "Authority" || traitName === "Hero") {
|
|
@@ -45684,37 +46078,8 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
45684
46078
|
entity: binding.linkedEntity
|
|
45685
46079
|
});
|
|
45686
46080
|
}
|
|
45687
|
-
if (
|
|
45688
|
-
|
|
45689
|
-
if (stashed !== void 0 && stashed.length > 0) {
|
|
45690
|
-
await executor.executeAll(stashed);
|
|
45691
|
-
for (const [slot, patterns] of pendingSlots) {
|
|
45692
|
-
flushSlot(traitName, slot, patterns, {
|
|
45693
|
-
event: flushEvent,
|
|
45694
|
-
state: previousState,
|
|
45695
|
-
entity: binding.linkedEntity
|
|
45696
|
-
});
|
|
45697
|
-
}
|
|
45698
|
-
}
|
|
45699
|
-
if (sharedKey !== void 0 && executeTransitionEffectsRef.current !== null) {
|
|
45700
|
-
for (const sibling of traitBindingsRef.current) {
|
|
45701
|
-
const siblingName = sibling.trait.name;
|
|
45702
|
-
if (siblingName === traitName) continue;
|
|
45703
|
-
if (sharedKeyByTraitNameRef.current.get(siblingName) !== sharedKey) continue;
|
|
45704
|
-
const siblingStash = lastCanvasRenderUiRef.current.get(siblingName);
|
|
45705
|
-
if (siblingStash === void 0 || siblingStash.length === 0) continue;
|
|
45706
|
-
const siblingState = traitStatesRef.current.get(siblingName)?.currentState ?? "";
|
|
45707
|
-
await executeTransitionEffectsRef.current({
|
|
45708
|
-
binding: sibling,
|
|
45709
|
-
effects: siblingStash,
|
|
45710
|
-
previousState: siblingState,
|
|
45711
|
-
newState: siblingState,
|
|
45712
|
-
flushEvent: `${flushEvent}:repaint`,
|
|
45713
|
-
syncOnly,
|
|
45714
|
-
log: log9
|
|
45715
|
-
});
|
|
45716
|
-
}
|
|
45717
|
-
}
|
|
46081
|
+
if (didWrite && sharedKey === void 0) {
|
|
46082
|
+
publishBindingSnapshot(traitName, liveEntity);
|
|
45718
46083
|
}
|
|
45719
46084
|
} catch (error) {
|
|
45720
46085
|
log9.error("effects:error", {
|
|
@@ -45726,10 +46091,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
45726
46091
|
});
|
|
45727
46092
|
}
|
|
45728
46093
|
return emittedDuringExec;
|
|
45729
|
-
}, [eventBus, flushSlot, sharedEntityStore]);
|
|
45730
|
-
useEffect(() => {
|
|
45731
|
-
executeTransitionEffectsRef.current = executeTransitionEffects;
|
|
45732
|
-
}, [executeTransitionEffects]);
|
|
46094
|
+
}, [eventBus, flushSlot, sharedEntityStore, publishBindingSnapshot]);
|
|
45733
46095
|
const runTickEffects = useCallback((tick, binding) => {
|
|
45734
46096
|
const traitName = binding.trait.name;
|
|
45735
46097
|
const currentState = traitStatesRef.current.get(traitName)?.currentState ?? "";
|
|
@@ -45792,24 +46154,6 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
45792
46154
|
({ binding, tick }) => createSharedEntityWriter(binding, tick, traitStatesRef, emitFromSharedWriter)
|
|
45793
46155
|
);
|
|
45794
46156
|
runTickFrame(group.storeKey, writers, sharedEntityStore);
|
|
45795
|
-
const repaint = executeTransitionEffectsRef.current;
|
|
45796
|
-
if (repaint !== null) {
|
|
45797
|
-
for (const renderBinding of group.renderBindings) {
|
|
45798
|
-
const renderTraitName = renderBinding.trait.name;
|
|
45799
|
-
const stash = lastCanvasRenderUiRef.current.get(renderTraitName);
|
|
45800
|
-
if (stash === void 0 || stash.length === 0) continue;
|
|
45801
|
-
const renderState = traitStatesRef.current.get(renderTraitName)?.currentState ?? "";
|
|
45802
|
-
void repaint({
|
|
45803
|
-
binding: renderBinding,
|
|
45804
|
-
effects: stash,
|
|
45805
|
-
previousState: renderState,
|
|
45806
|
-
newState: renderState,
|
|
45807
|
-
flushEvent: "tick:repaint",
|
|
45808
|
-
syncOnly: true,
|
|
45809
|
-
log: sharedEntityLog
|
|
45810
|
-
});
|
|
45811
|
-
}
|
|
45812
|
-
}
|
|
45813
46157
|
};
|
|
45814
46158
|
if (interval === "frame") {
|
|
45815
46159
|
scheduler.add(0, onDue);
|
|
@@ -45880,6 +46224,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
45880
46224
|
executedTraits: results.map((r) => r.traitName).join(",")
|
|
45881
46225
|
});
|
|
45882
46226
|
const emittedByTrait = /* @__PURE__ */ new Map();
|
|
46227
|
+
bridgeEchoPendingRef.current.clear();
|
|
45883
46228
|
for (const { traitName, result } of results) {
|
|
45884
46229
|
const binding = bindingMap.get(traitName);
|
|
45885
46230
|
const traitState = currentManager.getState(traitName);
|
|
@@ -45934,6 +46279,12 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
45934
46279
|
log: stateLog
|
|
45935
46280
|
});
|
|
45936
46281
|
emittedByTrait.set(traitName, emittedDuringExec);
|
|
46282
|
+
for (const emittedKey of emittedDuringExec) {
|
|
46283
|
+
bridgeEchoPendingRef.current.set(
|
|
46284
|
+
emittedKey,
|
|
46285
|
+
(bridgeEchoPendingRef.current.get(emittedKey) ?? 0) + 1
|
|
46286
|
+
);
|
|
46287
|
+
}
|
|
45937
46288
|
} else if (!result.executed) {
|
|
45938
46289
|
if (result.guardResult === false) {
|
|
45939
46290
|
stateLog.debug("guard-blocked-transition", {
|
|
@@ -46083,8 +46434,13 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
46083
46434
|
crossTraitLog.debug("self:subscribe", { traitName, busKey: selfBusKey, eventKey });
|
|
46084
46435
|
const unsub = eventBus.on(selfBusKey, (event) => {
|
|
46085
46436
|
if (event.source && event.source.dispatched) {
|
|
46086
|
-
|
|
46087
|
-
|
|
46437
|
+
const pendingEchoes = bridgeEchoPendingRef.current.get(eventKey) ?? 0;
|
|
46438
|
+
if (pendingEchoes > 0) {
|
|
46439
|
+
bridgeEchoPendingRef.current.set(eventKey, pendingEchoes - 1);
|
|
46440
|
+
crossTraitLog.debug("self:fire-skipped-bridge-echo", { traitName, busKey: selfBusKey, eventKey });
|
|
46441
|
+
return;
|
|
46442
|
+
}
|
|
46443
|
+
crossTraitLog.debug("self:fire-server-cascade", { traitName, busKey: selfBusKey, eventKey });
|
|
46088
46444
|
}
|
|
46089
46445
|
crossTraitLog.debug("self:fire", { traitName, busKey: selfBusKey, eventKey });
|
|
46090
46446
|
enqueueAndDrain(eventKey, event.payload, traitName);
|
|
@@ -46176,11 +46532,47 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
46176
46532
|
initedTraitsRef.current = /* @__PURE__ */ new Set();
|
|
46177
46533
|
};
|
|
46178
46534
|
}, [traitBindings, enqueueAndDrain]);
|
|
46535
|
+
const entityBindingSource = useMemo(() => ({
|
|
46536
|
+
getEntitySnapshot: (traitName) => {
|
|
46537
|
+
const sharedKey = sharedKeyByTraitNameRef.current.get(traitName);
|
|
46538
|
+
if (sharedKey !== void 0) {
|
|
46539
|
+
return sharedEntityStore.getSnapshot(sharedKey);
|
|
46540
|
+
}
|
|
46541
|
+
return bindingSnapshotsRef.current.get(traitName) ?? EMPTY_BINDING_SNAPSHOT;
|
|
46542
|
+
},
|
|
46543
|
+
getConfig: (traitName) => {
|
|
46544
|
+
const binding = traitBindingsRef.current.find((b) => b.trait.name === traitName);
|
|
46545
|
+
if (binding === void 0) return void 0;
|
|
46546
|
+
return buildTraitRenderConfig(binding, traitConfigsByName, {});
|
|
46547
|
+
},
|
|
46548
|
+
getState: (traitName) => traitStatesRef.current.get(traitName)?.currentState ?? "",
|
|
46549
|
+
subscribe: (traitName, callback) => {
|
|
46550
|
+
const sharedKey = sharedKeyByTraitNameRef.current.get(traitName);
|
|
46551
|
+
if (sharedKey !== void 0) {
|
|
46552
|
+
return sharedEntityStore.subscribe(sharedKey, callback);
|
|
46553
|
+
}
|
|
46554
|
+
let listeners7 = bindingListenersRef.current.get(traitName);
|
|
46555
|
+
if (!listeners7) {
|
|
46556
|
+
listeners7 = /* @__PURE__ */ new Set();
|
|
46557
|
+
bindingListenersRef.current.set(traitName, listeners7);
|
|
46558
|
+
}
|
|
46559
|
+
listeners7.add(callback);
|
|
46560
|
+
return () => {
|
|
46561
|
+
const current = bindingListenersRef.current.get(traitName);
|
|
46562
|
+
if (!current) return;
|
|
46563
|
+
current.delete(callback);
|
|
46564
|
+
if (current.size === 0) {
|
|
46565
|
+
bindingListenersRef.current.delete(traitName);
|
|
46566
|
+
}
|
|
46567
|
+
};
|
|
46568
|
+
}
|
|
46569
|
+
}), [sharedEntityStore, traitConfigsByName]);
|
|
46179
46570
|
return {
|
|
46180
46571
|
traitStates,
|
|
46181
46572
|
sendEvent,
|
|
46182
46573
|
getTraitState,
|
|
46183
|
-
canHandleEvent
|
|
46574
|
+
canHandleEvent,
|
|
46575
|
+
entityBindingSource
|
|
46184
46576
|
};
|
|
46185
46577
|
}
|
|
46186
46578
|
var resolvedSchemaLog = createLogger("almadar:ui:resolved-schema");
|
|
@@ -46372,7 +46764,7 @@ function collectServerActiveTraits(ir, allTraits, mountedTraitNames) {
|
|
|
46372
46764
|
}
|
|
46373
46765
|
return active;
|
|
46374
46766
|
}
|
|
46375
|
-
function TraitInitializer({ traits: traits2, routeParams, orbitalNames, onNavigate, onLocalFallback, persistence, traitConfigsByName, orbitalsByTrait, embeddedTraits, serverActiveTraits }) {
|
|
46767
|
+
function TraitInitializer({ traits: traits2, routeParams, orbitalNames, onNavigate, onLocalFallback, persistence, traitConfigsByName, orbitalsByTrait, embeddedTraits, serverActiveTraits, children }) {
|
|
46376
46768
|
const bridge = useServerBridge();
|
|
46377
46769
|
const activeTraitNames = useMemo(
|
|
46378
46770
|
() => new Set(traits2.map((b) => b.trait.name).filter((n) => !!n)),
|
|
@@ -46402,7 +46794,7 @@ function TraitInitializer({ traits: traits2, routeParams, orbitalNames, onNaviga
|
|
|
46402
46794
|
}
|
|
46403
46795
|
}, [bridge.connected, bridge.sendEvent, orbitalNames, uiSlots, onNavigate, embeddedTraits, activeTraitNames, withActiveTraits]);
|
|
46404
46796
|
const opts = orbitalNames ? { onEventProcessed, navigate: onNavigate, traitConfigsByName, orbitalsByTrait, embeddedTraits, initPayload: routeParams } : { navigate: onNavigate, persistence, traitConfigsByName, orbitalsByTrait, embeddedTraits, initPayload: routeParams };
|
|
46405
|
-
const { sendEvent } = useTraitStateMachine(traits2, uiSlots, opts);
|
|
46797
|
+
const { sendEvent, entityBindingSource } = useTraitStateMachine(traits2, uiSlots, opts);
|
|
46406
46798
|
const initSentRef = useRef(false);
|
|
46407
46799
|
const prevTraitsRef = useRef(void 0);
|
|
46408
46800
|
const paramsKey = JSON.stringify(routeParams ?? {});
|
|
@@ -46448,7 +46840,7 @@ function TraitInitializer({ traits: traits2, routeParams, orbitalNames, onNaviga
|
|
|
46448
46840
|
{ type: "fetch", args: [], status: "executed" },
|
|
46449
46841
|
...effects.map((eff) => ({
|
|
46450
46842
|
type: eff.type,
|
|
46451
|
-
args: eff.type === "render-ui" ? [eff.slot] : [],
|
|
46843
|
+
args: eff.type === "render-ui" && eff.slot !== void 0 ? [eff.slot] : [],
|
|
46452
46844
|
status: "executed"
|
|
46453
46845
|
}))
|
|
46454
46846
|
];
|
|
@@ -46464,7 +46856,7 @@ function TraitInitializer({ traits: traits2, routeParams, orbitalNames, onNaviga
|
|
|
46464
46856
|
}
|
|
46465
46857
|
})();
|
|
46466
46858
|
}, [bridge.connected, orbitalNames, bridge.sendEvent, uiSlots, onNavigate, embeddedTraits, activeTraitNames, withActiveTraits, routeParams]);
|
|
46467
|
-
return
|
|
46859
|
+
return /* @__PURE__ */ jsx(EntityBindingContext.Provider, { value: entityBindingSource, children });
|
|
46468
46860
|
}
|
|
46469
46861
|
function SchemaRunner({ schema, serverUrl, transport, mockData, pageName, routeParams, onNavigate, onLocalFallback, persistence }) {
|
|
46470
46862
|
const { traits: traits2, allEntities, allTraits, ir } = useResolvedSchema(schema, pageName);
|
|
@@ -46597,30 +46989,28 @@ function SchemaRunner({ schema, serverUrl, transport, mockData, pageName, routeP
|
|
|
46597
46989
|
}
|
|
46598
46990
|
return schema.orbitals[0]?.theme;
|
|
46599
46991
|
}, [schema, pageName]);
|
|
46600
|
-
const inner = /* @__PURE__ */ jsx(VerificationProvider, { enabled: true, children: /* @__PURE__ */
|
|
46992
|
+
const inner = /* @__PURE__ */ jsx(VerificationProvider, { enabled: true, children: /* @__PURE__ */ jsx(
|
|
46601
46993
|
EntitySchemaProvider,
|
|
46602
46994
|
{
|
|
46603
46995
|
entities: entitiesArray,
|
|
46604
46996
|
traitLinkedEntities: traitLinkedEntitiesMap,
|
|
46605
46997
|
orbitalsByTrait: orbitalsByTraitMap,
|
|
46606
|
-
children:
|
|
46607
|
-
|
|
46608
|
-
|
|
46609
|
-
|
|
46610
|
-
|
|
46611
|
-
|
|
46612
|
-
|
|
46613
|
-
|
|
46614
|
-
|
|
46615
|
-
|
|
46616
|
-
|
|
46617
|
-
|
|
46618
|
-
|
|
46619
|
-
|
|
46620
|
-
|
|
46621
|
-
|
|
46622
|
-
/* @__PURE__ */ jsx(OrbitalThemeProvider, { theme: activeOrbitalTheme, children: /* @__PURE__ */ jsx(Box, { className: "h-full min-h-full overflow-auto p-4", children: /* @__PURE__ */ jsx(UISlotRenderer, { includeHud: true, hudMode: "inline", includeFloating: true }) }) })
|
|
46623
|
-
]
|
|
46998
|
+
children: /* @__PURE__ */ jsx(
|
|
46999
|
+
TraitInitializer,
|
|
47000
|
+
{
|
|
47001
|
+
traits: allPageTraits,
|
|
47002
|
+
routeParams,
|
|
47003
|
+
orbitalNames: serverUrl || transport ? pageOrbitalNames : void 0,
|
|
47004
|
+
traitConfigsByName,
|
|
47005
|
+
orbitalsByTrait,
|
|
47006
|
+
embeddedTraits,
|
|
47007
|
+
serverActiveTraits,
|
|
47008
|
+
onNavigate,
|
|
47009
|
+
onLocalFallback,
|
|
47010
|
+
persistence,
|
|
47011
|
+
children: /* @__PURE__ */ jsx(OrbitalThemeProvider, { theme: activeOrbitalTheme, children: /* @__PURE__ */ jsx(Box, { className: "h-full min-h-full overflow-auto p-4", children: /* @__PURE__ */ jsx(UISlotRenderer, { includeHud: true, hudMode: "inline", includeFloating: true }) }) })
|
|
47012
|
+
}
|
|
47013
|
+
)
|
|
46624
47014
|
}
|
|
46625
47015
|
) });
|
|
46626
47016
|
if (serverUrl || transport) {
|