@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/avl/index.js
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
2
2
|
import * as React92 from 'react';
|
|
3
3
|
import React92__default, { createContext, useState, useMemo, useRef, useEffect, useContext, useCallback, Suspense, useLayoutEffect, Profiler, useReducer, useSyncExternalStore, lazy, useId } from 'react';
|
|
4
|
-
import { getAllPages, matchPathAmong, OrbitalProvider, EventBusContext, useTraitScopeChain, ServerBridgeProvider, VerificationProvider, EntitySchemaProvider, OrbitalThemeProvider, useServerBridge, useEntitySchema, useEntitySchemaOptional, TraitScopeProvider, useCurrentPagePath, useGameAudioContextOptional } from '@almadar/ui/providers';
|
|
4
|
+
import { getAllPages, matchPathAmong, OrbitalProvider, EventBusContext, useTraitScopeChain, ServerBridgeProvider, VerificationProvider, EntitySchemaProvider, OrbitalThemeProvider, useServerBridge, EntityBindingContext, useEntitySchema, useEntitySchemaOptional, useEntityBindingSnapshot, TraitScopeProvider, useTraitScope, useCurrentPagePath, useGameAudioContextOptional } from '@almadar/ui/providers';
|
|
5
5
|
import { createLogger, setNamespaceLevel, isLogLevelEnabled } from '@almadar/logger';
|
|
6
6
|
import ELK from 'elkjs/lib/elk.bundled.js';
|
|
7
7
|
import { MarkerType, useReactFlow, Handle, Position, getBezierPath, EdgeLabelRenderer, useNodeId, ReactFlowProvider, BaseEdge, useNodesState, useEdgesState, ReactFlow, Controls, Background, BackgroundVariant } from '@xyflow/react';
|
|
8
8
|
import { useTranslate } from '@almadar/ui/hooks';
|
|
9
|
+
import { InMemoryPersistence, StateMachineManager, collectDeclaredConfigDefaults, resolveCallSitePayloadCaptures, createServerEffectHandlers, EffectExecutor, createContextFromBindings, createTickScheduler, isValidCronExpression, parseDurationString, normalizeCallSiteConfigToValues, interpolateValue } from '@almadar/runtime';
|
|
10
|
+
import { FieldTypeSchema, isInlineTrait, isPageReference, buildResolvedTraitConfigs, schemaToIR, getPage, mergeEntityFrame, isCircuitEvent, applyListenPayloadMapping, walkSExpr, isRenderBindingMarker, containsEntityBinding, isSExpr, isEventPayloadValue, RENDER_BINDING_MARKER } from '@almadar/core';
|
|
9
11
|
import * as LucideIcons2 from 'lucide-react';
|
|
10
12
|
import { Loader2, X, Code, FileText, WrapText, Check, Copy, Lightbulb, CheckCircle, List, Printer, ChevronRight, ChevronLeft, GitBranch, Pencil, Eye, Plus, ArrowRight, Trash, RotateCcw, Play, Terminal, XCircle, AlertTriangle, Trash2, Link2, ZoomOut, ZoomIn, Download, ChevronDown, Menu as Menu$1, Package, Calendar, MoreHorizontal, Image as Image$1, Upload, ArrowLeft, HelpCircle, PauseCircle, Search, Type, Heading1, Heading2, Heading3, ListOrdered, Quote, Minus, Eraser, TrendingUp, TrendingDown, AlertCircle, Circle, Clock, CheckCircle2, ChevronUp, Tag, User, DollarSign } from 'lucide-react';
|
|
11
13
|
import { createPortal } from 'react-dom';
|
|
@@ -66,15 +68,14 @@ import ReactMarkdown from 'react-markdown';
|
|
|
66
68
|
import remarkGfm from 'remark-gfm';
|
|
67
69
|
import remarkMath from 'remark-math';
|
|
68
70
|
import rehypeKatex from 'rehype-katex';
|
|
69
|
-
import { FieldTypeSchema, isInlineTrait, isPageReference, buildResolvedTraitConfigs, schemaToIR, getPage, mergeEntityFrame, isCircuitEvent, applyListenPayloadMapping, walkSExpr, isSExpr, isEventPayloadValue } from '@almadar/core';
|
|
70
71
|
import { useDroppable, useDraggable, DndContext, DragOverlay, useSensors, useSensor, PointerSensor, KeyboardSensor, pointerWithin, rectIntersection, closestCorners } from '@dnd-kit/core';
|
|
71
72
|
import { sortableKeyboardCoordinates, useSortable, arrayMove, SortableContext, rectSortingStrategy, verticalListSortingStrategy } from '@dnd-kit/sortable';
|
|
72
73
|
import { CSS } from '@dnd-kit/utilities';
|
|
74
|
+
import { ordered, lib } from 'emojilib';
|
|
73
75
|
import { forceSimulation, forceLink, forceManyBody, forceCollide, forceX, forceY } from 'd3-force';
|
|
74
76
|
import { isDrawHostPattern, getPatternDefinition, getComponentForPattern as getComponentForPattern$1, isEntityAwarePattern } from '@almadar/core/patterns';
|
|
75
77
|
import { OrbitalServerRuntime } from '@almadar/runtime/OrbitalServerRuntime';
|
|
76
78
|
import { isKnownStdOperator } from '@almadar/std/registry';
|
|
77
|
-
import { InMemoryPersistence, StateMachineManager, collectDeclaredConfigDefaults, resolveCallSitePayloadCaptures, createServerEffectHandlers, EffectExecutor, createContextFromBindings, createTickScheduler, isValidCronExpression, parseDurationString, normalizeCallSiteConfigToValues } from '@almadar/runtime';
|
|
78
79
|
|
|
79
80
|
var __defProp = Object.defineProperty;
|
|
80
81
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
@@ -3162,6 +3163,32 @@ function formatValue(value, format) {
|
|
|
3162
3163
|
return String(value);
|
|
3163
3164
|
}
|
|
3164
3165
|
}
|
|
3166
|
+
function compareCellValues(a, b) {
|
|
3167
|
+
const aEmpty = a === null || a === void 0 || a === "";
|
|
3168
|
+
const bEmpty = b === null || b === void 0 || b === "";
|
|
3169
|
+
if (aEmpty || bEmpty) return aEmpty && bEmpty ? 0 : aEmpty ? 1 : -1;
|
|
3170
|
+
if (typeof a === "number" && typeof b === "number") return a - b;
|
|
3171
|
+
if (typeof a === "boolean" && typeof b === "boolean") return Number(a) - Number(b);
|
|
3172
|
+
const aNum = Number(a);
|
|
3173
|
+
const bNum = Number(b);
|
|
3174
|
+
if (Number.isFinite(aNum) && Number.isFinite(bNum)) return aNum - bNum;
|
|
3175
|
+
const aTime = dateLikeTime(a);
|
|
3176
|
+
const bTime = dateLikeTime(b);
|
|
3177
|
+
if (aTime !== null && bTime !== null) return aTime - bTime;
|
|
3178
|
+
return String(a).localeCompare(String(b));
|
|
3179
|
+
}
|
|
3180
|
+
function dateLikeTime(value) {
|
|
3181
|
+
if (value instanceof Date) return value.getTime();
|
|
3182
|
+
const text = String(value);
|
|
3183
|
+
if (!/\d/.test(text) || !/[-/:T]/.test(text)) return null;
|
|
3184
|
+
const time = Date.parse(text);
|
|
3185
|
+
return Number.isNaN(time) ? null : time;
|
|
3186
|
+
}
|
|
3187
|
+
function sortRows(rows, field, direction = "asc") {
|
|
3188
|
+
if (!field) return rows;
|
|
3189
|
+
const dir = direction === "desc" ? -1 : 1;
|
|
3190
|
+
return [...rows].sort((a, b) => dir * compareCellValues(a?.[field], b?.[field]));
|
|
3191
|
+
}
|
|
3165
3192
|
var init_format = __esm({
|
|
3166
3193
|
"lib/format.ts"() {
|
|
3167
3194
|
}
|
|
@@ -4544,6 +4571,75 @@ var init_BehaviorView = __esm({
|
|
|
4544
4571
|
BehaviorView.displayName = "BehaviorView";
|
|
4545
4572
|
}
|
|
4546
4573
|
});
|
|
4574
|
+
function resolveMarkerExpression(expression, entity, config, state) {
|
|
4575
|
+
const ctx = createContextFromBindings({
|
|
4576
|
+
entity,
|
|
4577
|
+
payload: {},
|
|
4578
|
+
state,
|
|
4579
|
+
...config !== void 0 ? { config } : {}
|
|
4580
|
+
});
|
|
4581
|
+
return interpolateValue(expression, ctx);
|
|
4582
|
+
}
|
|
4583
|
+
function isPlainObject(value) {
|
|
4584
|
+
if (value === null || value === void 0 || typeof value !== "object") return false;
|
|
4585
|
+
if (Array.isArray(value)) return false;
|
|
4586
|
+
if (React92__default.isValidElement(value)) return false;
|
|
4587
|
+
if (value instanceof Date) return false;
|
|
4588
|
+
if (typeof value === "function") return false;
|
|
4589
|
+
return true;
|
|
4590
|
+
}
|
|
4591
|
+
function walkValue(value, scopeTrait, entity, config, state) {
|
|
4592
|
+
if (isRenderBindingMarker(value)) {
|
|
4593
|
+
return { resolved: resolveMarkerExpression(value.expression, entity, config, state), changed: true };
|
|
4594
|
+
}
|
|
4595
|
+
if (Array.isArray(value)) {
|
|
4596
|
+
const out = [];
|
|
4597
|
+
let changed = false;
|
|
4598
|
+
for (const item of value) {
|
|
4599
|
+
const element = item;
|
|
4600
|
+
const wasMarker = isRenderBindingMarker(element);
|
|
4601
|
+
const { resolved, changed: itemChanged } = walkValue(element, scopeTrait, entity, config, state);
|
|
4602
|
+
if (wasMarker && Array.isArray(resolved)) {
|
|
4603
|
+
out.push(...resolved);
|
|
4604
|
+
changed = true;
|
|
4605
|
+
continue;
|
|
4606
|
+
}
|
|
4607
|
+
out.push(resolved);
|
|
4608
|
+
if (itemChanged) changed = true;
|
|
4609
|
+
}
|
|
4610
|
+
return changed ? { resolved: out, changed: true } : { resolved: value, changed: false };
|
|
4611
|
+
}
|
|
4612
|
+
if (isPlainObject(value)) {
|
|
4613
|
+
const sourceTrait = value._sourceTrait;
|
|
4614
|
+
if (typeof sourceTrait === "string" && sourceTrait !== scopeTrait) {
|
|
4615
|
+
return { resolved: value, changed: false };
|
|
4616
|
+
}
|
|
4617
|
+
const out = {};
|
|
4618
|
+
let changed = false;
|
|
4619
|
+
for (const [key, item] of Object.entries(value)) {
|
|
4620
|
+
const { resolved, changed: itemChanged } = walkValue(item, scopeTrait, entity, config, state);
|
|
4621
|
+
out[key] = resolved;
|
|
4622
|
+
if (itemChanged) changed = true;
|
|
4623
|
+
}
|
|
4624
|
+
return changed ? { resolved: out, changed: true } : { resolved: value, changed: false };
|
|
4625
|
+
}
|
|
4626
|
+
return { resolved: value, changed: false };
|
|
4627
|
+
}
|
|
4628
|
+
function resolveRenderBindingMarkers(props, scopeTrait, entity, config, state) {
|
|
4629
|
+
const out = {};
|
|
4630
|
+
let changed = false;
|
|
4631
|
+
for (const [key, value] of Object.entries(props)) {
|
|
4632
|
+
const { resolved, changed: propChanged } = walkValue(value, scopeTrait, entity, config, state);
|
|
4633
|
+
out[key] = resolved;
|
|
4634
|
+
if (propChanged) changed = true;
|
|
4635
|
+
}
|
|
4636
|
+
return changed ? out : props;
|
|
4637
|
+
}
|
|
4638
|
+
var init_resolve_render_bindings = __esm({
|
|
4639
|
+
"lib/resolve-render-bindings.ts"() {
|
|
4640
|
+
"use client";
|
|
4641
|
+
}
|
|
4642
|
+
});
|
|
4547
4643
|
function getCurrentIconFamily() {
|
|
4548
4644
|
if (typeof window === "undefined" || typeof document === "undefined") {
|
|
4549
4645
|
return DEFAULT_FAMILY;
|
|
@@ -4786,9 +4882,13 @@ function getAtlas(url, onReady) {
|
|
|
4786
4882
|
onReady();
|
|
4787
4883
|
}).catch(() => {
|
|
4788
4884
|
atlasCache.set(url, null);
|
|
4885
|
+
onReady();
|
|
4789
4886
|
});
|
|
4790
4887
|
return void 0;
|
|
4791
4888
|
}
|
|
4889
|
+
function atlasFailed(url) {
|
|
4890
|
+
return atlasCache.get(url) === null;
|
|
4891
|
+
}
|
|
4792
4892
|
function subRectFor(atlas, sprite) {
|
|
4793
4893
|
if (isTilesheet(atlas)) {
|
|
4794
4894
|
let col;
|
|
@@ -6846,6 +6946,20 @@ var init_Input = __esm({
|
|
|
6846
6946
|
const { t } = useTranslate();
|
|
6847
6947
|
const eventBus = useEventBus();
|
|
6848
6948
|
const type = inputType || htmlType || "text";
|
|
6949
|
+
const isDeclarative = typeof onChange === "string";
|
|
6950
|
+
const [localValue, setLocalValue] = React92__default.useState(value);
|
|
6951
|
+
const pendingEchoRef = React92__default.useRef(/* @__PURE__ */ new Set());
|
|
6952
|
+
React92__default.useEffect(() => {
|
|
6953
|
+
if (!isDeclarative) return;
|
|
6954
|
+
const incoming = value == null ? "" : String(value);
|
|
6955
|
+
if (pendingEchoRef.current.has(incoming)) {
|
|
6956
|
+
pendingEchoRef.current.delete(incoming);
|
|
6957
|
+
return;
|
|
6958
|
+
}
|
|
6959
|
+
pendingEchoRef.current.clear();
|
|
6960
|
+
setLocalValue(value);
|
|
6961
|
+
}, [value, isDeclarative]);
|
|
6962
|
+
const displayValue = isDeclarative ? localValue : value;
|
|
6849
6963
|
const resolveIconNode = (i, cls) => {
|
|
6850
6964
|
if (!i) return null;
|
|
6851
6965
|
if (typeof i === "string") return /* @__PURE__ */ jsx(Icon, { name: i, className: cls });
|
|
@@ -6855,7 +6969,7 @@ var init_Input = __esm({
|
|
|
6855
6969
|
const iconCls = "h-icon-default w-icon-default";
|
|
6856
6970
|
const IconComponent = typeof iconProp === "string" ? resolveIcon(iconProp) : iconProp;
|
|
6857
6971
|
const resolvedLeftIcon = (leftIcon ? resolveIconNode(leftIcon, iconCls) : null) || IconComponent && /* @__PURE__ */ jsx(IconComponent, { className: iconCls });
|
|
6858
|
-
const showClearButton = clearable &&
|
|
6972
|
+
const showClearButton = clearable && displayValue && String(displayValue).length > 0;
|
|
6859
6973
|
const isMultiline = type === "textarea";
|
|
6860
6974
|
const baseClassName = cn(
|
|
6861
6975
|
"block w-full rounded-sm transition-all duration-fast",
|
|
@@ -6874,6 +6988,10 @@ var init_Input = __esm({
|
|
|
6874
6988
|
if (typeof onChange === "string") {
|
|
6875
6989
|
const target = e.target;
|
|
6876
6990
|
const payload = type === "checkbox" ? { checked: target.checked } : { value: target.value };
|
|
6991
|
+
if (type !== "checkbox") {
|
|
6992
|
+
pendingEchoRef.current.add(target.value);
|
|
6993
|
+
setLocalValue(target.value);
|
|
6994
|
+
}
|
|
6877
6995
|
eventBus.emit(`UI:${onChange}`, payload);
|
|
6878
6996
|
} else {
|
|
6879
6997
|
onChange?.(e);
|
|
@@ -6904,7 +7022,7 @@ var init_Input = __esm({
|
|
|
6904
7022
|
"select",
|
|
6905
7023
|
{
|
|
6906
7024
|
ref,
|
|
6907
|
-
value,
|
|
7025
|
+
value: displayValue,
|
|
6908
7026
|
onChange: handleChange,
|
|
6909
7027
|
className: cn(baseClassName, "appearance-none pr-10", className),
|
|
6910
7028
|
...props,
|
|
@@ -6924,7 +7042,7 @@ var init_Input = __esm({
|
|
|
6924
7042
|
"textarea",
|
|
6925
7043
|
{
|
|
6926
7044
|
ref,
|
|
6927
|
-
value,
|
|
7045
|
+
value: displayValue,
|
|
6928
7046
|
onChange: handleChange,
|
|
6929
7047
|
rows,
|
|
6930
7048
|
className: baseClassName,
|
|
@@ -6963,7 +7081,7 @@ var init_Input = __esm({
|
|
|
6963
7081
|
{
|
|
6964
7082
|
ref,
|
|
6965
7083
|
type,
|
|
6966
|
-
value,
|
|
7084
|
+
value: displayValue,
|
|
6967
7085
|
onChange: handleChange,
|
|
6968
7086
|
onKeyDown: handleKeyDown,
|
|
6969
7087
|
className: baseClassName,
|
|
@@ -10800,46 +10918,45 @@ var init_useImageCache = __esm({
|
|
|
10800
10918
|
});
|
|
10801
10919
|
|
|
10802
10920
|
// lib/isometric.ts
|
|
10803
|
-
function isoToScreen(tileX, tileY,
|
|
10804
|
-
const
|
|
10805
|
-
const
|
|
10921
|
+
function isoToScreen(tileX, tileY, cellWidth, baseOffsetX, layout = "isometric") {
|
|
10922
|
+
const w = cellWidth;
|
|
10923
|
+
const fh = cellWidth / 2;
|
|
10806
10924
|
if (layout === "hex") {
|
|
10807
|
-
const screenX2 = tileX *
|
|
10808
|
-
const screenY2 = tileY * (
|
|
10925
|
+
const screenX2 = tileX * w + (tileY & 1) * (w / 2) + baseOffsetX;
|
|
10926
|
+
const screenY2 = tileY * (fh * 0.75);
|
|
10809
10927
|
return { x: screenX2, y: screenY2 };
|
|
10810
10928
|
}
|
|
10811
10929
|
if (layout === "flat") {
|
|
10812
|
-
const screenX2 = tileX *
|
|
10813
|
-
const screenY2 = tileY *
|
|
10930
|
+
const screenX2 = tileX * w + baseOffsetX;
|
|
10931
|
+
const screenY2 = tileY * w;
|
|
10814
10932
|
return { x: screenX2, y: screenY2 };
|
|
10815
10933
|
}
|
|
10816
|
-
const screenX = (tileX - tileY) * (
|
|
10817
|
-
const screenY = (tileX + tileY) * (
|
|
10934
|
+
const screenX = (tileX - tileY) * (w / 2) + baseOffsetX;
|
|
10935
|
+
const screenY = (tileX + tileY) * (fh / 2);
|
|
10818
10936
|
return { x: screenX, y: screenY };
|
|
10819
10937
|
}
|
|
10820
|
-
function screenToIso(screenX, screenY,
|
|
10821
|
-
const
|
|
10822
|
-
const
|
|
10938
|
+
function screenToIso(screenX, screenY, cellWidth, baseOffsetX, layout = "isometric") {
|
|
10939
|
+
const w = cellWidth;
|
|
10940
|
+
const fh = cellWidth / 2;
|
|
10823
10941
|
if (layout === "hex") {
|
|
10824
|
-
const row = Math.round(screenY / (
|
|
10825
|
-
const col = Math.round((screenX - (row & 1) * (
|
|
10942
|
+
const row = Math.round(screenY / (fh * 0.75));
|
|
10943
|
+
const col = Math.round((screenX - (row & 1) * (w / 2) - baseOffsetX) / w);
|
|
10826
10944
|
return { x: col, y: row };
|
|
10827
10945
|
}
|
|
10828
10946
|
if (layout === "flat") {
|
|
10829
|
-
const col = Math.round((screenX - baseOffsetX) /
|
|
10830
|
-
const row = Math.round(screenY /
|
|
10947
|
+
const col = Math.round((screenX - baseOffsetX) / w);
|
|
10948
|
+
const row = Math.round(screenY / w);
|
|
10831
10949
|
return { x: col, y: row };
|
|
10832
10950
|
}
|
|
10833
10951
|
const adjustedX = screenX - baseOffsetX;
|
|
10834
|
-
const tileX = (adjustedX / (
|
|
10835
|
-
const tileY = (screenY / (
|
|
10952
|
+
const tileX = (adjustedX / (w / 2) + screenY / (fh / 2)) / 2;
|
|
10953
|
+
const tileY = (screenY / (fh / 2) - adjustedX / (w / 2)) / 2;
|
|
10836
10954
|
return { x: Math.round(tileX), y: Math.round(tileY) };
|
|
10837
10955
|
}
|
|
10838
|
-
var TILE_WIDTH,
|
|
10956
|
+
var TILE_WIDTH, DIAMOND_TOP_Y, BACKGROUND_FALLBACK_COLOR, MINIMAP_TERRAIN_COLORS;
|
|
10839
10957
|
var init_isometric = __esm({
|
|
10840
10958
|
"lib/isometric.ts"() {
|
|
10841
10959
|
TILE_WIDTH = 256;
|
|
10842
|
-
FLOOR_HEIGHT = 128;
|
|
10843
10960
|
DIAMOND_TOP_Y = 374;
|
|
10844
10961
|
BACKGROUND_FALLBACK_COLOR = "#1a1a2e";
|
|
10845
10962
|
MINIMAP_TERRAIN_COLORS = {
|
|
@@ -11324,210 +11441,6 @@ var init_ChoiceButton = __esm({
|
|
|
11324
11441
|
ChoiceButton.displayName = "ChoiceButton";
|
|
11325
11442
|
}
|
|
11326
11443
|
});
|
|
11327
|
-
function SvgStage({
|
|
11328
|
-
cols,
|
|
11329
|
-
rows,
|
|
11330
|
-
tileSize = 32,
|
|
11331
|
-
background = "var(--color-background)",
|
|
11332
|
-
tileClickEvent,
|
|
11333
|
-
tileHoverEvent,
|
|
11334
|
-
tileLeaveEvent,
|
|
11335
|
-
keyMap,
|
|
11336
|
-
keyUpMap,
|
|
11337
|
-
className,
|
|
11338
|
-
children
|
|
11339
|
-
}) {
|
|
11340
|
-
const eventBus = useEventBus();
|
|
11341
|
-
const svgRef = useRef(null);
|
|
11342
|
-
const pointerDownRef = useRef(null);
|
|
11343
|
-
const cellFromClient = useCallback((clientX, clientY) => {
|
|
11344
|
-
const svg = svgRef.current;
|
|
11345
|
-
if (!svg) return null;
|
|
11346
|
-
const rect = svg.getBoundingClientRect();
|
|
11347
|
-
if (rect.width === 0 || rect.height === 0) return null;
|
|
11348
|
-
const vbW = cols * tileSize;
|
|
11349
|
-
const vbH = rows * tileSize;
|
|
11350
|
-
const meet = Math.min(rect.width / vbW, rect.height / vbH);
|
|
11351
|
-
const offsetX = (rect.width - vbW * meet) / 2;
|
|
11352
|
-
const offsetY = (rect.height - vbH * meet) / 2;
|
|
11353
|
-
const svgX = (clientX - rect.left - offsetX) / meet;
|
|
11354
|
-
const svgY = (clientY - rect.top - offsetY) / meet;
|
|
11355
|
-
return {
|
|
11356
|
-
x: Math.min(Math.max(Math.floor(svgX / tileSize), 0), cols - 1),
|
|
11357
|
-
y: Math.min(Math.max(Math.floor(svgY / tileSize), 0), rows - 1)
|
|
11358
|
-
};
|
|
11359
|
-
}, [cols, rows, tileSize]);
|
|
11360
|
-
const handlePointerDown = useCallback((e) => {
|
|
11361
|
-
pointerDownRef.current = { clientX: e.clientX, clientY: e.clientY };
|
|
11362
|
-
}, []);
|
|
11363
|
-
const handlePointerUp = useCallback((e) => {
|
|
11364
|
-
const down = pointerDownRef.current;
|
|
11365
|
-
pointerDownRef.current = null;
|
|
11366
|
-
if (!tileClickEvent) return;
|
|
11367
|
-
if (down && Math.hypot(e.clientX - down.clientX, e.clientY - down.clientY) > 5) return;
|
|
11368
|
-
const cell = cellFromClient(e.clientX, e.clientY);
|
|
11369
|
-
if (cell) eventBus.emit(`UI:${tileClickEvent}`, cell);
|
|
11370
|
-
}, [cellFromClient, tileClickEvent, eventBus]);
|
|
11371
|
-
const handlePointerMove = useCallback((e) => {
|
|
11372
|
-
if (!tileHoverEvent) return;
|
|
11373
|
-
const cell = cellFromClient(e.clientX, e.clientY);
|
|
11374
|
-
if (cell) eventBus.emit(`UI:${tileHoverEvent}`, cell);
|
|
11375
|
-
}, [cellFromClient, tileHoverEvent, eventBus]);
|
|
11376
|
-
const handlePointerLeave = useCallback(() => {
|
|
11377
|
-
pointerDownRef.current = null;
|
|
11378
|
-
if (tileLeaveEvent) eventBus.emit(`UI:${tileLeaveEvent}`, {});
|
|
11379
|
-
}, [tileLeaveEvent, eventBus]);
|
|
11380
|
-
useEffect(() => {
|
|
11381
|
-
if (!keyMap && !keyUpMap) return;
|
|
11382
|
-
const onDown = (e) => {
|
|
11383
|
-
const ev = keyMap?.[e.code];
|
|
11384
|
-
if (ev) {
|
|
11385
|
-
eventBus.emit(`UI:${ev}`, {});
|
|
11386
|
-
e.preventDefault();
|
|
11387
|
-
}
|
|
11388
|
-
};
|
|
11389
|
-
const onUp = (e) => {
|
|
11390
|
-
const ev = keyUpMap?.[e.code];
|
|
11391
|
-
if (ev) eventBus.emit(`UI:${ev}`, {});
|
|
11392
|
-
};
|
|
11393
|
-
window.addEventListener("keydown", onDown);
|
|
11394
|
-
window.addEventListener("keyup", onUp);
|
|
11395
|
-
return () => {
|
|
11396
|
-
window.removeEventListener("keydown", onDown);
|
|
11397
|
-
window.removeEventListener("keyup", onUp);
|
|
11398
|
-
};
|
|
11399
|
-
}, [keyMap, keyUpMap, eventBus]);
|
|
11400
|
-
useEffect(() => {
|
|
11401
|
-
if (!keyMap && !keyUpMap) return;
|
|
11402
|
-
svgRef.current?.focus();
|
|
11403
|
-
}, [keyMap, keyUpMap]);
|
|
11404
|
-
const stageContext = useMemo(() => ({ tileSize }), [tileSize]);
|
|
11405
|
-
return /* @__PURE__ */ jsxs(
|
|
11406
|
-
"svg",
|
|
11407
|
-
{
|
|
11408
|
-
ref: svgRef,
|
|
11409
|
-
"data-testid": "svg-stage",
|
|
11410
|
-
viewBox: `0 0 ${cols * tileSize} ${rows * tileSize}`,
|
|
11411
|
-
preserveAspectRatio: "xMidYMid meet",
|
|
11412
|
-
className: cn("block h-full w-full", className),
|
|
11413
|
-
tabIndex: keyMap || keyUpMap ? 0 : void 0,
|
|
11414
|
-
onPointerDown: handlePointerDown,
|
|
11415
|
-
onPointerMove: handlePointerMove,
|
|
11416
|
-
onPointerUp: handlePointerUp,
|
|
11417
|
-
onPointerLeave: handlePointerLeave,
|
|
11418
|
-
children: [
|
|
11419
|
-
/* @__PURE__ */ jsx("rect", { width: cols * tileSize, height: rows * tileSize, fill: background }),
|
|
11420
|
-
/* @__PURE__ */ jsx(SvgStageContext.Provider, { value: stageContext, children })
|
|
11421
|
-
]
|
|
11422
|
-
}
|
|
11423
|
-
);
|
|
11424
|
-
}
|
|
11425
|
-
var SvgStageContext;
|
|
11426
|
-
var init_SvgStage = __esm({
|
|
11427
|
-
"components/game/molecules/SvgStage.tsx"() {
|
|
11428
|
-
"use client";
|
|
11429
|
-
init_cn();
|
|
11430
|
-
init_useEventBus();
|
|
11431
|
-
SvgStageContext = React92.createContext({ tileSize: 1 });
|
|
11432
|
-
SvgStage.displayName = "SvgStage";
|
|
11433
|
-
}
|
|
11434
|
-
});
|
|
11435
|
-
function SvgDrawShape({
|
|
11436
|
-
shape,
|
|
11437
|
-
x,
|
|
11438
|
-
y,
|
|
11439
|
-
width,
|
|
11440
|
-
height,
|
|
11441
|
-
radius,
|
|
11442
|
-
radiusY,
|
|
11443
|
-
points,
|
|
11444
|
-
d,
|
|
11445
|
-
x2,
|
|
11446
|
-
y2,
|
|
11447
|
-
fill,
|
|
11448
|
-
stroke,
|
|
11449
|
-
strokeWidth,
|
|
11450
|
-
opacity,
|
|
11451
|
-
className
|
|
11452
|
-
}) {
|
|
11453
|
-
const { tileSize } = useContext(SvgStageContext);
|
|
11454
|
-
const cell = (v) => v === void 0 ? void 0 : v * tileSize;
|
|
11455
|
-
const paint = {
|
|
11456
|
-
fill: fill ?? (stroke === void 0 ? "var(--color-primary)" : "none"),
|
|
11457
|
-
stroke,
|
|
11458
|
-
strokeWidth,
|
|
11459
|
-
opacity,
|
|
11460
|
-
className
|
|
11461
|
-
};
|
|
11462
|
-
return /* @__PURE__ */ jsxs("g", { transform: `translate(${x * tileSize} ${y * tileSize})`, children: [
|
|
11463
|
-
shape === "rect" && /* @__PURE__ */ jsx("rect", { width: cell(width), height: cell(height), ...paint }),
|
|
11464
|
-
shape === "circle" && /* @__PURE__ */ jsx("circle", { r: cell(radius), ...paint }),
|
|
11465
|
-
shape === "ellipse" && /* @__PURE__ */ jsx("ellipse", { rx: cell(radius), ry: cell(radiusY ?? radius), ...paint }),
|
|
11466
|
-
shape === "polygon" && /* @__PURE__ */ jsx("polygon", { points, ...paint }),
|
|
11467
|
-
shape === "polyline" && /* @__PURE__ */ jsx("polyline", { points, ...paint }),
|
|
11468
|
-
shape === "path" && /* @__PURE__ */ jsx("path", { d, ...paint }),
|
|
11469
|
-
shape === "line" && /* @__PURE__ */ jsx("line", { x2: cell(x2), y2: cell(y2), ...paint })
|
|
11470
|
-
] });
|
|
11471
|
-
}
|
|
11472
|
-
var init_SvgDrawShape = __esm({
|
|
11473
|
-
"components/game/atoms/SvgDrawShape.tsx"() {
|
|
11474
|
-
"use client";
|
|
11475
|
-
init_SvgStage();
|
|
11476
|
-
SvgDrawShape.displayName = "SvgDrawShape";
|
|
11477
|
-
}
|
|
11478
|
-
});
|
|
11479
|
-
function SvgDrawGroup({
|
|
11480
|
-
x = 0,
|
|
11481
|
-
y = 0,
|
|
11482
|
-
scale,
|
|
11483
|
-
rotate,
|
|
11484
|
-
opacity,
|
|
11485
|
-
className,
|
|
11486
|
-
children
|
|
11487
|
-
}) {
|
|
11488
|
-
const { tileSize } = useContext(SvgStageContext);
|
|
11489
|
-
const transforms = [`translate(${x * tileSize} ${y * tileSize})`];
|
|
11490
|
-
if (rotate !== void 0) transforms.push(`rotate(${rotate})`);
|
|
11491
|
-
if (scale !== void 0) transforms.push(`scale(${scale})`);
|
|
11492
|
-
return /* @__PURE__ */ jsx("g", { transform: transforms.join(" "), opacity, className, children });
|
|
11493
|
-
}
|
|
11494
|
-
var init_SvgDrawGroup = __esm({
|
|
11495
|
-
"components/game/atoms/SvgDrawGroup.tsx"() {
|
|
11496
|
-
"use client";
|
|
11497
|
-
init_SvgStage();
|
|
11498
|
-
SvgDrawGroup.displayName = "SvgDrawGroup";
|
|
11499
|
-
}
|
|
11500
|
-
});
|
|
11501
|
-
function SvgDrawText({
|
|
11502
|
-
x,
|
|
11503
|
-
y,
|
|
11504
|
-
text,
|
|
11505
|
-
size = 12,
|
|
11506
|
-
fill = "var(--color-foreground)",
|
|
11507
|
-
anchor = "middle",
|
|
11508
|
-
className
|
|
11509
|
-
}) {
|
|
11510
|
-
const { tileSize } = useContext(SvgStageContext);
|
|
11511
|
-
return /* @__PURE__ */ jsx(
|
|
11512
|
-
"text",
|
|
11513
|
-
{
|
|
11514
|
-
x: x * tileSize,
|
|
11515
|
-
y: y * tileSize,
|
|
11516
|
-
fontSize: size,
|
|
11517
|
-
fill,
|
|
11518
|
-
textAnchor: anchor,
|
|
11519
|
-
className,
|
|
11520
|
-
children: text
|
|
11521
|
-
}
|
|
11522
|
-
);
|
|
11523
|
-
}
|
|
11524
|
-
var init_SvgDrawText = __esm({
|
|
11525
|
-
"components/game/atoms/SvgDrawText.tsx"() {
|
|
11526
|
-
"use client";
|
|
11527
|
-
init_SvgStage();
|
|
11528
|
-
SvgDrawText.displayName = "SvgDrawText";
|
|
11529
|
-
}
|
|
11530
|
-
});
|
|
11531
11444
|
function ControlGrid({
|
|
11532
11445
|
kind,
|
|
11533
11446
|
buttons = DEFAULT_BUTTONS,
|
|
@@ -12231,6 +12144,7 @@ function MiniMap({
|
|
|
12231
12144
|
const cached = imgCacheRef.current.get(url);
|
|
12232
12145
|
if (cached) return cached.complete ? cached : null;
|
|
12233
12146
|
const img = new Image();
|
|
12147
|
+
img.crossOrigin = "anonymous";
|
|
12234
12148
|
img.src = url;
|
|
12235
12149
|
img.onload = () => {
|
|
12236
12150
|
const canvas = canvasRef.current;
|
|
@@ -12398,7 +12312,7 @@ function useCamera(initial) {
|
|
|
12398
12312
|
const handleWheel = useCallback((e, drawFn) => {
|
|
12399
12313
|
e.preventDefault();
|
|
12400
12314
|
const zoomDelta = e.deltaY > 0 ? 0.9 : 1.1;
|
|
12401
|
-
cameraRef.current.zoom = Math.max(
|
|
12315
|
+
cameraRef.current.zoom = Math.max(MIN_ZOOM, Math.min(MAX_ZOOM, cameraRef.current.zoom * zoomDelta));
|
|
12402
12316
|
drawFn?.();
|
|
12403
12317
|
}, []);
|
|
12404
12318
|
const handlePointerDown = useCallback((e) => {
|
|
@@ -12419,7 +12333,7 @@ function useCamera(initial) {
|
|
|
12419
12333
|
const zoomAtPoint = useCallback((factor, centerX, centerY, viewportSize, drawFn) => {
|
|
12420
12334
|
const cam = cameraRef.current;
|
|
12421
12335
|
const oldZoom = cam.zoom;
|
|
12422
|
-
const newZoom = Math.max(
|
|
12336
|
+
const newZoom = Math.max(MIN_ZOOM, Math.min(MAX_ZOOM, oldZoom * factor));
|
|
12423
12337
|
if (newZoom === oldZoom) {
|
|
12424
12338
|
drawFn?.();
|
|
12425
12339
|
return;
|
|
@@ -12471,9 +12385,12 @@ function useCamera(initial) {
|
|
|
12471
12385
|
lerpToTarget
|
|
12472
12386
|
};
|
|
12473
12387
|
}
|
|
12388
|
+
var MIN_ZOOM, MAX_ZOOM;
|
|
12474
12389
|
var init_useCamera = __esm({
|
|
12475
12390
|
"hooks/useCamera.ts"() {
|
|
12476
12391
|
"use client";
|
|
12392
|
+
MIN_ZOOM = 0.05;
|
|
12393
|
+
MAX_ZOOM = 10;
|
|
12477
12394
|
}
|
|
12478
12395
|
});
|
|
12479
12396
|
function localPoint(canvas, clientX, clientY) {
|
|
@@ -12594,6 +12511,7 @@ function getOrLoadImage(url, onReady) {
|
|
|
12594
12511
|
return null;
|
|
12595
12512
|
}
|
|
12596
12513
|
const img = new Image();
|
|
12514
|
+
img.crossOrigin = "anonymous";
|
|
12597
12515
|
const entry = { img, status: "pending", onReady };
|
|
12598
12516
|
cache.set(url, entry);
|
|
12599
12517
|
updateAssetStatus(url, "pending");
|
|
@@ -12605,10 +12523,14 @@ function getOrLoadImage(url, onReady) {
|
|
|
12605
12523
|
img.onerror = () => {
|
|
12606
12524
|
entry.status = "failed";
|
|
12607
12525
|
updateAssetStatus(url, "failed");
|
|
12526
|
+
entry.onReady?.();
|
|
12608
12527
|
};
|
|
12609
12528
|
img.src = url;
|
|
12610
12529
|
return null;
|
|
12611
12530
|
}
|
|
12531
|
+
function getImageStatus(url) {
|
|
12532
|
+
return cache.get(url)?.status;
|
|
12533
|
+
}
|
|
12612
12534
|
var cache;
|
|
12613
12535
|
var init_imageCache = __esm({
|
|
12614
12536
|
"lib/imageCache.ts"() {
|
|
@@ -12717,6 +12639,15 @@ function createWebPainter(ctx, onAssetLoad) {
|
|
|
12717
12639
|
ctx.lineWidth = lineWidth;
|
|
12718
12640
|
ctx.stroke();
|
|
12719
12641
|
},
|
|
12642
|
+
fillPath(d, color) {
|
|
12643
|
+
ctx.fillStyle = color;
|
|
12644
|
+
ctx.fill(new Path2D(d));
|
|
12645
|
+
},
|
|
12646
|
+
strokePath(d, color, lineWidth = 1) {
|
|
12647
|
+
ctx.strokeStyle = color;
|
|
12648
|
+
ctx.lineWidth = lineWidth;
|
|
12649
|
+
ctx.stroke(new Path2D(d));
|
|
12650
|
+
},
|
|
12720
12651
|
text(str, x, y, style) {
|
|
12721
12652
|
if (style.font) ctx.font = style.font;
|
|
12722
12653
|
ctx.fillStyle = style.color;
|
|
@@ -12738,12 +12669,13 @@ var init_webPainter2d = __esm({
|
|
|
12738
12669
|
|
|
12739
12670
|
// lib/drawable/projector.ts
|
|
12740
12671
|
function create2DProjector(opts) {
|
|
12741
|
-
const {
|
|
12742
|
-
const
|
|
12743
|
-
const
|
|
12744
|
-
const
|
|
12672
|
+
const { baseOffsetX, layout } = opts;
|
|
12673
|
+
const tw = opts.tileWidth ?? TILE_WIDTH;
|
|
12674
|
+
const tileWidth = layout === "free" ? 1 : tw;
|
|
12675
|
+
const floorHeight = layout === "free" ? 1 : tw / 2;
|
|
12676
|
+
const diamondTopY = layout === "free" ? 0 : opts.diamondTopY ?? tw * (DIAMOND_TOP_Y / TILE_WIDTH);
|
|
12745
12677
|
const squareGrid = layout === "flat" || layout === "free";
|
|
12746
|
-
const project = (pos) => layout === "free" ? { x: pos.x, y: pos.y } : isoToScreen(pos.x, pos.y,
|
|
12678
|
+
const project = (pos) => layout === "free" ? { x: pos.x, y: pos.y } : isoToScreen(pos.x, pos.y, tw, baseOffsetX, layout);
|
|
12747
12679
|
const anchorPoint = (pos, anchor) => {
|
|
12748
12680
|
const base = project(pos);
|
|
12749
12681
|
if (anchor === "top-left") return base;
|
|
@@ -12774,7 +12706,7 @@ function create2DProjector(opts) {
|
|
|
12774
12706
|
{ x: base.x, y: topY + floorHeight / 2 }
|
|
12775
12707
|
];
|
|
12776
12708
|
};
|
|
12777
|
-
return { project, anchorPoint, cellPath, tileWidth, floorHeight, diamondTopY,
|
|
12709
|
+
return { project, anchorPoint, cellPath, tileWidth, floorHeight, diamondTopY, squareGrid, worldPixelDirect: layout === "free" };
|
|
12778
12710
|
}
|
|
12779
12711
|
var init_projector = __esm({
|
|
12780
12712
|
"lib/drawable/projector.ts"() {
|
|
@@ -12790,32 +12722,67 @@ var init_contract = __esm({
|
|
|
12790
12722
|
"lib/drawable/contract.ts"() {
|
|
12791
12723
|
}
|
|
12792
12724
|
});
|
|
12793
|
-
|
|
12794
|
-
|
|
12725
|
+
function warnMissingOnce(reason, node) {
|
|
12726
|
+
const key = `${reason}:${node.asset.url}:${String(node.asset.atlas)}:${String(node.asset.sprite)}`;
|
|
12727
|
+
if (loggedMissing.has(key)) return;
|
|
12728
|
+
loggedMissing.add(key);
|
|
12729
|
+
spriteLog.warn("draw-sprite asset unresolvable \u2014 painting fallback square", { reason, url: node.asset.url, atlas: node.asset.atlas, sprite: node.asset.sprite });
|
|
12730
|
+
}
|
|
12731
|
+
function paintFallbackSquare(painter, node, dctx, reason) {
|
|
12732
|
+
warnMissingOnce(reason, node);
|
|
12733
|
+
const tw = dctx.projector.tileWidth;
|
|
12734
|
+
const natural = dctx.projector.worldPixelDirect ? FALLBACK_WORLD_PX : tw;
|
|
12735
|
+
const w = node.width !== void 0 ? node.width * tw : natural;
|
|
12736
|
+
const h = node.height !== void 0 ? node.height * tw : natural;
|
|
12737
|
+
const anchor = node.anchor ?? "top-left";
|
|
12738
|
+
const p = dctx.projector.anchorPoint(node.position, anchor);
|
|
12739
|
+
const dx = anchor === "top-left" ? p.x : p.x - w / 2;
|
|
12740
|
+
const dy = anchor === "ground" ? p.y - h : anchor === "center" ? p.y - h / 2 : p.y;
|
|
12741
|
+
painter.save();
|
|
12742
|
+
if (node.opacity !== void 0 && node.opacity !== 1) painter.setAlpha(node.opacity);
|
|
12743
|
+
painter.fillRect(dx, dy, w, h, "#9b8f7f");
|
|
12744
|
+
painter.strokeRect(dx, dy, w, h, "#5e564b", Math.max(1, tw / 32));
|
|
12745
|
+
painter.restore();
|
|
12746
|
+
}
|
|
12795
12747
|
function DrawSprite(_props) {
|
|
12796
12748
|
return null;
|
|
12797
12749
|
}
|
|
12798
|
-
var paintSprite;
|
|
12750
|
+
var spriteLog, loggedMissing, FALLBACK_WORLD_PX, paintSprite;
|
|
12799
12751
|
var init_DrawSprite = __esm({
|
|
12800
12752
|
"components/game/atoms/DrawSprite.tsx"() {
|
|
12801
12753
|
"use client";
|
|
12802
12754
|
init_atlasSlice();
|
|
12755
|
+
init_imageCache();
|
|
12803
12756
|
init_contract();
|
|
12757
|
+
spriteLog = createLogger("almadar:ui:draw-sprite");
|
|
12758
|
+
loggedMissing = /* @__PURE__ */ new Set();
|
|
12759
|
+
FALLBACK_WORLD_PX = 32;
|
|
12804
12760
|
paintSprite = (painter, node, dctx) => {
|
|
12805
12761
|
if (!node.asset?.url || !isValidScenePos(node.position)) return;
|
|
12806
12762
|
const tex = painter.resolveTexture(node.asset.url);
|
|
12807
|
-
if (!tex)
|
|
12763
|
+
if (!tex) {
|
|
12764
|
+
if (getImageStatus(node.asset.url) === "failed") paintFallbackSquare(painter, node, dctx, "texture-failed");
|
|
12765
|
+
return;
|
|
12766
|
+
}
|
|
12808
12767
|
let src = typeof node.frame === "object" ? node.frame : void 0;
|
|
12809
12768
|
if (!src && isAtlasAsset(node.asset)) {
|
|
12810
12769
|
const atlas = getAtlas(node.asset.atlas, dctx.invalidate);
|
|
12811
|
-
if (!atlas)
|
|
12770
|
+
if (!atlas) {
|
|
12771
|
+
if (atlasFailed(node.asset.atlas)) paintFallbackSquare(painter, node, dctx, "atlas-failed");
|
|
12772
|
+
return;
|
|
12773
|
+
}
|
|
12812
12774
|
const r2 = subRectFor(atlas, node.asset.sprite);
|
|
12813
|
-
if (!r2)
|
|
12775
|
+
if (!r2) {
|
|
12776
|
+
paintFallbackSquare(painter, node, dctx, "sprite-missing");
|
|
12777
|
+
return;
|
|
12778
|
+
}
|
|
12814
12779
|
src = { x: r2.sx, y: r2.sy, w: r2.sw, h: r2.sh };
|
|
12815
12780
|
}
|
|
12816
12781
|
const tw = dctx.projector.tileWidth;
|
|
12817
|
-
const
|
|
12818
|
-
const
|
|
12782
|
+
const fallbackW = dctx.projector.worldPixelDirect ? src ? src.w : tex.width : tw;
|
|
12783
|
+
const fallbackH = dctx.projector.worldPixelDirect ? src ? src.h : tex.height : tw;
|
|
12784
|
+
const w = node.width !== void 0 ? node.width * tw : fallbackW;
|
|
12785
|
+
const h = node.height !== void 0 ? node.height * tw : fallbackH;
|
|
12819
12786
|
const anchor = node.anchor ?? "top-left";
|
|
12820
12787
|
const p = dctx.projector.anchorPoint(node.position, anchor);
|
|
12821
12788
|
const dx = anchor === "top-left" ? p.x : p.x - w / 2;
|
|
@@ -12892,6 +12859,16 @@ var init_DrawShape = __esm({
|
|
|
12892
12859
|
if (node.stroke) painter.strokePoly(pts, node.stroke, node.strokeWidth ?? 1, true);
|
|
12893
12860
|
break;
|
|
12894
12861
|
}
|
|
12862
|
+
case "path": {
|
|
12863
|
+
if (!node.d) break;
|
|
12864
|
+
const base = dctx.projector.project(node.position);
|
|
12865
|
+
const tw = dctx.projector.tileWidth;
|
|
12866
|
+
painter.translate(base.x, base.y);
|
|
12867
|
+
painter.scale(tw, tw);
|
|
12868
|
+
if (node.fill) painter.fillPath(node.d, node.fill);
|
|
12869
|
+
if (node.stroke) painter.strokePath(node.d, node.stroke, (node.strokeWidth ?? 1) / tw);
|
|
12870
|
+
break;
|
|
12871
|
+
}
|
|
12895
12872
|
}
|
|
12896
12873
|
painter.restore();
|
|
12897
12874
|
};
|
|
@@ -12983,6 +12960,19 @@ function paintDrawable(painter, node, dctx) {
|
|
|
12983
12960
|
case "draw-text":
|
|
12984
12961
|
paintText(painter, node, dctx);
|
|
12985
12962
|
break;
|
|
12963
|
+
case "draw-group": {
|
|
12964
|
+
if (!isValidScenePos(node.position)) break;
|
|
12965
|
+
if (!Array.isArray(node.items)) break;
|
|
12966
|
+
const p = dctx.projector.project(node.position);
|
|
12967
|
+
painter.save();
|
|
12968
|
+
painter.translate(p.x, p.y);
|
|
12969
|
+
if (node.scale !== void 0) painter.scale(node.scale, node.scale);
|
|
12970
|
+
if (node.rotate !== void 0) painter.rotate(node.rotate);
|
|
12971
|
+
if (node.opacity !== void 0 && node.opacity !== 1) painter.setAlpha(node.opacity);
|
|
12972
|
+
for (const item of node.items) paintDrawable(painter, item, dctx);
|
|
12973
|
+
painter.restore();
|
|
12974
|
+
break;
|
|
12975
|
+
}
|
|
12986
12976
|
case "draw-sprite-layer":
|
|
12987
12977
|
paintSpriteLayer(painter, node, dctx);
|
|
12988
12978
|
break;
|
|
@@ -12996,6 +12986,7 @@ function paintDrawable(painter, node, dctx) {
|
|
|
12996
12986
|
}
|
|
12997
12987
|
var init_paintDispatch = __esm({
|
|
12998
12988
|
"lib/drawable/paintDispatch.ts"() {
|
|
12989
|
+
init_contract();
|
|
12999
12990
|
init_DrawSprite();
|
|
13000
12991
|
init_DrawShape();
|
|
13001
12992
|
init_DrawText();
|
|
@@ -13013,6 +13004,7 @@ function collectDrawnItems(nodes) {
|
|
|
13013
13004
|
case "draw-sprite":
|
|
13014
13005
|
case "draw-shape":
|
|
13015
13006
|
case "draw-text":
|
|
13007
|
+
case "draw-group":
|
|
13016
13008
|
if (isValidScenePos(n.position)) out.push({ pos: n.position, id: n.id });
|
|
13017
13009
|
break;
|
|
13018
13010
|
case "draw-sprite-layer":
|
|
@@ -13056,6 +13048,8 @@ function Canvas2D({
|
|
|
13056
13048
|
keyUpMap,
|
|
13057
13049
|
camera = "pan-zoom",
|
|
13058
13050
|
scale = 0.4,
|
|
13051
|
+
tileWidth,
|
|
13052
|
+
fit = false,
|
|
13059
13053
|
showMinimap = true,
|
|
13060
13054
|
followTarget,
|
|
13061
13055
|
cameraPos,
|
|
@@ -13098,9 +13092,32 @@ function Canvas2D({
|
|
|
13098
13092
|
observer2.observe(el);
|
|
13099
13093
|
return () => observer2.disconnect();
|
|
13100
13094
|
}, []);
|
|
13101
|
-
const
|
|
13102
|
-
const
|
|
13103
|
-
const
|
|
13095
|
+
const [atlasVersion, setAtlasVersion] = useState(0);
|
|
13096
|
+
const bumpAtlas = useCallback(() => setAtlasVersion((v) => v + 1), []);
|
|
13097
|
+
const detectedTileWidth = useMemo(() => {
|
|
13098
|
+
for (const n of drawables ?? []) {
|
|
13099
|
+
const refs = [];
|
|
13100
|
+
if (n.type === "draw-sprite") refs.push(n.asset);
|
|
13101
|
+
else if (n.type === "draw-sprite-layer") for (const it of n.items) refs.push(it.asset);
|
|
13102
|
+
for (const a of refs) {
|
|
13103
|
+
if (a && isAtlasAsset(a) && a.atlas) {
|
|
13104
|
+
const atlas = getAtlas(a.atlas, bumpAtlas);
|
|
13105
|
+
if (atlas) {
|
|
13106
|
+
if ("tileWidth" in atlas) return atlas.tileWidth;
|
|
13107
|
+
if ("subTextures" in atlas) {
|
|
13108
|
+
const first = Object.values(atlas.subTextures)[0];
|
|
13109
|
+
if (first && typeof first.width === "number") return first.width;
|
|
13110
|
+
}
|
|
13111
|
+
}
|
|
13112
|
+
}
|
|
13113
|
+
}
|
|
13114
|
+
}
|
|
13115
|
+
return void 0;
|
|
13116
|
+
}, [drawables, atlasVersion]);
|
|
13117
|
+
const nativeTileW = tileWidth ?? detectedTileWidth ?? TILE_WIDTH;
|
|
13118
|
+
const scaledTileWidth = nativeTileW;
|
|
13119
|
+
const scaledFloorHeight = nativeTileW / 2;
|
|
13120
|
+
const scaledDiamondTopY = nativeTileW * (DIAMOND_TOP_Y / TILE_WIDTH);
|
|
13104
13121
|
const drawnItems = useMemo(() => collectDrawnItems(drawables ?? []), [drawables]);
|
|
13105
13122
|
const scenePositions = useMemo(() => drawnItems.map((i) => i.pos), [drawnItems]);
|
|
13106
13123
|
const hitIndex = useMemo(() => buildHitIndex(drawnItems), [drawnItems]);
|
|
@@ -13118,14 +13135,36 @@ function Canvas2D({
|
|
|
13118
13135
|
if (isFree || projection === "flat" || projection === "side") return 0;
|
|
13119
13136
|
return (gridExtent.height - 1) * (scaledTileWidth / 2);
|
|
13120
13137
|
}, [isFree, projection, gridExtent.height, scaledTileWidth]);
|
|
13138
|
+
const effectiveZoom = useMemo(() => {
|
|
13139
|
+
if (isFree || projection === "side") return scale;
|
|
13140
|
+
if (!fit) {
|
|
13141
|
+
const z2 = TILE_WIDTH * scale * scale / nativeTileW;
|
|
13142
|
+
return Number.isFinite(z2) && z2 > 0 ? z2 : scale;
|
|
13143
|
+
}
|
|
13144
|
+
if (!viewportSize.width || gridExtent.width < 2 || gridExtent.height < 2) return scale;
|
|
13145
|
+
let boardW;
|
|
13146
|
+
let boardH;
|
|
13147
|
+
if (projection === "flat") {
|
|
13148
|
+
boardW = gridExtent.width * nativeTileW;
|
|
13149
|
+
boardH = gridExtent.height * nativeTileW;
|
|
13150
|
+
} else if (projection === "hex") {
|
|
13151
|
+
boardW = (gridExtent.width + 0.5) * nativeTileW;
|
|
13152
|
+
boardH = gridExtent.height * (nativeTileW / 2) * 0.75 + nativeTileW / 2;
|
|
13153
|
+
} else {
|
|
13154
|
+
boardW = (gridExtent.width + gridExtent.height) * (nativeTileW / 2);
|
|
13155
|
+
boardH = (gridExtent.width + gridExtent.height) * (nativeTileW / 4);
|
|
13156
|
+
}
|
|
13157
|
+
const z = Math.min(viewportSize.width * 0.85 / boardW, viewportSize.height * 0.85 / boardH);
|
|
13158
|
+
return Number.isFinite(z) && z > 0 ? z : scale;
|
|
13159
|
+
}, [isFree, projection, fit, viewportSize, gridExtent, nativeTileW, scale]);
|
|
13121
13160
|
const projector = useMemo(
|
|
13122
|
-
() => create2DProjector({
|
|
13123
|
-
[
|
|
13161
|
+
() => create2DProjector({ tileWidth: nativeTileW, baseOffsetX, layout }),
|
|
13162
|
+
[nativeTileW, baseOffsetX, layout]
|
|
13124
13163
|
);
|
|
13125
13164
|
const unproject = useCallback((screenX, screenY) => {
|
|
13126
13165
|
if (projection === "free" || projection === "side") return { x: Math.round(screenX), y: Math.round(screenY) };
|
|
13127
|
-
return screenToIso(screenX, screenY,
|
|
13128
|
-
}, [projection,
|
|
13166
|
+
return screenToIso(screenX, screenY, nativeTileW, baseOffsetX, projection);
|
|
13167
|
+
}, [projection, nativeTileW, baseOffsetX]);
|
|
13129
13168
|
const bgUrls = useMemo(() => backgroundImage ? [backgroundImage.url] : [], [backgroundImage]);
|
|
13130
13169
|
const { getImage, pendingCount: _imagePendingCount } = useImageCache(bgUrls);
|
|
13131
13170
|
useEffect(() => {
|
|
@@ -13152,9 +13191,7 @@ function Canvas2D({
|
|
|
13152
13191
|
zoomAtPoint,
|
|
13153
13192
|
screenToWorld,
|
|
13154
13193
|
lerpToTarget
|
|
13155
|
-
} = useCamera({ zoom:
|
|
13156
|
-
const [atlasVersion, setAtlasVersion] = useState(0);
|
|
13157
|
-
const bumpAtlas = useCallback(() => setAtlasVersion((v) => v + 1), []);
|
|
13194
|
+
} = useCamera({ zoom: effectiveZoom });
|
|
13158
13195
|
const miniMapTiles = useMemo(() => {
|
|
13159
13196
|
if (!showMinimap) return [];
|
|
13160
13197
|
const color = MINIMAP_TERRAIN_COLORS.default;
|
|
@@ -13229,6 +13266,13 @@ function Canvas2D({
|
|
|
13229
13266
|
useEffect(() => {
|
|
13230
13267
|
draw();
|
|
13231
13268
|
}, [_imagePendingCount, draw]);
|
|
13269
|
+
const userZoomedRef = useRef(false);
|
|
13270
|
+
useEffect(() => {
|
|
13271
|
+
if (userZoomedRef.current) return;
|
|
13272
|
+
if (cameraRef.current.zoom === effectiveZoom) return;
|
|
13273
|
+
cameraRef.current.zoom = effectiveZoom;
|
|
13274
|
+
draw();
|
|
13275
|
+
}, [effectiveZoom, cameraRef, draw]);
|
|
13232
13276
|
useEffect(() => {
|
|
13233
13277
|
draw();
|
|
13234
13278
|
}, [atlasVersion, draw]);
|
|
@@ -13285,7 +13329,9 @@ function Canvas2D({
|
|
|
13285
13329
|
if (tileLeaveEvent) eventBus.emit(`UI:${tileLeaveEvent}`, {});
|
|
13286
13330
|
}, [handleMouseLeave, tileLeaveEvent, eventBus]);
|
|
13287
13331
|
const applyZoom = useCallback((factor, centerX, centerY) => {
|
|
13288
|
-
if (enableCamera)
|
|
13332
|
+
if (!enableCamera) return;
|
|
13333
|
+
userZoomedRef.current = true;
|
|
13334
|
+
zoomAtPoint(factor, centerX, centerY, viewportSize, () => draw());
|
|
13289
13335
|
}, [enableCamera, zoomAtPoint, viewportSize, draw]);
|
|
13290
13336
|
const applyPanDelta = useCallback((dx, dy) => {
|
|
13291
13337
|
if (enableCamera) panBy(dx, dy, () => draw());
|
|
@@ -13470,6 +13516,8 @@ function Canvas({
|
|
|
13470
13516
|
isLoading,
|
|
13471
13517
|
unitScale,
|
|
13472
13518
|
showMinimap,
|
|
13519
|
+
fit,
|
|
13520
|
+
tileWidth,
|
|
13473
13521
|
backgroundImage,
|
|
13474
13522
|
backgroundColor,
|
|
13475
13523
|
worldWidth,
|
|
@@ -13527,6 +13575,8 @@ function Canvas({
|
|
|
13527
13575
|
projection,
|
|
13528
13576
|
camera: to2DCamera(camera?.mode),
|
|
13529
13577
|
...zoom !== void 0 ? { scale: zoom } : {},
|
|
13578
|
+
...fit !== void 0 ? { fit } : {},
|
|
13579
|
+
...tileWidth !== void 0 ? { tileWidth } : {},
|
|
13530
13580
|
...camera?.target !== void 0 ? { followTarget: camera.target } : {},
|
|
13531
13581
|
...camera?.pos !== void 0 ? { cameraPos: camera.pos } : {},
|
|
13532
13582
|
showMinimap,
|
|
@@ -13553,32 +13603,6 @@ var init_Canvas = __esm({
|
|
|
13553
13603
|
Canvas.displayName = "Canvas";
|
|
13554
13604
|
}
|
|
13555
13605
|
});
|
|
13556
|
-
function SvgDrawShapeLayer({
|
|
13557
|
-
items,
|
|
13558
|
-
fill,
|
|
13559
|
-
stroke,
|
|
13560
|
-
strokeWidth,
|
|
13561
|
-
opacity
|
|
13562
|
-
}) {
|
|
13563
|
-
return /* @__PURE__ */ jsx("g", { children: items.map(({ id, ...shape }) => /* @__PURE__ */ jsx(
|
|
13564
|
-
SvgDrawShape,
|
|
13565
|
-
{
|
|
13566
|
-
...shape,
|
|
13567
|
-
fill: shape.fill ?? fill,
|
|
13568
|
-
stroke: shape.stroke ?? stroke,
|
|
13569
|
-
strokeWidth: shape.strokeWidth ?? strokeWidth,
|
|
13570
|
-
opacity: shape.opacity ?? opacity
|
|
13571
|
-
},
|
|
13572
|
-
id
|
|
13573
|
-
)) });
|
|
13574
|
-
}
|
|
13575
|
-
var init_SvgDrawShapeLayer = __esm({
|
|
13576
|
-
"components/game/molecules/SvgDrawShapeLayer.tsx"() {
|
|
13577
|
-
"use client";
|
|
13578
|
-
init_SvgDrawShape();
|
|
13579
|
-
SvgDrawShapeLayer.displayName = "SvgDrawShapeLayer";
|
|
13580
|
-
}
|
|
13581
|
-
});
|
|
13582
13606
|
function GameAudioToggle({
|
|
13583
13607
|
size = "sm",
|
|
13584
13608
|
className,
|
|
@@ -26068,6 +26092,8 @@ function DataList({
|
|
|
26068
26092
|
hasMore,
|
|
26069
26093
|
children,
|
|
26070
26094
|
pageSize = 5,
|
|
26095
|
+
sortBy,
|
|
26096
|
+
sortDirection,
|
|
26071
26097
|
renderItem: schemaRenderItem,
|
|
26072
26098
|
dragGroup,
|
|
26073
26099
|
accepts,
|
|
@@ -26096,7 +26122,11 @@ function DataList({
|
|
|
26096
26122
|
dndItemIdField,
|
|
26097
26123
|
dndRoot
|
|
26098
26124
|
});
|
|
26099
|
-
const
|
|
26125
|
+
const orderedData = dnd.orderedItems;
|
|
26126
|
+
const allData = React92__default.useMemo(
|
|
26127
|
+
() => sortRows(orderedData, sortBy, sortDirection),
|
|
26128
|
+
[orderedData, sortBy, sortDirection]
|
|
26129
|
+
);
|
|
26100
26130
|
const data = pageSize > 0 ? allData.slice(0, visibleCount) : allData;
|
|
26101
26131
|
const hasMoreLocal = pageSize > 0 && visibleCount < allData.length;
|
|
26102
26132
|
const hasRenderProp = typeof children === "function";
|
|
@@ -26133,7 +26163,7 @@ function DataList({
|
|
|
26133
26163
|
};
|
|
26134
26164
|
eventBus.emit(`UI:${action.event}`, payload);
|
|
26135
26165
|
};
|
|
26136
|
-
const renderItemActions = (itemData) => {
|
|
26166
|
+
const renderItemActions = (itemData, onPrimary = false) => {
|
|
26137
26167
|
if (!itemActions || itemActions.length === 0) return null;
|
|
26138
26168
|
const inline = maxInlineActions != null ? itemActions.slice(0, maxInlineActions) : itemActions;
|
|
26139
26169
|
const overflow = maxInlineActions != null ? itemActions.slice(maxInlineActions) : [];
|
|
@@ -26146,7 +26176,12 @@ function DataList({
|
|
|
26146
26176
|
onClick: handleActionClick(action, itemData),
|
|
26147
26177
|
"data-testid": `action-${action.event}`,
|
|
26148
26178
|
"data-row-id": String(itemData.id),
|
|
26149
|
-
className: cn(
|
|
26179
|
+
className: cn(
|
|
26180
|
+
action.variant === "danger" && "text-error hover:bg-error/10",
|
|
26181
|
+
// Must sit on the Button itself: the variant's own text colour
|
|
26182
|
+
// beats an inherited one from the row wrapper.
|
|
26183
|
+
onPrimary && "!text-primary-foreground hover:bg-primary-foreground/15"
|
|
26184
|
+
),
|
|
26150
26185
|
children: [
|
|
26151
26186
|
action.icon && renderIconInput2(action.icon, { size: "xs", className: "mr-1" }),
|
|
26152
26187
|
action.label
|
|
@@ -26246,7 +26281,11 @@ function DataList({
|
|
|
26246
26281
|
metaFields.length > 0 && /* @__PURE__ */ jsx(HStack, { gap: "xs", className: "mt-1 flex-wrap", children: metaFields.map((f3) => {
|
|
26247
26282
|
const v = getNestedValue(itemData, f3.name);
|
|
26248
26283
|
if (v === void 0 || v === null || v === "") return null;
|
|
26249
|
-
return f3.variant === "badge" ?
|
|
26284
|
+
return f3.variant === "badge" ? (
|
|
26285
|
+
// `format` applies here too — a boolean field badged
|
|
26286
|
+
// without it renders the raw "false" instead of "No".
|
|
26287
|
+
/* @__PURE__ */ jsx(Badge, { variant: statusVariant3(String(v)), children: formatValue2(v, f3.format) }, f3.name)
|
|
26288
|
+
) : /* @__PURE__ */ jsx(
|
|
26250
26289
|
Typography,
|
|
26251
26290
|
{
|
|
26252
26291
|
variant: "caption",
|
|
@@ -26265,7 +26304,7 @@ function DataList({
|
|
|
26265
26304
|
children: formatDate(timestamp)
|
|
26266
26305
|
}
|
|
26267
26306
|
) : /* @__PURE__ */ jsx("span", {}),
|
|
26268
|
-
renderItemActions(itemData)
|
|
26307
|
+
renderItemActions(itemData, isSent)
|
|
26269
26308
|
] })
|
|
26270
26309
|
]
|
|
26271
26310
|
}
|
|
@@ -26358,7 +26397,7 @@ function DataList({
|
|
|
26358
26397
|
if (val === void 0 || val === null) return null;
|
|
26359
26398
|
return /* @__PURE__ */ jsxs(HStack, { gap: "xs", className: "items-center flex-shrink-0", children: [
|
|
26360
26399
|
field.icon && renderIconInput2(field.icon, { size: "xs" }),
|
|
26361
|
-
/* @__PURE__ */ jsx(Badge, { variant: statusVariant3(String(val)), children:
|
|
26400
|
+
/* @__PURE__ */ jsx(Badge, { variant: statusVariant3(String(val)), children: formatValue2(val, field.format) })
|
|
26362
26401
|
] }, field.name);
|
|
26363
26402
|
})
|
|
26364
26403
|
] }),
|
|
@@ -26597,6 +26636,182 @@ var init_FormSection = __esm({
|
|
|
26597
26636
|
FormActions.displayName = "FormActions";
|
|
26598
26637
|
}
|
|
26599
26638
|
});
|
|
26639
|
+
var ALL_CATEGORY, MAX_RENDERED, GridPicker;
|
|
26640
|
+
var init_GridPicker = __esm({
|
|
26641
|
+
"components/core/molecules/GridPicker.tsx"() {
|
|
26642
|
+
"use client";
|
|
26643
|
+
init_cn();
|
|
26644
|
+
init_Input();
|
|
26645
|
+
init_Badge();
|
|
26646
|
+
init_Stack();
|
|
26647
|
+
ALL_CATEGORY = "__all__";
|
|
26648
|
+
MAX_RENDERED = 300;
|
|
26649
|
+
GridPicker = ({
|
|
26650
|
+
items,
|
|
26651
|
+
value,
|
|
26652
|
+
onChange,
|
|
26653
|
+
categories,
|
|
26654
|
+
searchPlaceholder,
|
|
26655
|
+
renderThumbnail,
|
|
26656
|
+
cellSize = 32,
|
|
26657
|
+
className
|
|
26658
|
+
}) => {
|
|
26659
|
+
const [search, setSearch] = useState("");
|
|
26660
|
+
const [activeCategory, setActiveCategory] = useState(ALL_CATEGORY);
|
|
26661
|
+
const gridRef = useRef(null);
|
|
26662
|
+
const categoryChips = useMemo(() => {
|
|
26663
|
+
if (categories !== void 0) return categories;
|
|
26664
|
+
const seen = [];
|
|
26665
|
+
for (const item of items) {
|
|
26666
|
+
if (!seen.includes(item.category)) seen.push(item.category);
|
|
26667
|
+
}
|
|
26668
|
+
return seen;
|
|
26669
|
+
}, [categories, items]);
|
|
26670
|
+
const filtered = useMemo(() => {
|
|
26671
|
+
const needle = search.trim().toLowerCase();
|
|
26672
|
+
return items.filter((item) => {
|
|
26673
|
+
const matchesCategory = activeCategory === ALL_CATEGORY || item.category === activeCategory;
|
|
26674
|
+
const matchesSearch = needle === "" || item.label.toLowerCase().includes(needle) || item.keywords !== void 0 && item.keywords.some((k) => k.toLowerCase().includes(needle));
|
|
26675
|
+
return matchesCategory && matchesSearch;
|
|
26676
|
+
});
|
|
26677
|
+
}, [items, search, activeCategory]);
|
|
26678
|
+
const visible = useMemo(() => filtered.slice(0, MAX_RENDERED), [filtered]);
|
|
26679
|
+
const truncated = filtered.length - visible.length;
|
|
26680
|
+
const select = useCallback(
|
|
26681
|
+
(item) => {
|
|
26682
|
+
onChange(item.id);
|
|
26683
|
+
},
|
|
26684
|
+
[onChange]
|
|
26685
|
+
);
|
|
26686
|
+
const handleKeyDown = useCallback(
|
|
26687
|
+
(e, index) => {
|
|
26688
|
+
const cells = gridRef.current?.querySelectorAll(
|
|
26689
|
+
"[data-gridpicker-cell]"
|
|
26690
|
+
);
|
|
26691
|
+
if (cells === void 0 || cells.length === 0) return;
|
|
26692
|
+
const columns = (() => {
|
|
26693
|
+
const grid = gridRef.current;
|
|
26694
|
+
if (grid === null) return 1;
|
|
26695
|
+
const style = window.getComputedStyle(grid);
|
|
26696
|
+
const cols = style.gridTemplateColumns.split(" ").filter(Boolean).length;
|
|
26697
|
+
return cols > 0 ? cols : 1;
|
|
26698
|
+
})();
|
|
26699
|
+
let next = -1;
|
|
26700
|
+
if (e.key === "ArrowRight") next = index + 1;
|
|
26701
|
+
else if (e.key === "ArrowLeft") next = index - 1;
|
|
26702
|
+
else if (e.key === "ArrowDown") next = index + columns;
|
|
26703
|
+
else if (e.key === "ArrowUp") next = index - columns;
|
|
26704
|
+
else if (e.key === "Enter" || e.key === " ") {
|
|
26705
|
+
e.preventDefault();
|
|
26706
|
+
select(filtered[index]);
|
|
26707
|
+
return;
|
|
26708
|
+
} else {
|
|
26709
|
+
return;
|
|
26710
|
+
}
|
|
26711
|
+
e.preventDefault();
|
|
26712
|
+
if (next >= 0 && next < cells.length) {
|
|
26713
|
+
cells[next].focus();
|
|
26714
|
+
}
|
|
26715
|
+
},
|
|
26716
|
+
[filtered, select]
|
|
26717
|
+
);
|
|
26718
|
+
return /* @__PURE__ */ jsxs(VStack, { gap: "sm", className: cn("w-full", className), children: [
|
|
26719
|
+
/* @__PURE__ */ jsx(
|
|
26720
|
+
Input,
|
|
26721
|
+
{
|
|
26722
|
+
type: "search",
|
|
26723
|
+
icon: "search",
|
|
26724
|
+
value: search,
|
|
26725
|
+
placeholder: searchPlaceholder,
|
|
26726
|
+
clearable: true,
|
|
26727
|
+
onClear: () => setSearch(""),
|
|
26728
|
+
onChange: (e) => setSearch(e.target.value)
|
|
26729
|
+
}
|
|
26730
|
+
),
|
|
26731
|
+
categoryChips.length > 0 && /* @__PURE__ */ jsxs(HStack, { gap: "xs", wrap: true, children: [
|
|
26732
|
+
/* @__PURE__ */ jsx(
|
|
26733
|
+
Badge,
|
|
26734
|
+
{
|
|
26735
|
+
variant: activeCategory === ALL_CATEGORY ? "primary" : "neutral",
|
|
26736
|
+
size: "sm",
|
|
26737
|
+
role: "button",
|
|
26738
|
+
tabIndex: 0,
|
|
26739
|
+
"aria-pressed": activeCategory === ALL_CATEGORY,
|
|
26740
|
+
className: "cursor-pointer",
|
|
26741
|
+
onClick: () => setActiveCategory(ALL_CATEGORY),
|
|
26742
|
+
onKeyDown: (e) => {
|
|
26743
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
26744
|
+
e.preventDefault();
|
|
26745
|
+
setActiveCategory(ALL_CATEGORY);
|
|
26746
|
+
}
|
|
26747
|
+
},
|
|
26748
|
+
children: "All"
|
|
26749
|
+
}
|
|
26750
|
+
),
|
|
26751
|
+
categoryChips.map((category) => /* @__PURE__ */ jsx(
|
|
26752
|
+
Badge,
|
|
26753
|
+
{
|
|
26754
|
+
variant: activeCategory === category ? "primary" : "neutral",
|
|
26755
|
+
size: "sm",
|
|
26756
|
+
role: "button",
|
|
26757
|
+
tabIndex: 0,
|
|
26758
|
+
"aria-pressed": activeCategory === category,
|
|
26759
|
+
className: "cursor-pointer",
|
|
26760
|
+
onClick: () => setActiveCategory(category),
|
|
26761
|
+
onKeyDown: (e) => {
|
|
26762
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
26763
|
+
e.preventDefault();
|
|
26764
|
+
setActiveCategory(category);
|
|
26765
|
+
}
|
|
26766
|
+
},
|
|
26767
|
+
children: category
|
|
26768
|
+
},
|
|
26769
|
+
category
|
|
26770
|
+
))
|
|
26771
|
+
] }),
|
|
26772
|
+
/* @__PURE__ */ jsx(
|
|
26773
|
+
"div",
|
|
26774
|
+
{
|
|
26775
|
+
ref: gridRef,
|
|
26776
|
+
role: "listbox",
|
|
26777
|
+
className: "grid gap-1 overflow-y-auto max-h-64 p-1",
|
|
26778
|
+
style: {
|
|
26779
|
+
gridTemplateColumns: `repeat(auto-fill, minmax(${cellSize}px, 1fr))`
|
|
26780
|
+
},
|
|
26781
|
+
children: visible.map((item, index) => {
|
|
26782
|
+
const selected = item.id === value;
|
|
26783
|
+
return /* @__PURE__ */ jsx(
|
|
26784
|
+
"button",
|
|
26785
|
+
{
|
|
26786
|
+
type: "button",
|
|
26787
|
+
role: "option",
|
|
26788
|
+
"aria-selected": selected,
|
|
26789
|
+
"aria-label": item.label,
|
|
26790
|
+
title: item.label,
|
|
26791
|
+
"data-gridpicker-cell": true,
|
|
26792
|
+
tabIndex: selected || value === void 0 && index === 0 ? 0 : -1,
|
|
26793
|
+
onClick: () => select(item),
|
|
26794
|
+
onKeyDown: (e) => handleKeyDown(e, index),
|
|
26795
|
+
className: cn(
|
|
26796
|
+
"flex items-center justify-center rounded-sm",
|
|
26797
|
+
"transition-colors hover:bg-muted",
|
|
26798
|
+
"focus:outline-none focus:ring-1 focus:ring-ring",
|
|
26799
|
+
selected && "bg-primary/10 ring-1 ring-primary"
|
|
26800
|
+
),
|
|
26801
|
+
style: { width: cellSize, height: cellSize },
|
|
26802
|
+
children: renderThumbnail(item)
|
|
26803
|
+
},
|
|
26804
|
+
item.id
|
|
26805
|
+
);
|
|
26806
|
+
})
|
|
26807
|
+
}
|
|
26808
|
+
),
|
|
26809
|
+
truncated > 0 && /* @__PURE__ */ jsx("div", { className: "px-1 text-xs text-muted-foreground", children: `+${truncated} more \u2014 refine your search` })
|
|
26810
|
+
] });
|
|
26811
|
+
};
|
|
26812
|
+
GridPicker.displayName = "GridPicker";
|
|
26813
|
+
}
|
|
26814
|
+
});
|
|
26600
26815
|
function fileIcon(name) {
|
|
26601
26816
|
const ext = name.split(".").pop()?.toLowerCase() ?? "";
|
|
26602
26817
|
switch (ext) {
|
|
@@ -27625,9 +27840,16 @@ var init_Popover = __esm({
|
|
|
27625
27840
|
position = "bottom",
|
|
27626
27841
|
trigger = "click",
|
|
27627
27842
|
showArrow = true,
|
|
27843
|
+
open,
|
|
27844
|
+
onOpenChange,
|
|
27628
27845
|
className
|
|
27629
27846
|
}) => {
|
|
27630
|
-
const [
|
|
27847
|
+
const [uncontrolledOpen, setUncontrolledOpen] = useState(false);
|
|
27848
|
+
const isOpen = open !== void 0 ? open : uncontrolledOpen;
|
|
27849
|
+
const setIsOpen = (next) => {
|
|
27850
|
+
if (open === void 0) setUncontrolledOpen(next);
|
|
27851
|
+
onOpenChange?.(next);
|
|
27852
|
+
};
|
|
27631
27853
|
const [triggerRect, setTriggerRect] = useState(null);
|
|
27632
27854
|
const [popoverWidth, setPopoverWidth] = useState(0);
|
|
27633
27855
|
const triggerRef = useRef(null);
|
|
@@ -27660,6 +27882,23 @@ var init_Popover = __esm({
|
|
|
27660
27882
|
updatePosition();
|
|
27661
27883
|
}
|
|
27662
27884
|
}, [isOpen]);
|
|
27885
|
+
useEffect(() => {
|
|
27886
|
+
if (!isOpen) return;
|
|
27887
|
+
let raf = 0;
|
|
27888
|
+
let lastTop = Number.NaN;
|
|
27889
|
+
let lastLeft = Number.NaN;
|
|
27890
|
+
const track = () => {
|
|
27891
|
+
const rect = triggerRef.current?.getBoundingClientRect();
|
|
27892
|
+
if (rect && (rect.top !== lastTop || rect.left !== lastLeft)) {
|
|
27893
|
+
lastTop = rect.top;
|
|
27894
|
+
lastLeft = rect.left;
|
|
27895
|
+
updatePosition();
|
|
27896
|
+
}
|
|
27897
|
+
raf = requestAnimationFrame(track);
|
|
27898
|
+
};
|
|
27899
|
+
raf = requestAnimationFrame(track);
|
|
27900
|
+
return () => cancelAnimationFrame(raf);
|
|
27901
|
+
}, [isOpen]);
|
|
27663
27902
|
useEffect(() => {
|
|
27664
27903
|
if (!mounted) setPopoverWidth(0);
|
|
27665
27904
|
}, [mounted]);
|
|
@@ -29008,6 +29247,80 @@ var init_FlipCard = __esm({
|
|
|
29008
29247
|
FlipCard.displayName = "FlipCard";
|
|
29009
29248
|
}
|
|
29010
29249
|
});
|
|
29250
|
+
var EMOJI_ITEMS, EmojiPicker;
|
|
29251
|
+
var init_EmojiPicker = __esm({
|
|
29252
|
+
"components/core/molecules/EmojiPicker.tsx"() {
|
|
29253
|
+
"use client";
|
|
29254
|
+
init_useEventBus();
|
|
29255
|
+
init_Button();
|
|
29256
|
+
init_GridPicker();
|
|
29257
|
+
init_Popover();
|
|
29258
|
+
EMOJI_ITEMS = (() => {
|
|
29259
|
+
const items = [];
|
|
29260
|
+
for (const name of ordered) {
|
|
29261
|
+
const entry = lib[name];
|
|
29262
|
+
if (entry === void 0 || entry.char === null || entry.char === "") continue;
|
|
29263
|
+
items.push({
|
|
29264
|
+
id: entry.char,
|
|
29265
|
+
label: name.replace(/_/g, " "),
|
|
29266
|
+
category: entry.category.replace(/_/g, " "),
|
|
29267
|
+
keywords: entry.keywords
|
|
29268
|
+
});
|
|
29269
|
+
}
|
|
29270
|
+
return items;
|
|
29271
|
+
})();
|
|
29272
|
+
EmojiPicker = ({
|
|
29273
|
+
pickEvent,
|
|
29274
|
+
position = "top",
|
|
29275
|
+
triggerIcon = "smile",
|
|
29276
|
+
triggerLabel = "Add emoji",
|
|
29277
|
+
className
|
|
29278
|
+
}) => {
|
|
29279
|
+
const eventBus = useEventBus();
|
|
29280
|
+
const [open, setOpen] = useState(false);
|
|
29281
|
+
const handlePick = (glyph) => {
|
|
29282
|
+
if (pickEvent !== void 0) {
|
|
29283
|
+
const payload = { emoji: glyph };
|
|
29284
|
+
eventBus.emit(`UI:${pickEvent}`, payload);
|
|
29285
|
+
}
|
|
29286
|
+
setOpen(false);
|
|
29287
|
+
};
|
|
29288
|
+
return /* @__PURE__ */ jsx(
|
|
29289
|
+
Popover,
|
|
29290
|
+
{
|
|
29291
|
+
position,
|
|
29292
|
+
trigger: "click",
|
|
29293
|
+
showArrow: false,
|
|
29294
|
+
open,
|
|
29295
|
+
onOpenChange: setOpen,
|
|
29296
|
+
content: /* @__PURE__ */ jsx(
|
|
29297
|
+
GridPicker,
|
|
29298
|
+
{
|
|
29299
|
+
items: EMOJI_ITEMS,
|
|
29300
|
+
onChange: handlePick,
|
|
29301
|
+
searchPlaceholder: "Search emoji\u2026",
|
|
29302
|
+
renderThumbnail: (item) => /* @__PURE__ */ jsx("span", { className: "text-xl leading-none", "aria-hidden": "true", children: item.id }),
|
|
29303
|
+
cellSize: 32,
|
|
29304
|
+
className: "w-80"
|
|
29305
|
+
}
|
|
29306
|
+
),
|
|
29307
|
+
children: /* @__PURE__ */ jsx(
|
|
29308
|
+
Button,
|
|
29309
|
+
{
|
|
29310
|
+
variant: "ghost",
|
|
29311
|
+
icon: triggerIcon,
|
|
29312
|
+
"aria-label": triggerLabel,
|
|
29313
|
+
title: triggerLabel,
|
|
29314
|
+
className,
|
|
29315
|
+
"data-testid": "emoji-picker-trigger"
|
|
29316
|
+
}
|
|
29317
|
+
)
|
|
29318
|
+
}
|
|
29319
|
+
);
|
|
29320
|
+
};
|
|
29321
|
+
EmojiPicker.displayName = "EmojiPicker";
|
|
29322
|
+
}
|
|
29323
|
+
});
|
|
29011
29324
|
function toISODate(d) {
|
|
29012
29325
|
return d.toISOString().slice(0, 10);
|
|
29013
29326
|
}
|
|
@@ -29960,13 +30273,13 @@ var init_MapView = __esm({
|
|
|
29960
30273
|
shadowSize: [41, 41]
|
|
29961
30274
|
});
|
|
29962
30275
|
L.Marker.prototype.options.icon = defaultIcon;
|
|
29963
|
-
const { useEffect:
|
|
30276
|
+
const { useEffect: useEffect63, useRef: useRef63, useCallback: useCallback95, useState: useState99 } = React92__default;
|
|
29964
30277
|
const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
|
|
29965
30278
|
const { useEventBus: useEventBus2 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
|
|
29966
30279
|
function MapUpdater({ centerLat, centerLng, zoom }) {
|
|
29967
30280
|
const map = useMap();
|
|
29968
30281
|
const prevRef = useRef63({ centerLat, centerLng, zoom });
|
|
29969
|
-
|
|
30282
|
+
useEffect63(() => {
|
|
29970
30283
|
const prev = prevRef.current;
|
|
29971
30284
|
if (prev.centerLat !== centerLat || prev.centerLng !== centerLng || prev.zoom !== zoom) {
|
|
29972
30285
|
map.setView([centerLat, centerLng], zoom);
|
|
@@ -29977,7 +30290,7 @@ var init_MapView = __esm({
|
|
|
29977
30290
|
}
|
|
29978
30291
|
function MapClickHandler({ onMapClick }) {
|
|
29979
30292
|
const map = useMap();
|
|
29980
|
-
|
|
30293
|
+
useEffect63(() => {
|
|
29981
30294
|
if (!onMapClick) return;
|
|
29982
30295
|
const handler = (e) => {
|
|
29983
30296
|
onMapClick(e.latlng.lat, e.latlng.lng);
|
|
@@ -30005,7 +30318,7 @@ var init_MapView = __esm({
|
|
|
30005
30318
|
showAttribution = true
|
|
30006
30319
|
}) {
|
|
30007
30320
|
const eventBus = useEventBus2();
|
|
30008
|
-
const [clickedPosition, setClickedPosition] =
|
|
30321
|
+
const [clickedPosition, setClickedPosition] = useState99(null);
|
|
30009
30322
|
const handleMapClick = useCallback95((lat, lng) => {
|
|
30010
30323
|
if (showClickedPin) {
|
|
30011
30324
|
setClickedPosition({ lat, lng });
|
|
@@ -30850,6 +31163,7 @@ function TableView({
|
|
|
30850
31163
|
fields,
|
|
30851
31164
|
itemActions,
|
|
30852
31165
|
maxInlineActions,
|
|
31166
|
+
itemClickEvent,
|
|
30853
31167
|
selectable = false,
|
|
30854
31168
|
selectEvent,
|
|
30855
31169
|
selectedIds,
|
|
@@ -30894,9 +31208,9 @@ function TableView({
|
|
|
30894
31208
|
dndItemIdField,
|
|
30895
31209
|
dndRoot
|
|
30896
31210
|
});
|
|
30897
|
-
const
|
|
30898
|
-
const data = pageSize > 0 ?
|
|
30899
|
-
const hasMore = pageSize > 0 && visibleCount <
|
|
31211
|
+
const ordered2 = dnd.orderedItems;
|
|
31212
|
+
const data = pageSize > 0 ? ordered2.slice(0, visibleCount) : ordered2;
|
|
31213
|
+
const hasMore = pageSize > 0 && visibleCount < ordered2.length;
|
|
30900
31214
|
const hasRenderProp = typeof children === "function";
|
|
30901
31215
|
const idField = dndItemIdField ?? "id";
|
|
30902
31216
|
const isCoarsePointer = useMediaQuery("(pointer: coarse)");
|
|
@@ -30949,6 +31263,14 @@ function TableView({
|
|
|
30949
31263
|
};
|
|
30950
31264
|
eventBus.emit(`UI:${action.event}`, payload);
|
|
30951
31265
|
};
|
|
31266
|
+
const handleRowClick = (row) => () => {
|
|
31267
|
+
if (!itemClickEvent) return;
|
|
31268
|
+
const payload = {
|
|
31269
|
+
id: row.id,
|
|
31270
|
+
row
|
|
31271
|
+
};
|
|
31272
|
+
eventBus.emit(`UI:${itemClickEvent}`, payload);
|
|
31273
|
+
};
|
|
30952
31274
|
const colFloors = React92__default.useMemo(
|
|
30953
31275
|
() => colDefs.map((col) => {
|
|
30954
31276
|
const longest = data.reduce((widest, row) => {
|
|
@@ -31025,10 +31347,12 @@ function TableView({
|
|
|
31025
31347
|
role: "row",
|
|
31026
31348
|
"data-entity-row": true,
|
|
31027
31349
|
"data-entity-id": id,
|
|
31350
|
+
onClick: itemClickEvent ? handleRowClick(row) : void 0,
|
|
31028
31351
|
style: !hasRenderProp ? { gridTemplateColumns } : void 0,
|
|
31029
31352
|
className: cn(
|
|
31030
31353
|
"group items-center gap-3 transition-colors duration-fast",
|
|
31031
31354
|
hasRenderProp ? "flex" : "grid",
|
|
31355
|
+
itemClickEvent && "cursor-pointer",
|
|
31032
31356
|
lk.rowPad,
|
|
31033
31357
|
lk.divider && "border-b border-[var(--color-border)]",
|
|
31034
31358
|
lk.striped && index % 2 === 1 && "bg-[var(--color-surface-subtle)]",
|
|
@@ -31036,7 +31360,7 @@ function TableView({
|
|
|
31036
31360
|
look === "bordered" && "[&>*]:border-r [&>*]:border-[var(--color-border)] [&>*:last-child]:border-r-0"
|
|
31037
31361
|
),
|
|
31038
31362
|
children: [
|
|
31039
|
-
selectable && /* @__PURE__ */ jsx(Box, { className: "flex items-center", children: /* @__PURE__ */ jsx(
|
|
31363
|
+
selectable && /* @__PURE__ */ jsx(Box, { className: "flex items-center", onClick: itemClickEvent ? (e) => e.stopPropagation() : void 0, children: /* @__PURE__ */ jsx(
|
|
31040
31364
|
Checkbox,
|
|
31041
31365
|
{
|
|
31042
31366
|
checked: selected.has(id),
|
|
@@ -31061,6 +31385,7 @@ function TableView({
|
|
|
31061
31385
|
HStack,
|
|
31062
31386
|
{
|
|
31063
31387
|
gap: "xs",
|
|
31388
|
+
onClick: itemClickEvent ? (e) => e.stopPropagation() : void 0,
|
|
31064
31389
|
className: cn(
|
|
31065
31390
|
// Pinned: the fixed column tracks routinely overflow the caller's
|
|
31066
31391
|
// scroll container, which used to leave the actions off-screen.
|
|
@@ -31130,7 +31455,7 @@ function TableView({
|
|
|
31130
31455
|
/* @__PURE__ */ jsx(Icon, { name: "chevron-down", size: "xs", className: "mr-1" }),
|
|
31131
31456
|
t("common.showMore"),
|
|
31132
31457
|
" (",
|
|
31133
|
-
t("common.remaining", { count:
|
|
31458
|
+
t("common.remaining", { count: ordered2.length - visibleCount }),
|
|
31134
31459
|
")"
|
|
31135
31460
|
] }) })
|
|
31136
31461
|
]
|
|
@@ -40160,6 +40485,16 @@ var init_DetailPanel = __esm({
|
|
|
40160
40485
|
DetailPanel.displayName = "DetailPanel";
|
|
40161
40486
|
}
|
|
40162
40487
|
});
|
|
40488
|
+
|
|
40489
|
+
// components/game/atoms/DrawGroup.tsx
|
|
40490
|
+
function DrawGroup(_props) {
|
|
40491
|
+
return null;
|
|
40492
|
+
}
|
|
40493
|
+
var init_DrawGroup = __esm({
|
|
40494
|
+
"components/game/atoms/DrawGroup.tsx"() {
|
|
40495
|
+
"use client";
|
|
40496
|
+
}
|
|
40497
|
+
});
|
|
40163
40498
|
function extractTitle(children) {
|
|
40164
40499
|
if (!React92__default.isValidElement(children)) return void 0;
|
|
40165
40500
|
const props = children.props;
|
|
@@ -45882,6 +46217,7 @@ var init_component_registry_generated = __esm({
|
|
|
45882
46217
|
init_DocSidebar();
|
|
45883
46218
|
init_DocTOC();
|
|
45884
46219
|
init_DocumentViewer();
|
|
46220
|
+
init_DrawGroup();
|
|
45885
46221
|
init_DrawShape();
|
|
45886
46222
|
init_DrawShapeLayer();
|
|
45887
46223
|
init_DrawSprite();
|
|
@@ -45891,6 +46227,7 @@ var init_component_registry_generated = __esm({
|
|
|
45891
46227
|
init_Drawer();
|
|
45892
46228
|
init_DrawerSlot();
|
|
45893
46229
|
init_EdgeDecoration();
|
|
46230
|
+
init_EmojiPicker();
|
|
45894
46231
|
init_EmptyState();
|
|
45895
46232
|
init_ErrorBoundary();
|
|
45896
46233
|
init_ErrorState();
|
|
@@ -46025,10 +46362,6 @@ var init_component_registry_generated = __esm({
|
|
|
46025
46362
|
init_SubagentTracePanel();
|
|
46026
46363
|
init_SvgBranch();
|
|
46027
46364
|
init_SvgConnection();
|
|
46028
|
-
init_SvgDrawGroup();
|
|
46029
|
-
init_SvgDrawShape();
|
|
46030
|
-
init_SvgDrawShapeLayer();
|
|
46031
|
-
init_SvgDrawText();
|
|
46032
46365
|
init_SvgFlow();
|
|
46033
46366
|
init_SvgGrid();
|
|
46034
46367
|
init_SvgLobe();
|
|
@@ -46039,7 +46372,6 @@ var init_component_registry_generated = __esm({
|
|
|
46039
46372
|
init_SvgRing();
|
|
46040
46373
|
init_SvgShield();
|
|
46041
46374
|
init_SvgStack();
|
|
46042
|
-
init_SvgStage();
|
|
46043
46375
|
init_SwipeableRow();
|
|
46044
46376
|
init_Switch();
|
|
46045
46377
|
init_TabbedContainer();
|
|
@@ -46153,6 +46485,7 @@ var init_component_registry_generated = __esm({
|
|
|
46153
46485
|
"DocSidebar": DocSidebar,
|
|
46154
46486
|
"DocTOC": DocTOC,
|
|
46155
46487
|
"DocumentViewer": DocumentViewer,
|
|
46488
|
+
"DrawGroup": DrawGroup,
|
|
46156
46489
|
"DrawShape": DrawShape,
|
|
46157
46490
|
"DrawShapeLayer": DrawShapeLayer,
|
|
46158
46491
|
"DrawSprite": DrawSprite,
|
|
@@ -46162,6 +46495,7 @@ var init_component_registry_generated = __esm({
|
|
|
46162
46495
|
"Drawer": Drawer,
|
|
46163
46496
|
"DrawerSlot": DrawerSlot,
|
|
46164
46497
|
"EdgeDecoration": EdgeDecoration,
|
|
46498
|
+
"EmojiPicker": EmojiPicker,
|
|
46165
46499
|
"EmptyState": EmptyState,
|
|
46166
46500
|
"ErrorBoundary": ErrorBoundary,
|
|
46167
46501
|
"ErrorState": ErrorState,
|
|
@@ -46301,10 +46635,6 @@ var init_component_registry_generated = __esm({
|
|
|
46301
46635
|
"SubagentTracePanel": SubagentTracePanel,
|
|
46302
46636
|
"SvgBranch": SvgBranch,
|
|
46303
46637
|
"SvgConnection": SvgConnection,
|
|
46304
|
-
"SvgDrawGroup": SvgDrawGroup,
|
|
46305
|
-
"SvgDrawShape": SvgDrawShape,
|
|
46306
|
-
"SvgDrawShapeLayer": SvgDrawShapeLayer,
|
|
46307
|
-
"SvgDrawText": SvgDrawText,
|
|
46308
46638
|
"SvgFlow": SvgFlow,
|
|
46309
46639
|
"SvgGrid": SvgGrid,
|
|
46310
46640
|
"SvgLobe": SvgLobe,
|
|
@@ -46315,7 +46645,6 @@ var init_component_registry_generated = __esm({
|
|
|
46315
46645
|
"SvgRing": SvgRing,
|
|
46316
46646
|
"SvgShield": SvgShield,
|
|
46317
46647
|
"SvgStack": SvgStack,
|
|
46318
|
-
"SvgStage": SvgStage,
|
|
46319
46648
|
"SwipeableRow": SwipeableRow,
|
|
46320
46649
|
"Switch": Switch,
|
|
46321
46650
|
"TabbedContainer": TabbedContainer,
|
|
@@ -46594,7 +46923,19 @@ function UISlotComponent({
|
|
|
46594
46923
|
const suspenseConfig = useContext(SuspenseConfigContext);
|
|
46595
46924
|
const contained = useContext(SlotContainedContext);
|
|
46596
46925
|
const schemaCtx = useEntitySchemaOptional();
|
|
46597
|
-
const
|
|
46926
|
+
const rawContent = slots[slot];
|
|
46927
|
+
const binding = useEntityBindingSnapshot(rawContent?.sourceTrait);
|
|
46928
|
+
const content = useMemo(() => {
|
|
46929
|
+
if (!rawContent) return rawContent;
|
|
46930
|
+
const resolvedProps = resolveRenderBindingMarkers(
|
|
46931
|
+
rawContent.props,
|
|
46932
|
+
rawContent.sourceTrait,
|
|
46933
|
+
binding.entity,
|
|
46934
|
+
binding.config,
|
|
46935
|
+
binding.state
|
|
46936
|
+
);
|
|
46937
|
+
return resolvedProps === rawContent.props ? rawContent : { ...rawContent, props: resolvedProps };
|
|
46938
|
+
}, [rawContent, binding.entity, binding.config, binding.state]);
|
|
46598
46939
|
if (children !== void 0) {
|
|
46599
46940
|
if (pattern === "clear") {
|
|
46600
46941
|
return null;
|
|
@@ -46938,6 +47279,7 @@ function isPlainConfigObject(value) {
|
|
|
46938
47279
|
return proto === Object.prototype || proto === null;
|
|
46939
47280
|
}
|
|
46940
47281
|
function substituteTraitRefsDeep(value, pathKey) {
|
|
47282
|
+
if (isRenderBindingMarker(value)) return value;
|
|
46941
47283
|
if (typeof value === "string") {
|
|
46942
47284
|
const match = TRAIT_BINDING_RE.exec(value);
|
|
46943
47285
|
if (match) {
|
|
@@ -47010,7 +47352,14 @@ function SlotContentRenderer({
|
|
|
47010
47352
|
onDismiss,
|
|
47011
47353
|
patternPath
|
|
47012
47354
|
}) {
|
|
47013
|
-
const
|
|
47355
|
+
const ambientScope = useTraitScope();
|
|
47356
|
+
const bindingTrait = content.sourceTrait ?? ambientScope?.trait;
|
|
47357
|
+
const binding = useEntityBindingSnapshot(bindingTrait);
|
|
47358
|
+
const liveProps = useMemo(
|
|
47359
|
+
() => resolveRenderBindingMarkers(content.props, bindingTrait, binding.entity, binding.config, binding.state),
|
|
47360
|
+
[content.props, bindingTrait, binding.entity, binding.config, binding.state]
|
|
47361
|
+
);
|
|
47362
|
+
const entityProp = liveProps.entity;
|
|
47014
47363
|
if (content.pattern === "form-section") {
|
|
47015
47364
|
slotLog.debug("SlotContentRenderer:form-section-render", {
|
|
47016
47365
|
contentId: content.id,
|
|
@@ -47041,7 +47390,7 @@ function SlotContentRenderer({
|
|
|
47041
47390
|
const orbitalName = schemaCtx && content.sourceTrait !== void 0 ? schemaCtx.orbitalsByTrait.get(content.sourceTrait) : void 0;
|
|
47042
47391
|
const PatternComponent = getComponentForPattern(content.pattern);
|
|
47043
47392
|
if (PatternComponent) {
|
|
47044
|
-
const childrenConfig =
|
|
47393
|
+
const childrenConfig = liveProps.children;
|
|
47045
47394
|
const isSingleChild = typeof childrenConfig === "string" || typeof childrenConfig === "object" && childrenConfig !== null && !Array.isArray(childrenConfig) && "type" in childrenConfig;
|
|
47046
47395
|
const hasChildren = PATTERNS_WITH_CHILDREN.has(content.pattern) || Array.isArray(childrenConfig) && childrenConfig.length > 0 || isSingleChild;
|
|
47047
47396
|
const isDrawHost = isDrawHostPattern(content.pattern);
|
|
@@ -47052,9 +47401,9 @@ function SlotContentRenderer({
|
|
|
47052
47401
|
fromState: content.fromState,
|
|
47053
47402
|
entity: content.entity
|
|
47054
47403
|
}) : void 0;
|
|
47055
|
-
const incomingChildren =
|
|
47404
|
+
const incomingChildren = liveProps.children;
|
|
47056
47405
|
const childrenIsRenderFn = typeof incomingChildren === "function";
|
|
47057
|
-
const { children: _childrenConfig, ...restPropsNoChildren } =
|
|
47406
|
+
const { children: _childrenConfig, ...restPropsNoChildren } = liveProps;
|
|
47058
47407
|
const restProps = childrenIsRenderFn ? { ...restPropsNoChildren, children: incomingChildren } : restPropsNoChildren;
|
|
47059
47408
|
const nodeSlotOverrides = {};
|
|
47060
47409
|
for (const slotKey of CONTENT_NODE_SLOTS) {
|
|
@@ -47163,7 +47512,7 @@ function SlotContentRenderer({
|
|
|
47163
47512
|
"data-orb-path": patternPath ?? "root",
|
|
47164
47513
|
"data-orb-pattern": content.pattern,
|
|
47165
47514
|
"data-orb-orbital": orbitalName,
|
|
47166
|
-
children:
|
|
47515
|
+
children: liveProps.children ?? /* @__PURE__ */ jsxs(Box, { className: "p-4 text-sm text-muted-foreground border border-dashed border-border rounded", children: [
|
|
47167
47516
|
"Unknown pattern: ",
|
|
47168
47517
|
content.pattern,
|
|
47169
47518
|
content.sourceTrait && /* @__PURE__ */ jsxs(Typography, { variant: "small", className: "ml-2", children: [
|
|
@@ -47235,6 +47584,7 @@ var scopeWrapLog, TRAIT_BINDING_RE, SuspenseConfigContext, SlotContainedContext,
|
|
|
47235
47584
|
var init_UISlotRenderer = __esm({
|
|
47236
47585
|
"components/core/organisms/UISlotRenderer.tsx"() {
|
|
47237
47586
|
"use client";
|
|
47587
|
+
init_resolve_render_bindings();
|
|
47238
47588
|
init_Modal();
|
|
47239
47589
|
init_Drawer();
|
|
47240
47590
|
init_Toast();
|
|
@@ -50736,6 +51086,9 @@ function resolveLambdaBindings(body, params, item, index) {
|
|
|
50736
51086
|
const arr = body;
|
|
50737
51087
|
const substituted = arr.map((b) => recur(b));
|
|
50738
51088
|
if (isOperatorCall(substituted) && isSExpr(substituted)) {
|
|
51089
|
+
if (containsEntityBinding(substituted)) {
|
|
51090
|
+
return substituted;
|
|
51091
|
+
}
|
|
50739
51092
|
const evaluated = evaluate(substituted, createMinimalContext());
|
|
50740
51093
|
return isEventPayloadValue(evaluated) ? evaluated : String(evaluated);
|
|
50741
51094
|
}
|
|
@@ -50757,9 +51110,37 @@ function getSlotContentRenderer2() {
|
|
|
50757
51110
|
_slotContentRenderer2 = mod.SlotContentRenderer;
|
|
50758
51111
|
return _slotContentRenderer2;
|
|
50759
51112
|
}
|
|
51113
|
+
function deferLambdaEntityExprs(value) {
|
|
51114
|
+
if (typeof value === "string") {
|
|
51115
|
+
if (containsEntityBinding(value)) {
|
|
51116
|
+
const marker = { [RENDER_BINDING_MARKER]: true, expression: value };
|
|
51117
|
+
return marker;
|
|
51118
|
+
}
|
|
51119
|
+
return value;
|
|
51120
|
+
}
|
|
51121
|
+
if (Array.isArray(value)) {
|
|
51122
|
+
if (isFnFormLambda(value)) return value;
|
|
51123
|
+
const arr = value;
|
|
51124
|
+
if (isOperatorCall(arr) && isSExpr(arr) && containsEntityBinding(arr)) {
|
|
51125
|
+
const marker = { [RENDER_BINDING_MARKER]: true, expression: arr };
|
|
51126
|
+
return marker;
|
|
51127
|
+
}
|
|
51128
|
+
return arr.map((v) => deferLambdaEntityExprs(v));
|
|
51129
|
+
}
|
|
51130
|
+
if (value !== null && typeof value === "object" && !React92__default.isValidElement(value) && !(value instanceof Date) && typeof value !== "function" && !isRenderBindingMarker(value)) {
|
|
51131
|
+
const out = {};
|
|
51132
|
+
for (const [k, v] of Object.entries(value)) {
|
|
51133
|
+
out[k] = deferLambdaEntityExprs(v);
|
|
51134
|
+
}
|
|
51135
|
+
return out;
|
|
51136
|
+
}
|
|
51137
|
+
return value;
|
|
51138
|
+
}
|
|
50760
51139
|
function makeLambdaFn(params, lambdaBody, callerKey) {
|
|
50761
51140
|
return (item, index) => {
|
|
50762
|
-
const resolvedBody =
|
|
51141
|
+
const resolvedBody = deferLambdaEntityExprs(
|
|
51142
|
+
resolveLambdaBindings(lambdaBody, params, item, index)
|
|
51143
|
+
);
|
|
50763
51144
|
if (resolvedBody === null || typeof resolvedBody !== "object" || Array.isArray(resolvedBody) || typeof resolvedBody === "function" || React92__default.isValidElement(resolvedBody) || resolvedBody instanceof Date) {
|
|
50764
51145
|
return null;
|
|
50765
51146
|
}
|
|
@@ -50784,6 +51165,7 @@ function makeLambdaFn(params, lambdaBody, callerKey) {
|
|
|
50784
51165
|
}
|
|
50785
51166
|
function convertNode(node, callerKey) {
|
|
50786
51167
|
if (node === null || node === void 0) return node;
|
|
51168
|
+
if (isRenderBindingMarker(node)) return node;
|
|
50787
51169
|
if (Array.isArray(node)) {
|
|
50788
51170
|
if (isFnFormLambda(node)) {
|
|
50789
51171
|
const arr2 = node;
|
|
@@ -50957,6 +51339,7 @@ var tickLog = createLogger("almadar:ui:tick-effects");
|
|
|
50957
51339
|
setNamespaceLevel("almadar:ui:tick-effects", "WARN");
|
|
50958
51340
|
var sharedEntityLog = createLogger("almadar:ui:shared-entity");
|
|
50959
51341
|
setNamespaceLevel("almadar:ui:shared-entity", "WARN");
|
|
51342
|
+
var EMPTY_BINDING_SNAPSHOT = {};
|
|
50960
51343
|
var SYNC_TICK_OPERATORS = /* @__PURE__ */ new Set([
|
|
50961
51344
|
"set",
|
|
50962
51345
|
"emit",
|
|
@@ -50977,11 +51360,6 @@ var SYNC_TICK_OPERATORS = /* @__PURE__ */ new Set([
|
|
|
50977
51360
|
"do",
|
|
50978
51361
|
"when"
|
|
50979
51362
|
]);
|
|
50980
|
-
var REACTIVE_REPAINT_PATTERN_TYPES = /* @__PURE__ */ new Set([
|
|
50981
|
-
"canvas",
|
|
50982
|
-
"game-hud",
|
|
50983
|
-
"game-shell"
|
|
50984
|
-
]);
|
|
50985
51363
|
var LIFECYCLE_EVENTS = ["INIT", "LOAD", "$MOUNT"];
|
|
50986
51364
|
function toTraitDefinition(binding) {
|
|
50987
51365
|
return {
|
|
@@ -51022,6 +51400,27 @@ function classifySharedTick(tick) {
|
|
|
51022
51400
|
if (renders) return "renderer";
|
|
51023
51401
|
return "neither";
|
|
51024
51402
|
}
|
|
51403
|
+
function buildTraitRenderConfig(binding, traitConfigsByName, payload) {
|
|
51404
|
+
const declaredDefaults = collectDeclaredConfigDefaults(binding.trait);
|
|
51405
|
+
const resolvedDefaults = traitConfigsByName?.[binding.trait.name];
|
|
51406
|
+
const callSiteConfig = getBindingConfig(binding);
|
|
51407
|
+
const callSiteOverrides = callSiteConfig ? resolveCallSitePayloadCaptures(
|
|
51408
|
+
Object.fromEntries(
|
|
51409
|
+
Object.entries(callSiteConfig).filter(
|
|
51410
|
+
([, v]) => !containsConfigForward(v)
|
|
51411
|
+
)
|
|
51412
|
+
),
|
|
51413
|
+
payload
|
|
51414
|
+
) : void 0;
|
|
51415
|
+
if (declaredDefaults || resolvedDefaults || callSiteOverrides) {
|
|
51416
|
+
return {
|
|
51417
|
+
...declaredDefaults ?? {},
|
|
51418
|
+
...resolvedDefaults ?? {},
|
|
51419
|
+
...callSiteOverrides ?? {}
|
|
51420
|
+
};
|
|
51421
|
+
}
|
|
51422
|
+
return void 0;
|
|
51423
|
+
}
|
|
51025
51424
|
function createSharedEntityWriter(binding, tick, traitStatesRef, emit) {
|
|
51026
51425
|
return (scratch) => {
|
|
51027
51426
|
const traitName = binding.trait.name;
|
|
@@ -51242,8 +51641,24 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
51242
51641
|
}, [traitStates]);
|
|
51243
51642
|
const traitSnapshotDataRef = useRef(/* @__PURE__ */ new Map());
|
|
51244
51643
|
const traitFieldStatesRef = useRef(/* @__PURE__ */ new Map());
|
|
51245
|
-
const
|
|
51246
|
-
const
|
|
51644
|
+
const bridgeEchoPendingRef = useRef(/* @__PURE__ */ new Map());
|
|
51645
|
+
const bindingSnapshotsRef = useRef(/* @__PURE__ */ new Map());
|
|
51646
|
+
const bindingListenersRef = useRef(/* @__PURE__ */ new Map());
|
|
51647
|
+
const publishBindingSnapshot = useCallback((traitName, row) => {
|
|
51648
|
+
bindingSnapshotsRef.current.set(traitName, { ...row });
|
|
51649
|
+
const listeners7 = bindingListenersRef.current.get(traitName);
|
|
51650
|
+
if (!listeners7) return;
|
|
51651
|
+
listeners7.forEach((callback) => {
|
|
51652
|
+
try {
|
|
51653
|
+
callback();
|
|
51654
|
+
} catch (error) {
|
|
51655
|
+
stateLog.error("binding-snapshot listener error", {
|
|
51656
|
+
traitName,
|
|
51657
|
+
error: error instanceof Error ? error.message : String(error)
|
|
51658
|
+
});
|
|
51659
|
+
}
|
|
51660
|
+
});
|
|
51661
|
+
}, []);
|
|
51247
51662
|
useEffect(() => {
|
|
51248
51663
|
const mgr = managerRef.current;
|
|
51249
51664
|
const bindings = traitBindingsRef.current;
|
|
@@ -51371,15 +51786,6 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
51371
51786
|
const existing = pendingSlots.get(slot) || [];
|
|
51372
51787
|
existing.push({ pattern, props: props || {} });
|
|
51373
51788
|
pendingSlots.set(slot, existing);
|
|
51374
|
-
const patternType = pattern?.type;
|
|
51375
|
-
if (patternType !== void 0 && REACTIVE_REPAINT_PATTERN_TYPES.has(patternType)) {
|
|
51376
|
-
const rawForSlot = effects.filter(
|
|
51377
|
-
(e) => Array.isArray(e) && (e[0] === "render-ui" || e[0] === "render") && e[1] === slot
|
|
51378
|
-
);
|
|
51379
|
-
if (rawForSlot.length > 0) {
|
|
51380
|
-
lastCanvasRenderUiRef.current.set(traitName, rawForSlot);
|
|
51381
|
-
}
|
|
51382
|
-
}
|
|
51383
51789
|
},
|
|
51384
51790
|
clearSlot: (slot) => {
|
|
51385
51791
|
pendingSlots.set(slot, []);
|
|
@@ -51451,11 +51857,13 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
51451
51857
|
};
|
|
51452
51858
|
}
|
|
51453
51859
|
const sharedWrites = [];
|
|
51860
|
+
let didWrite = false;
|
|
51454
51861
|
const baseSet = handlers.set;
|
|
51455
51862
|
handlers = {
|
|
51456
51863
|
...handlers,
|
|
51457
51864
|
set: async (targetId, field, value) => {
|
|
51458
51865
|
if (baseSet) await baseSet(targetId, field, value);
|
|
51866
|
+
didWrite = true;
|
|
51459
51867
|
if (sharedKey !== void 0) {
|
|
51460
51868
|
sharedWrites.push({ field, value });
|
|
51461
51869
|
}
|
|
@@ -51472,23 +51880,9 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
51472
51880
|
payload: payload || {},
|
|
51473
51881
|
state: previousState
|
|
51474
51882
|
};
|
|
51475
|
-
const
|
|
51476
|
-
|
|
51477
|
-
|
|
51478
|
-
const callSiteOverrides = callSiteConfig ? resolveCallSitePayloadCaptures(
|
|
51479
|
-
Object.fromEntries(
|
|
51480
|
-
Object.entries(callSiteConfig).filter(
|
|
51481
|
-
([, v]) => !containsConfigForward(v)
|
|
51482
|
-
)
|
|
51483
|
-
),
|
|
51484
|
-
payload || {}
|
|
51485
|
-
) : void 0;
|
|
51486
|
-
if (declaredDefaults || resolvedDefaults || callSiteOverrides) {
|
|
51487
|
-
bindingCtx.config = {
|
|
51488
|
-
...declaredDefaults ?? {},
|
|
51489
|
-
...resolvedDefaults ?? {},
|
|
51490
|
-
...callSiteOverrides ?? {}
|
|
51491
|
-
};
|
|
51883
|
+
const renderConfig = buildTraitRenderConfig(binding, traitConfigsByName, payload || {});
|
|
51884
|
+
if (renderConfig !== void 0) {
|
|
51885
|
+
bindingCtx.config = renderConfig;
|
|
51492
51886
|
}
|
|
51493
51887
|
if (traitName === "Authority" || traitName === "Hero") {
|
|
51494
51888
|
sharedEntityLog.debug("executeTransitionEffects config tiles", {
|
|
@@ -51522,7 +51916,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
51522
51916
|
effectHeads: effects.map((e) => Array.isArray(e) ? String(e[0]) : "??")
|
|
51523
51917
|
});
|
|
51524
51918
|
}
|
|
51525
|
-
const executor = new EffectExecutor({ handlers: trackingHandlers, bindings: bindingCtx, context: effectContext });
|
|
51919
|
+
const executor = new EffectExecutor({ handlers: trackingHandlers, bindings: bindingCtx, context: effectContext, deferRenderBindings: true });
|
|
51526
51920
|
try {
|
|
51527
51921
|
await executor.executeAll(effects);
|
|
51528
51922
|
if (traitName === "Authority" || traitName === "Hero") {
|
|
@@ -51563,37 +51957,8 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
51563
51957
|
entity: binding.linkedEntity
|
|
51564
51958
|
});
|
|
51565
51959
|
}
|
|
51566
|
-
if (
|
|
51567
|
-
|
|
51568
|
-
if (stashed !== void 0 && stashed.length > 0) {
|
|
51569
|
-
await executor.executeAll(stashed);
|
|
51570
|
-
for (const [slot, patterns] of pendingSlots) {
|
|
51571
|
-
flushSlot(traitName, slot, patterns, {
|
|
51572
|
-
event: flushEvent,
|
|
51573
|
-
state: previousState,
|
|
51574
|
-
entity: binding.linkedEntity
|
|
51575
|
-
});
|
|
51576
|
-
}
|
|
51577
|
-
}
|
|
51578
|
-
if (sharedKey !== void 0 && executeTransitionEffectsRef.current !== null) {
|
|
51579
|
-
for (const sibling of traitBindingsRef.current) {
|
|
51580
|
-
const siblingName = sibling.trait.name;
|
|
51581
|
-
if (siblingName === traitName) continue;
|
|
51582
|
-
if (sharedKeyByTraitNameRef.current.get(siblingName) !== sharedKey) continue;
|
|
51583
|
-
const siblingStash = lastCanvasRenderUiRef.current.get(siblingName);
|
|
51584
|
-
if (siblingStash === void 0 || siblingStash.length === 0) continue;
|
|
51585
|
-
const siblingState = traitStatesRef.current.get(siblingName)?.currentState ?? "";
|
|
51586
|
-
await executeTransitionEffectsRef.current({
|
|
51587
|
-
binding: sibling,
|
|
51588
|
-
effects: siblingStash,
|
|
51589
|
-
previousState: siblingState,
|
|
51590
|
-
newState: siblingState,
|
|
51591
|
-
flushEvent: `${flushEvent}:repaint`,
|
|
51592
|
-
syncOnly,
|
|
51593
|
-
log: log11
|
|
51594
|
-
});
|
|
51595
|
-
}
|
|
51596
|
-
}
|
|
51960
|
+
if (didWrite && sharedKey === void 0) {
|
|
51961
|
+
publishBindingSnapshot(traitName, liveEntity);
|
|
51597
51962
|
}
|
|
51598
51963
|
} catch (error) {
|
|
51599
51964
|
log11.error("effects:error", {
|
|
@@ -51605,10 +51970,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
51605
51970
|
});
|
|
51606
51971
|
}
|
|
51607
51972
|
return emittedDuringExec;
|
|
51608
|
-
}, [eventBus, flushSlot, sharedEntityStore]);
|
|
51609
|
-
useEffect(() => {
|
|
51610
|
-
executeTransitionEffectsRef.current = executeTransitionEffects;
|
|
51611
|
-
}, [executeTransitionEffects]);
|
|
51973
|
+
}, [eventBus, flushSlot, sharedEntityStore, publishBindingSnapshot]);
|
|
51612
51974
|
const runTickEffects = useCallback((tick, binding) => {
|
|
51613
51975
|
const traitName = binding.trait.name;
|
|
51614
51976
|
const currentState = traitStatesRef.current.get(traitName)?.currentState ?? "";
|
|
@@ -51671,24 +52033,6 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
51671
52033
|
({ binding, tick }) => createSharedEntityWriter(binding, tick, traitStatesRef, emitFromSharedWriter)
|
|
51672
52034
|
);
|
|
51673
52035
|
runTickFrame(group.storeKey, writers, sharedEntityStore);
|
|
51674
|
-
const repaint = executeTransitionEffectsRef.current;
|
|
51675
|
-
if (repaint !== null) {
|
|
51676
|
-
for (const renderBinding of group.renderBindings) {
|
|
51677
|
-
const renderTraitName = renderBinding.trait.name;
|
|
51678
|
-
const stash = lastCanvasRenderUiRef.current.get(renderTraitName);
|
|
51679
|
-
if (stash === void 0 || stash.length === 0) continue;
|
|
51680
|
-
const renderState = traitStatesRef.current.get(renderTraitName)?.currentState ?? "";
|
|
51681
|
-
void repaint({
|
|
51682
|
-
binding: renderBinding,
|
|
51683
|
-
effects: stash,
|
|
51684
|
-
previousState: renderState,
|
|
51685
|
-
newState: renderState,
|
|
51686
|
-
flushEvent: "tick:repaint",
|
|
51687
|
-
syncOnly: true,
|
|
51688
|
-
log: sharedEntityLog
|
|
51689
|
-
});
|
|
51690
|
-
}
|
|
51691
|
-
}
|
|
51692
52036
|
};
|
|
51693
52037
|
if (interval === "frame") {
|
|
51694
52038
|
scheduler.add(0, onDue);
|
|
@@ -51759,6 +52103,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
51759
52103
|
executedTraits: results.map((r2) => r2.traitName).join(",")
|
|
51760
52104
|
});
|
|
51761
52105
|
const emittedByTrait = /* @__PURE__ */ new Map();
|
|
52106
|
+
bridgeEchoPendingRef.current.clear();
|
|
51762
52107
|
for (const { traitName, result } of results) {
|
|
51763
52108
|
const binding = bindingMap.get(traitName);
|
|
51764
52109
|
const traitState = currentManager.getState(traitName);
|
|
@@ -51813,6 +52158,12 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
51813
52158
|
log: stateLog
|
|
51814
52159
|
});
|
|
51815
52160
|
emittedByTrait.set(traitName, emittedDuringExec);
|
|
52161
|
+
for (const emittedKey of emittedDuringExec) {
|
|
52162
|
+
bridgeEchoPendingRef.current.set(
|
|
52163
|
+
emittedKey,
|
|
52164
|
+
(bridgeEchoPendingRef.current.get(emittedKey) ?? 0) + 1
|
|
52165
|
+
);
|
|
52166
|
+
}
|
|
51816
52167
|
} else if (!result.executed) {
|
|
51817
52168
|
if (result.guardResult === false) {
|
|
51818
52169
|
stateLog.debug("guard-blocked-transition", {
|
|
@@ -51962,8 +52313,13 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
51962
52313
|
crossTraitLog.debug("self:subscribe", { traitName, busKey: selfBusKey, eventKey });
|
|
51963
52314
|
const unsub = eventBus.on(selfBusKey, (event) => {
|
|
51964
52315
|
if (event.source && event.source.dispatched) {
|
|
51965
|
-
|
|
51966
|
-
|
|
52316
|
+
const pendingEchoes = bridgeEchoPendingRef.current.get(eventKey) ?? 0;
|
|
52317
|
+
if (pendingEchoes > 0) {
|
|
52318
|
+
bridgeEchoPendingRef.current.set(eventKey, pendingEchoes - 1);
|
|
52319
|
+
crossTraitLog.debug("self:fire-skipped-bridge-echo", { traitName, busKey: selfBusKey, eventKey });
|
|
52320
|
+
return;
|
|
52321
|
+
}
|
|
52322
|
+
crossTraitLog.debug("self:fire-server-cascade", { traitName, busKey: selfBusKey, eventKey });
|
|
51967
52323
|
}
|
|
51968
52324
|
crossTraitLog.debug("self:fire", { traitName, busKey: selfBusKey, eventKey });
|
|
51969
52325
|
enqueueAndDrain(eventKey, event.payload, traitName);
|
|
@@ -52055,11 +52411,47 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
|
|
|
52055
52411
|
initedTraitsRef.current = /* @__PURE__ */ new Set();
|
|
52056
52412
|
};
|
|
52057
52413
|
}, [traitBindings, enqueueAndDrain]);
|
|
52414
|
+
const entityBindingSource = useMemo(() => ({
|
|
52415
|
+
getEntitySnapshot: (traitName) => {
|
|
52416
|
+
const sharedKey = sharedKeyByTraitNameRef.current.get(traitName);
|
|
52417
|
+
if (sharedKey !== void 0) {
|
|
52418
|
+
return sharedEntityStore.getSnapshot(sharedKey);
|
|
52419
|
+
}
|
|
52420
|
+
return bindingSnapshotsRef.current.get(traitName) ?? EMPTY_BINDING_SNAPSHOT;
|
|
52421
|
+
},
|
|
52422
|
+
getConfig: (traitName) => {
|
|
52423
|
+
const binding = traitBindingsRef.current.find((b) => b.trait.name === traitName);
|
|
52424
|
+
if (binding === void 0) return void 0;
|
|
52425
|
+
return buildTraitRenderConfig(binding, traitConfigsByName, {});
|
|
52426
|
+
},
|
|
52427
|
+
getState: (traitName) => traitStatesRef.current.get(traitName)?.currentState ?? "",
|
|
52428
|
+
subscribe: (traitName, callback) => {
|
|
52429
|
+
const sharedKey = sharedKeyByTraitNameRef.current.get(traitName);
|
|
52430
|
+
if (sharedKey !== void 0) {
|
|
52431
|
+
return sharedEntityStore.subscribe(sharedKey, callback);
|
|
52432
|
+
}
|
|
52433
|
+
let listeners7 = bindingListenersRef.current.get(traitName);
|
|
52434
|
+
if (!listeners7) {
|
|
52435
|
+
listeners7 = /* @__PURE__ */ new Set();
|
|
52436
|
+
bindingListenersRef.current.set(traitName, listeners7);
|
|
52437
|
+
}
|
|
52438
|
+
listeners7.add(callback);
|
|
52439
|
+
return () => {
|
|
52440
|
+
const current = bindingListenersRef.current.get(traitName);
|
|
52441
|
+
if (!current) return;
|
|
52442
|
+
current.delete(callback);
|
|
52443
|
+
if (current.size === 0) {
|
|
52444
|
+
bindingListenersRef.current.delete(traitName);
|
|
52445
|
+
}
|
|
52446
|
+
};
|
|
52447
|
+
}
|
|
52448
|
+
}), [sharedEntityStore, traitConfigsByName]);
|
|
52058
52449
|
return {
|
|
52059
52450
|
traitStates,
|
|
52060
52451
|
sendEvent,
|
|
52061
52452
|
getTraitState,
|
|
52062
|
-
canHandleEvent
|
|
52453
|
+
canHandleEvent,
|
|
52454
|
+
entityBindingSource
|
|
52063
52455
|
};
|
|
52064
52456
|
}
|
|
52065
52457
|
|
|
@@ -52148,7 +52540,7 @@ function collectServerActiveTraits(ir, allTraits, mountedTraitNames) {
|
|
|
52148
52540
|
}
|
|
52149
52541
|
return active;
|
|
52150
52542
|
}
|
|
52151
|
-
function TraitInitializer({ traits: traits2, routeParams, orbitalNames, onNavigate, onLocalFallback, persistence, traitConfigsByName, orbitalsByTrait, embeddedTraits, serverActiveTraits }) {
|
|
52543
|
+
function TraitInitializer({ traits: traits2, routeParams, orbitalNames, onNavigate, onLocalFallback, persistence, traitConfigsByName, orbitalsByTrait, embeddedTraits, serverActiveTraits, children }) {
|
|
52152
52544
|
const bridge = useServerBridge();
|
|
52153
52545
|
const activeTraitNames = useMemo(
|
|
52154
52546
|
() => new Set(traits2.map((b) => b.trait.name).filter((n) => !!n)),
|
|
@@ -52178,7 +52570,7 @@ function TraitInitializer({ traits: traits2, routeParams, orbitalNames, onNaviga
|
|
|
52178
52570
|
}
|
|
52179
52571
|
}, [bridge.connected, bridge.sendEvent, orbitalNames, uiSlots, onNavigate, embeddedTraits, activeTraitNames, withActiveTraits]);
|
|
52180
52572
|
const opts = orbitalNames ? { onEventProcessed, navigate: onNavigate, traitConfigsByName, orbitalsByTrait, embeddedTraits, initPayload: routeParams } : { navigate: onNavigate, persistence, traitConfigsByName, orbitalsByTrait, embeddedTraits, initPayload: routeParams };
|
|
52181
|
-
const { sendEvent } = useTraitStateMachine(traits2, uiSlots, opts);
|
|
52573
|
+
const { sendEvent, entityBindingSource } = useTraitStateMachine(traits2, uiSlots, opts);
|
|
52182
52574
|
const initSentRef = useRef(false);
|
|
52183
52575
|
const prevTraitsRef = useRef(void 0);
|
|
52184
52576
|
const paramsKey = JSON.stringify(routeParams ?? {});
|
|
@@ -52224,7 +52616,7 @@ function TraitInitializer({ traits: traits2, routeParams, orbitalNames, onNaviga
|
|
|
52224
52616
|
{ type: "fetch", args: [], status: "executed" },
|
|
52225
52617
|
...effects.map((eff) => ({
|
|
52226
52618
|
type: eff.type,
|
|
52227
|
-
args: eff.type === "render-ui" ? [eff.slot] : [],
|
|
52619
|
+
args: eff.type === "render-ui" && eff.slot !== void 0 ? [eff.slot] : [],
|
|
52228
52620
|
status: "executed"
|
|
52229
52621
|
}))
|
|
52230
52622
|
];
|
|
@@ -52240,7 +52632,7 @@ function TraitInitializer({ traits: traits2, routeParams, orbitalNames, onNaviga
|
|
|
52240
52632
|
}
|
|
52241
52633
|
})();
|
|
52242
52634
|
}, [bridge.connected, orbitalNames, bridge.sendEvent, uiSlots, onNavigate, embeddedTraits, activeTraitNames, withActiveTraits, routeParams]);
|
|
52243
|
-
return
|
|
52635
|
+
return /* @__PURE__ */ jsx(EntityBindingContext.Provider, { value: entityBindingSource, children });
|
|
52244
52636
|
}
|
|
52245
52637
|
function SchemaRunner({ schema, serverUrl, transport, mockData, pageName, routeParams, onNavigate, onLocalFallback, persistence }) {
|
|
52246
52638
|
const { traits: traits2, allEntities, allTraits, ir } = useResolvedSchema(schema, pageName);
|
|
@@ -52373,30 +52765,28 @@ function SchemaRunner({ schema, serverUrl, transport, mockData, pageName, routeP
|
|
|
52373
52765
|
}
|
|
52374
52766
|
return schema.orbitals[0]?.theme;
|
|
52375
52767
|
}, [schema, pageName]);
|
|
52376
|
-
const inner = /* @__PURE__ */ jsx(VerificationProvider, { enabled: true, children: /* @__PURE__ */
|
|
52768
|
+
const inner = /* @__PURE__ */ jsx(VerificationProvider, { enabled: true, children: /* @__PURE__ */ jsx(
|
|
52377
52769
|
EntitySchemaProvider,
|
|
52378
52770
|
{
|
|
52379
52771
|
entities: entitiesArray,
|
|
52380
52772
|
traitLinkedEntities: traitLinkedEntitiesMap,
|
|
52381
52773
|
orbitalsByTrait: orbitalsByTraitMap,
|
|
52382
|
-
children:
|
|
52383
|
-
|
|
52384
|
-
|
|
52385
|
-
|
|
52386
|
-
|
|
52387
|
-
|
|
52388
|
-
|
|
52389
|
-
|
|
52390
|
-
|
|
52391
|
-
|
|
52392
|
-
|
|
52393
|
-
|
|
52394
|
-
|
|
52395
|
-
|
|
52396
|
-
|
|
52397
|
-
|
|
52398
|
-
/* @__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 }) }) })
|
|
52399
|
-
]
|
|
52774
|
+
children: /* @__PURE__ */ jsx(
|
|
52775
|
+
TraitInitializer,
|
|
52776
|
+
{
|
|
52777
|
+
traits: allPageTraits,
|
|
52778
|
+
routeParams,
|
|
52779
|
+
orbitalNames: serverUrl || transport ? pageOrbitalNames : void 0,
|
|
52780
|
+
traitConfigsByName,
|
|
52781
|
+
orbitalsByTrait,
|
|
52782
|
+
embeddedTraits,
|
|
52783
|
+
serverActiveTraits,
|
|
52784
|
+
onNavigate,
|
|
52785
|
+
onLocalFallback,
|
|
52786
|
+
persistence,
|
|
52787
|
+
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 }) }) })
|
|
52788
|
+
}
|
|
52789
|
+
)
|
|
52400
52790
|
}
|
|
52401
52791
|
) });
|
|
52402
52792
|
if (serverUrl || transport) {
|