@almadar/ui 2.50.1 → 2.52.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/avl/index.cjs +302 -72
- package/dist/avl/index.d.cts +47 -0
- package/dist/avl/index.js +302 -72
- package/dist/components/index.cjs +35 -3
- package/dist/components/index.js +35 -3
- package/dist/components/molecules/markdown/CodeBlock.d.ts +12 -0
- package/dist/components/organisms/avl/AvlOrbitalsCosmicZoom.d.ts +23 -0
- package/dist/components/organisms/avl/FlowCanvas.d.ts +24 -0
- package/dist/providers/index.cjs +35 -3
- package/dist/providers/index.js +35 -3
- package/dist/runtime/index.cjs +76 -9
- package/dist/runtime/index.js +76 -9
- package/index.css +40 -0
- package/package.json +1 -1
package/dist/avl/index.cjs
CHANGED
|
@@ -19388,13 +19388,13 @@ var MapViewImpl = React125.lazy(async () => {
|
|
|
19388
19388
|
shadowSize: [41, 41]
|
|
19389
19389
|
});
|
|
19390
19390
|
L.Marker.prototype.options.icon = defaultIcon;
|
|
19391
|
-
const { useEffect:
|
|
19391
|
+
const { useEffect: useEffect88, useRef: useRef88, useCallback: useCallback124, useState: useState124 } = React125__namespace.default;
|
|
19392
19392
|
const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
|
|
19393
19393
|
const { useEventBus: useEventBus3 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
|
|
19394
19394
|
function MapUpdater({ centerLat, centerLng, zoom }) {
|
|
19395
19395
|
const map = useMap();
|
|
19396
|
-
const prevRef =
|
|
19397
|
-
|
|
19396
|
+
const prevRef = useRef88({ centerLat, centerLng, zoom });
|
|
19397
|
+
useEffect88(() => {
|
|
19398
19398
|
const prev = prevRef.current;
|
|
19399
19399
|
if (prev.centerLat !== centerLat || prev.centerLng !== centerLng || prev.zoom !== zoom) {
|
|
19400
19400
|
map.setView([centerLat, centerLng], zoom);
|
|
@@ -19405,7 +19405,7 @@ var MapViewImpl = React125.lazy(async () => {
|
|
|
19405
19405
|
}
|
|
19406
19406
|
function MapClickHandler({ onMapClick }) {
|
|
19407
19407
|
const map = useMap();
|
|
19408
|
-
|
|
19408
|
+
useEffect88(() => {
|
|
19409
19409
|
if (!onMapClick) return;
|
|
19410
19410
|
const handler = (e) => {
|
|
19411
19411
|
onMapClick(e.latlng.lat, e.latlng.lng);
|
|
@@ -22118,7 +22118,9 @@ var CodeBlock = React125__namespace.default.memo(
|
|
|
22118
22118
|
showLanguageBadge = true,
|
|
22119
22119
|
maxHeight = "60vh",
|
|
22120
22120
|
foldable: foldableProp,
|
|
22121
|
-
className
|
|
22121
|
+
className,
|
|
22122
|
+
editable = false,
|
|
22123
|
+
onChange
|
|
22122
22124
|
}) => {
|
|
22123
22125
|
const code = typeof rawCode === "string" ? rawCode : String(rawCode ?? "");
|
|
22124
22126
|
const isOrb = language === "orb";
|
|
@@ -22289,7 +22291,37 @@ var CodeBlock = React125__namespace.default.memo(
|
|
|
22289
22291
|
]
|
|
22290
22292
|
}
|
|
22291
22293
|
),
|
|
22292
|
-
|
|
22294
|
+
editable ? (
|
|
22295
|
+
/* GAP-51: editable mode — composes the Textarea atom. Plain text editing,
|
|
22296
|
+
no Prism highlighting overlay (follow-up). The textarea is uncontrolled
|
|
22297
|
+
on the value side: we pass `code` as the initial value and forward
|
|
22298
|
+
every keystroke via onChange — the consumer is responsible for
|
|
22299
|
+
debouncing and re-deriving `code` only after the user stops typing
|
|
22300
|
+
so the cursor doesn't fight a re-render. */
|
|
22301
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
22302
|
+
Textarea,
|
|
22303
|
+
{
|
|
22304
|
+
defaultValue: code,
|
|
22305
|
+
onChange: (e) => onChange?.(e.target.value),
|
|
22306
|
+
spellCheck: false,
|
|
22307
|
+
style: {
|
|
22308
|
+
fontFamily: 'ui-monospace, SFMono-Regular, Menlo, Monaco, "Cascadia Mono", "Courier New", monospace',
|
|
22309
|
+
fontSize: "13px",
|
|
22310
|
+
lineHeight: "1.5",
|
|
22311
|
+
backgroundColor: "#1e1e1e",
|
|
22312
|
+
color: "#e6e6e6",
|
|
22313
|
+
borderRadius: hasHeader ? "0 0 0.5rem 0.5rem" : "0.5rem",
|
|
22314
|
+
border: "none",
|
|
22315
|
+
padding: "1rem",
|
|
22316
|
+
resize: "none",
|
|
22317
|
+
minHeight: "160px",
|
|
22318
|
+
maxHeight,
|
|
22319
|
+
width: "100%",
|
|
22320
|
+
outline: "none"
|
|
22321
|
+
}
|
|
22322
|
+
}
|
|
22323
|
+
)
|
|
22324
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
22293
22325
|
"div",
|
|
22294
22326
|
{
|
|
22295
22327
|
ref: scrollRef,
|
|
@@ -22309,7 +22341,7 @@ var CodeBlock = React125__namespace.default.memo(
|
|
|
22309
22341
|
)
|
|
22310
22342
|
] });
|
|
22311
22343
|
},
|
|
22312
|
-
(prev, next) => prev.language === next.language && prev.code === next.code && prev.showCopyButton === next.showCopyButton && prev.maxHeight === next.maxHeight && prev.foldable === next.foldable
|
|
22344
|
+
(prev, next) => prev.language === next.language && prev.code === next.code && prev.showCopyButton === next.showCopyButton && prev.maxHeight === next.maxHeight && prev.foldable === next.foldable && prev.editable === next.editable && prev.onChange === next.onChange
|
|
22313
22345
|
);
|
|
22314
22346
|
CodeBlock.displayName = "CodeBlock";
|
|
22315
22347
|
|
|
@@ -46481,6 +46513,9 @@ function OrbitalProvider({
|
|
|
46481
46513
|
);
|
|
46482
46514
|
}
|
|
46483
46515
|
OrbitalProvider.displayName = "OrbitalProvider";
|
|
46516
|
+
|
|
46517
|
+
// runtime/OrbPreview.tsx
|
|
46518
|
+
init_useEventBus();
|
|
46484
46519
|
function useResolvedSchema(schema, pageName) {
|
|
46485
46520
|
const [loading, setLoading] = React125.useState(true);
|
|
46486
46521
|
const [error, setError] = React125.useState(null);
|
|
@@ -47250,7 +47285,7 @@ function SlotBridge() {
|
|
|
47250
47285
|
}, [slots, render, clear]);
|
|
47251
47286
|
return null;
|
|
47252
47287
|
}
|
|
47253
|
-
function TraitInitializer({ traits: traits2, orbitalNames, onNavigate }) {
|
|
47288
|
+
function TraitInitializer({ traits: traits2, orbitalNames, onNavigate, onLocalFallback }) {
|
|
47254
47289
|
const slotsActions = useSlotsActions();
|
|
47255
47290
|
const bridge = useServerBridge();
|
|
47256
47291
|
const entityStore = useEntityStore();
|
|
@@ -47291,10 +47326,11 @@ function TraitInitializer({ traits: traits2, orbitalNames, onNavigate }) {
|
|
|
47291
47326
|
const fallback = setTimeout(() => {
|
|
47292
47327
|
if (!initSentRef.current) {
|
|
47293
47328
|
sendEvent("INIT");
|
|
47329
|
+
onLocalFallback?.();
|
|
47294
47330
|
}
|
|
47295
47331
|
}, 5e3);
|
|
47296
47332
|
return () => clearTimeout(fallback);
|
|
47297
|
-
}, [traits2, orbitalNames, sendEvent]);
|
|
47333
|
+
}, [traits2, orbitalNames, sendEvent, onLocalFallback]);
|
|
47298
47334
|
React125.useEffect(() => {
|
|
47299
47335
|
if (!bridge.connected || !orbitalNames?.length || initSentRef.current) return;
|
|
47300
47336
|
initSentRef.current = true;
|
|
@@ -47340,7 +47376,7 @@ function TraitInitializer({ traits: traits2, orbitalNames, onNavigate }) {
|
|
|
47340
47376
|
}, [bridge.connected, orbitalNames, bridge.sendEvent, slotsActions]);
|
|
47341
47377
|
return null;
|
|
47342
47378
|
}
|
|
47343
|
-
function SchemaRunner({ schema, serverUrl, mockData, pageName, onNavigate }) {
|
|
47379
|
+
function SchemaRunner({ schema, serverUrl, mockData, pageName, onNavigate, onLocalFallback }) {
|
|
47344
47380
|
const { traits: traits2, allEntities, ir } = useResolvedSchema(schema, pageName);
|
|
47345
47381
|
const allPageTraits = React125.useMemo(() => {
|
|
47346
47382
|
if (pageName && traits2.length > 0) return traits2;
|
|
@@ -47380,7 +47416,15 @@ function SchemaRunner({ schema, serverUrl, mockData, pageName, onNavigate }) {
|
|
|
47380
47416
|
}
|
|
47381
47417
|
}, [mockKey, serverUrl, mockData, entityStore]);
|
|
47382
47418
|
const inner = /* @__PURE__ */ jsxRuntime.jsx(VerificationProvider, { enabled: true, children: /* @__PURE__ */ jsxRuntime.jsx(SlotsProvider, { children: /* @__PURE__ */ jsxRuntime.jsxs(EntitySchemaProvider, { entities: Array.from(allEntities.values()), children: [
|
|
47383
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
47419
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
47420
|
+
TraitInitializer,
|
|
47421
|
+
{
|
|
47422
|
+
traits: allPageTraits,
|
|
47423
|
+
orbitalNames: serverUrl ? orbitalNames : void 0,
|
|
47424
|
+
onNavigate,
|
|
47425
|
+
onLocalFallback
|
|
47426
|
+
}
|
|
47427
|
+
),
|
|
47384
47428
|
/* @__PURE__ */ jsxRuntime.jsx(SlotBridge, {}),
|
|
47385
47429
|
/* @__PURE__ */ jsxRuntime.jsx(Box, { className: "min-h-full p-4", children: /* @__PURE__ */ jsxRuntime.jsx(UISlotRenderer, { includeHud: true, hudMode: "inline", includeFloating: true }) })
|
|
47386
47430
|
] }) }) });
|
|
@@ -47397,6 +47441,16 @@ function OrbPreview({
|
|
|
47397
47441
|
className,
|
|
47398
47442
|
serverUrl
|
|
47399
47443
|
}) {
|
|
47444
|
+
const [localFallback, setLocalFallback] = React125.useState(false);
|
|
47445
|
+
const eventBus = useEventBus();
|
|
47446
|
+
const handleLocalFallback = React125.useCallback(() => {
|
|
47447
|
+
if (localFallback) return;
|
|
47448
|
+
setLocalFallback(true);
|
|
47449
|
+
eventBus.emit("UI:NOTIFY", {
|
|
47450
|
+
message: "Preview server unreachable \u2014 running locally without server-side state.",
|
|
47451
|
+
severity: "warning"
|
|
47452
|
+
});
|
|
47453
|
+
}, [localFallback, eventBus]);
|
|
47400
47454
|
const parseResult = React125.useMemo(() => {
|
|
47401
47455
|
let parsed;
|
|
47402
47456
|
if (typeof schema === "string") {
|
|
@@ -47454,13 +47508,26 @@ function OrbPreview({
|
|
|
47454
47508
|
el.addEventListener("click", handler, true);
|
|
47455
47509
|
return () => el.removeEventListener("click", handler, true);
|
|
47456
47510
|
}, [pages, handleNavigate]);
|
|
47457
|
-
return /* @__PURE__ */ jsxRuntime.
|
|
47511
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
47458
47512
|
Box,
|
|
47459
47513
|
{
|
|
47460
47514
|
ref: containerRef,
|
|
47461
47515
|
className: `overflow-auto border border-[var(--color-border)] rounded-[var(--radius-md)] ${className ?? ""}`,
|
|
47462
47516
|
style: { height },
|
|
47463
|
-
children:
|
|
47517
|
+
children: [
|
|
47518
|
+
localFallback && /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "px-3 py-2 bg-[var(--color-warning)] bg-opacity-10 border-b border-[var(--color-warning)] flex items-center gap-2", children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", className: "text-[var(--color-warning-foreground)] flex-1", children: "Preview server unreachable \u2014 running locally. Server-side state and persistence are disabled." }) }),
|
|
47519
|
+
/* @__PURE__ */ jsxRuntime.jsx(OrbitalProvider, { initialData: effectiveMockData, skipTheme: true, verification: true, children: /* @__PURE__ */ jsxRuntime.jsx(UISlotProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
47520
|
+
SchemaRunner,
|
|
47521
|
+
{
|
|
47522
|
+
schema: parsedSchema,
|
|
47523
|
+
serverUrl,
|
|
47524
|
+
mockData: effectiveMockData,
|
|
47525
|
+
pageName: currentPage,
|
|
47526
|
+
onNavigate: handleNavigate,
|
|
47527
|
+
onLocalFallback: handleLocalFallback
|
|
47528
|
+
}
|
|
47529
|
+
) }) })
|
|
47530
|
+
]
|
|
47464
47531
|
}
|
|
47465
47532
|
);
|
|
47466
47533
|
}
|
|
@@ -47708,12 +47775,18 @@ var OrbPreviewNodeInner = (props) => {
|
|
|
47708
47775
|
el = el.parentElement;
|
|
47709
47776
|
if (!el || el === contentRef.current) break;
|
|
47710
47777
|
}
|
|
47778
|
+
const containerNode = {
|
|
47779
|
+
orbitalName: data.orbitalName,
|
|
47780
|
+
traitName: data.traitName,
|
|
47781
|
+
transitionEvent: data.transitionEvent
|
|
47782
|
+
};
|
|
47711
47783
|
const containerPath = el?.dataset?.patternPath;
|
|
47712
47784
|
if (!containerPath) {
|
|
47713
|
-
eventBus.emit("UI:
|
|
47785
|
+
eventBus.emit("UI:PATTERN_DROP", {
|
|
47714
47786
|
parentPath: "root",
|
|
47715
47787
|
patternType: payload.data.type,
|
|
47716
|
-
index: 0
|
|
47788
|
+
index: 0,
|
|
47789
|
+
containerNode
|
|
47717
47790
|
});
|
|
47718
47791
|
return;
|
|
47719
47792
|
}
|
|
@@ -47730,12 +47803,13 @@ var OrbPreviewNodeInner = (props) => {
|
|
|
47730
47803
|
break;
|
|
47731
47804
|
}
|
|
47732
47805
|
}
|
|
47733
|
-
eventBus.emit("UI:
|
|
47806
|
+
eventBus.emit("UI:PATTERN_DROP", {
|
|
47734
47807
|
parentPath: containerPath,
|
|
47735
47808
|
patternType: payload.data.type,
|
|
47736
|
-
index: insertIndex
|
|
47809
|
+
index: insertIndex,
|
|
47810
|
+
containerNode
|
|
47737
47811
|
});
|
|
47738
|
-
}, [eventBus]);
|
|
47812
|
+
}, [eventBus, data.orbitalName, data.traitName, data.transitionEvent]);
|
|
47739
47813
|
const handlePreviewDragOver = React125.useCallback((e) => {
|
|
47740
47814
|
if (!e.dataTransfer.types.includes(ALMADAR_DND_MIME)) return;
|
|
47741
47815
|
e.preventDefault();
|
|
@@ -48338,6 +48412,11 @@ function OrbInspector({ node, schema, editable = false, onSchemaChange, onClose
|
|
|
48338
48412
|
] }),
|
|
48339
48413
|
/* @__PURE__ */ jsxRuntime.jsx(Box, { className: "flex-1 overflow-y-auto", children: activeTab === "code" ? (
|
|
48340
48414
|
/* ── Code Tab ── */
|
|
48415
|
+
/* GAP-51: when editable, the CodeBlock molecule renders the existing
|
|
48416
|
+
Textarea atom internally and forwards keystrokes via UI:CODE_CHANGE
|
|
48417
|
+
on the EventBus. The consumer (builder workspace) listens, debounces,
|
|
48418
|
+
parses via safeParseOrbitalSchema, and calls setSchema. Read-only
|
|
48419
|
+
consumers (editable=false) see the existing syntax-highlighted view. */
|
|
48341
48420
|
/* @__PURE__ */ jsxRuntime.jsx(Box, { className: "p-2", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
48342
48421
|
CodeBlock,
|
|
48343
48422
|
{
|
|
@@ -48345,7 +48424,9 @@ function OrbInspector({ node, schema, editable = false, onSchemaChange, onClose
|
|
|
48345
48424
|
language: "orb",
|
|
48346
48425
|
showCopyButton: true,
|
|
48347
48426
|
showLanguageBadge: true,
|
|
48348
|
-
maxHeight: "100%"
|
|
48427
|
+
maxHeight: "100%",
|
|
48428
|
+
editable,
|
|
48429
|
+
onChange: editable ? (code) => eventBus.emit("UI:CODE_CHANGE", { code }) : void 0
|
|
48349
48430
|
}
|
|
48350
48431
|
) })
|
|
48351
48432
|
) : (
|
|
@@ -48638,6 +48719,8 @@ function FlowCanvasInner({
|
|
|
48638
48719
|
height = 500,
|
|
48639
48720
|
onNodeClick,
|
|
48640
48721
|
onLevelChange,
|
|
48722
|
+
onOrbitalDoubleClick,
|
|
48723
|
+
cosmicEntryLevel = "expanded",
|
|
48641
48724
|
initialOrbital,
|
|
48642
48725
|
initialLevel,
|
|
48643
48726
|
initialSelectedNode,
|
|
@@ -48711,11 +48794,24 @@ function FlowCanvasInner({
|
|
|
48711
48794
|
}
|
|
48712
48795
|
if (level === "overview") {
|
|
48713
48796
|
const d = node.data;
|
|
48714
|
-
|
|
48797
|
+
const orbitalName = d.orbitalName ?? node.id;
|
|
48798
|
+
if (onOrbitalDoubleClick && (cosmicEntryLevel === "overview" || cosmicEntryLevel === "both")) {
|
|
48799
|
+
onOrbitalDoubleClick(orbitalName);
|
|
48800
|
+
return;
|
|
48801
|
+
}
|
|
48802
|
+
setExpandedOrbital(orbitalName);
|
|
48715
48803
|
setLevel("expanded");
|
|
48716
|
-
onLevelChange?.("expanded",
|
|
48804
|
+
onLevelChange?.("expanded", orbitalName);
|
|
48805
|
+
return;
|
|
48717
48806
|
}
|
|
48718
|
-
|
|
48807
|
+
if (level === "expanded") {
|
|
48808
|
+
const d = node.data;
|
|
48809
|
+
const orbitalName = d.orbitalName ?? node.id;
|
|
48810
|
+
if (orbitalName && onOrbitalDoubleClick && (cosmicEntryLevel === "expanded" || cosmicEntryLevel === "both")) {
|
|
48811
|
+
onOrbitalDoubleClick(orbitalName);
|
|
48812
|
+
}
|
|
48813
|
+
}
|
|
48814
|
+
}, [level, onLevelChange, onOrbitalDoubleClick, cosmicEntryLevel, atBehaviorLevel, composeLevel]);
|
|
48719
48815
|
const handleNodeClick = React125.useCallback((_, node) => {
|
|
48720
48816
|
const nodeData = node.data;
|
|
48721
48817
|
if (level === "expanded") {
|
|
@@ -48810,10 +48906,10 @@ function FlowCanvasInner({
|
|
|
48810
48906
|
return /* @__PURE__ */ jsxRuntime.jsx(ScreenSizeContext.Provider, { value: screenSize, children: /* @__PURE__ */ jsxRuntime.jsx(PatternSelectionContext.Provider, { value: patternSelectionValue, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
48811
48907
|
Box,
|
|
48812
48908
|
{
|
|
48813
|
-
className: `flex ${className ?? ""}`,
|
|
48909
|
+
className: `flex h-full ${className ?? ""}`,
|
|
48814
48910
|
style: { width, height },
|
|
48815
48911
|
children: [
|
|
48816
|
-
/* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "relative flex-1 min-w-0", children: [
|
|
48912
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "relative flex-1 min-w-0 h-full", children: [
|
|
48817
48913
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
48818
48914
|
react.ReactFlow,
|
|
48819
48915
|
{
|
|
@@ -48830,6 +48926,7 @@ function FlowCanvasInner({
|
|
|
48830
48926
|
minZoom: 0.1,
|
|
48831
48927
|
maxZoom: 2,
|
|
48832
48928
|
fitView: true,
|
|
48929
|
+
fitViewOptions: { padding: 0.15 },
|
|
48833
48930
|
nodesDraggable: true,
|
|
48834
48931
|
elementsSelectable: true,
|
|
48835
48932
|
proOptions: { hideAttribution: true },
|
|
@@ -49249,7 +49346,11 @@ var AvlOrbitalsCosmicZoom = ({
|
|
|
49249
49346
|
color = "var(--color-primary, #4A90D9)",
|
|
49250
49347
|
animated = true,
|
|
49251
49348
|
width = "100%",
|
|
49252
|
-
height = 450
|
|
49349
|
+
height = 450,
|
|
49350
|
+
highlightedOrbital,
|
|
49351
|
+
onOrbitalSelect,
|
|
49352
|
+
minZoom = 0.4,
|
|
49353
|
+
maxZoom = 3
|
|
49253
49354
|
}) => {
|
|
49254
49355
|
const parsedSchema = React125.useMemo(() => {
|
|
49255
49356
|
if (typeof schemaProp === "string") return JSON.parse(schemaProp);
|
|
@@ -49280,10 +49381,83 @@ var AvlOrbitalsCosmicZoom = ({
|
|
|
49280
49381
|
);
|
|
49281
49382
|
const [selected, setSelected] = React125.useState(null);
|
|
49282
49383
|
const handleSelect = React125.useCallback(
|
|
49283
|
-
(name) =>
|
|
49284
|
-
|
|
49384
|
+
(name) => {
|
|
49385
|
+
setSelected((prev) => prev === name ? null : name);
|
|
49386
|
+
onOrbitalSelect?.(name);
|
|
49387
|
+
},
|
|
49388
|
+
[onOrbitalSelect]
|
|
49285
49389
|
);
|
|
49286
49390
|
const selectedView = orbitalViews.find((o) => o.name === selected);
|
|
49391
|
+
const [zoom, setZoom] = React125.useState(1);
|
|
49392
|
+
const [pan, setPan] = React125.useState({ x: 0, y: 0 });
|
|
49393
|
+
const dragStateRef = React125.useRef(null);
|
|
49394
|
+
const transformWrapperRef = React125.useRef(null);
|
|
49395
|
+
const clampZoom = React125.useCallback(
|
|
49396
|
+
(z) => Math.max(minZoom, Math.min(maxZoom, z)),
|
|
49397
|
+
[minZoom, maxZoom]
|
|
49398
|
+
);
|
|
49399
|
+
const handlePointerDown = React125.useCallback((e) => {
|
|
49400
|
+
if (e.target.closest("[data-orbital-tile]")) return;
|
|
49401
|
+
dragStateRef.current = {
|
|
49402
|
+
startX: e.clientX,
|
|
49403
|
+
startY: e.clientY,
|
|
49404
|
+
panX: pan.x,
|
|
49405
|
+
panY: pan.y
|
|
49406
|
+
};
|
|
49407
|
+
e.target.setPointerCapture(e.pointerId);
|
|
49408
|
+
}, [pan]);
|
|
49409
|
+
const handlePointerMove = React125.useCallback((e) => {
|
|
49410
|
+
const drag = dragStateRef.current;
|
|
49411
|
+
if (!drag) return;
|
|
49412
|
+
setPan({
|
|
49413
|
+
x: drag.panX + (e.clientX - drag.startX),
|
|
49414
|
+
y: drag.panY + (e.clientY - drag.startY)
|
|
49415
|
+
});
|
|
49416
|
+
}, []);
|
|
49417
|
+
const handlePointerUp = React125.useCallback((e) => {
|
|
49418
|
+
if (!dragStateRef.current) return;
|
|
49419
|
+
dragStateRef.current = null;
|
|
49420
|
+
try {
|
|
49421
|
+
e.target.releasePointerCapture(e.pointerId);
|
|
49422
|
+
} catch {
|
|
49423
|
+
}
|
|
49424
|
+
}, []);
|
|
49425
|
+
const panRef = React125.useRef(pan);
|
|
49426
|
+
const zoomRef = React125.useRef(zoom);
|
|
49427
|
+
React125.useEffect(() => {
|
|
49428
|
+
panRef.current = pan;
|
|
49429
|
+
}, [pan]);
|
|
49430
|
+
React125.useEffect(() => {
|
|
49431
|
+
zoomRef.current = zoom;
|
|
49432
|
+
}, [zoom]);
|
|
49433
|
+
React125.useEffect(() => {
|
|
49434
|
+
const wrapper = transformWrapperRef.current;
|
|
49435
|
+
if (!wrapper) return;
|
|
49436
|
+
const wheelListener = (e) => {
|
|
49437
|
+
e.preventDefault();
|
|
49438
|
+
const rect = wrapper.getBoundingClientRect();
|
|
49439
|
+
const cursorX = e.clientX - rect.left;
|
|
49440
|
+
const cursorY = e.clientY - rect.top;
|
|
49441
|
+
const currentZoom = zoomRef.current;
|
|
49442
|
+
const currentPan = panRef.current;
|
|
49443
|
+
const worldX = (cursorX - currentPan.x) / currentZoom;
|
|
49444
|
+
const worldY = (cursorY - currentPan.y) / currentZoom;
|
|
49445
|
+
const delta = e.deltaY > 0 ? -0.1 : 0.1;
|
|
49446
|
+
const nextZoom = clampZoom(currentZoom * (1 + delta));
|
|
49447
|
+
const nextPanX = cursorX - worldX * nextZoom;
|
|
49448
|
+
const nextPanY = cursorY - worldY * nextZoom;
|
|
49449
|
+
setZoom(nextZoom);
|
|
49450
|
+
setPan({ x: nextPanX, y: nextPanY });
|
|
49451
|
+
};
|
|
49452
|
+
wrapper.addEventListener("wheel", wheelListener, { passive: false });
|
|
49453
|
+
return () => wrapper.removeEventListener("wheel", wheelListener);
|
|
49454
|
+
}, [clampZoom]);
|
|
49455
|
+
const zoomIn = React125.useCallback(() => setZoom((z) => clampZoom(z * 1.2)), [clampZoom]);
|
|
49456
|
+
const zoomOut = React125.useCallback(() => setZoom((z) => clampZoom(z / 1.2)), [clampZoom]);
|
|
49457
|
+
const resetZoom = React125.useCallback(() => {
|
|
49458
|
+
setZoom(1);
|
|
49459
|
+
setPan({ x: 0, y: 0 });
|
|
49460
|
+
}, []);
|
|
49287
49461
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
49288
49462
|
Box,
|
|
49289
49463
|
{
|
|
@@ -49293,59 +49467,115 @@ var AvlOrbitalsCosmicZoom = ({
|
|
|
49293
49467
|
style: { width, height: containerH },
|
|
49294
49468
|
children: [
|
|
49295
49469
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
49296
|
-
|
|
49470
|
+
"div",
|
|
49297
49471
|
{
|
|
49298
|
-
|
|
49299
|
-
|
|
49300
|
-
|
|
49301
|
-
|
|
49302
|
-
|
|
49303
|
-
|
|
49472
|
+
ref: transformWrapperRef,
|
|
49473
|
+
onPointerDown: handlePointerDown,
|
|
49474
|
+
onPointerMove: handlePointerMove,
|
|
49475
|
+
onPointerUp: handlePointerUp,
|
|
49476
|
+
onPointerCancel: handlePointerUp,
|
|
49477
|
+
style: {
|
|
49478
|
+
position: "absolute",
|
|
49479
|
+
inset: 0,
|
|
49480
|
+
overflow: "hidden",
|
|
49481
|
+
cursor: dragStateRef.current ? "grabbing" : "grab",
|
|
49482
|
+
touchAction: "none"
|
|
49483
|
+
},
|
|
49484
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
49485
|
+
"div",
|
|
49486
|
+
{
|
|
49487
|
+
style: {
|
|
49488
|
+
position: "absolute",
|
|
49489
|
+
inset: 0,
|
|
49490
|
+
transform: `translate(${pan.x}px, ${pan.y}px) scale(${zoom})`,
|
|
49491
|
+
transformOrigin: "0 0"
|
|
49492
|
+
},
|
|
49493
|
+
children: [
|
|
49494
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
49495
|
+
EventWireOverlay,
|
|
49496
|
+
{
|
|
49497
|
+
orbitalViews,
|
|
49498
|
+
crossLinks,
|
|
49499
|
+
color,
|
|
49500
|
+
animated,
|
|
49501
|
+
containerW,
|
|
49502
|
+
containerH
|
|
49503
|
+
}
|
|
49504
|
+
),
|
|
49505
|
+
orbitalViews.map((view) => {
|
|
49506
|
+
const isHighlighted = view.name === highlightedOrbital;
|
|
49507
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
49508
|
+
Box,
|
|
49509
|
+
{
|
|
49510
|
+
role: "button",
|
|
49511
|
+
tabIndex: 0,
|
|
49512
|
+
"data-orbital-tile": "true",
|
|
49513
|
+
onClick: () => handleSelect(view.name),
|
|
49514
|
+
onKeyDown: (e) => {
|
|
49515
|
+
if (e.key === "Enter" || e.key === " ") handleSelect(view.name);
|
|
49516
|
+
},
|
|
49517
|
+
"aria-label": `Orbital: ${view.name}${isHighlighted ? " (highlighted)" : ""}`,
|
|
49518
|
+
position: "absolute",
|
|
49519
|
+
style: {
|
|
49520
|
+
left: view.cx - UNIT_DISPLAY_W / 2,
|
|
49521
|
+
top: view.cy - UNIT_DISPLAY_H / 2,
|
|
49522
|
+
width: UNIT_DISPLAY_W,
|
|
49523
|
+
height: UNIT_DISPLAY_H,
|
|
49524
|
+
cursor: "pointer",
|
|
49525
|
+
transition: "transform 0.2s ease, filter 0.2s ease, box-shadow 0.3s ease",
|
|
49526
|
+
transform: selected === view.name ? "scale(1.05)" : "scale(1)",
|
|
49527
|
+
filter: selected && selected !== view.name ? "opacity(0.5)" : "none",
|
|
49528
|
+
// GAP-52: persistent highlight ring (independent from user selection)
|
|
49529
|
+
boxShadow: isHighlighted ? `0 0 0 3px ${color}, 0 0 24px 4px ${color}` : "none",
|
|
49530
|
+
borderRadius: isHighlighted ? "12px" : void 0,
|
|
49531
|
+
zIndex: isHighlighted ? 11 : selected === view.name ? 10 : 1
|
|
49532
|
+
},
|
|
49533
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
49534
|
+
AvlOrbitalUnit,
|
|
49535
|
+
{
|
|
49536
|
+
entityName: view.entityName,
|
|
49537
|
+
fields: view.fieldCount,
|
|
49538
|
+
persistence: view.persistence,
|
|
49539
|
+
traits: view.traits,
|
|
49540
|
+
pages: view.pages,
|
|
49541
|
+
color,
|
|
49542
|
+
animated: animated && (selected === view.name || isHighlighted)
|
|
49543
|
+
}
|
|
49544
|
+
)
|
|
49545
|
+
},
|
|
49546
|
+
view.name
|
|
49547
|
+
);
|
|
49548
|
+
}),
|
|
49549
|
+
selectedView && /* @__PURE__ */ jsxRuntime.jsx(
|
|
49550
|
+
InfoPanel,
|
|
49551
|
+
{
|
|
49552
|
+
view: selectedView,
|
|
49553
|
+
crossLinks,
|
|
49554
|
+
color
|
|
49555
|
+
}
|
|
49556
|
+
)
|
|
49557
|
+
]
|
|
49558
|
+
}
|
|
49559
|
+
)
|
|
49304
49560
|
}
|
|
49305
49561
|
),
|
|
49306
|
-
|
|
49562
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
49307
49563
|
Box,
|
|
49308
49564
|
{
|
|
49309
|
-
role: "button",
|
|
49310
|
-
tabIndex: 0,
|
|
49311
|
-
onClick: () => handleSelect(view.name),
|
|
49312
|
-
onKeyDown: (e) => {
|
|
49313
|
-
if (e.key === "Enter" || e.key === " ") handleSelect(view.name);
|
|
49314
|
-
},
|
|
49315
|
-
"aria-label": `Orbital: ${view.name}`,
|
|
49316
49565
|
position: "absolute",
|
|
49317
49566
|
style: {
|
|
49318
|
-
|
|
49319
|
-
|
|
49320
|
-
|
|
49321
|
-
|
|
49322
|
-
|
|
49323
|
-
|
|
49324
|
-
transform: selected === view.name ? "scale(1.05)" : "scale(1)",
|
|
49325
|
-
filter: selected && selected !== view.name ? "opacity(0.5)" : "none",
|
|
49326
|
-
zIndex: selected === view.name ? 10 : 1
|
|
49567
|
+
top: 12,
|
|
49568
|
+
right: 12,
|
|
49569
|
+
display: "flex",
|
|
49570
|
+
flexDirection: "column",
|
|
49571
|
+
gap: 4,
|
|
49572
|
+
zIndex: 30
|
|
49327
49573
|
},
|
|
49328
|
-
children:
|
|
49329
|
-
|
|
49330
|
-
{
|
|
49331
|
-
|
|
49332
|
-
|
|
49333
|
-
persistence: view.persistence,
|
|
49334
|
-
traits: view.traits,
|
|
49335
|
-
pages: view.pages,
|
|
49336
|
-
color,
|
|
49337
|
-
animated: animated && selected === view.name
|
|
49338
|
-
}
|
|
49339
|
-
)
|
|
49340
|
-
},
|
|
49341
|
-
view.name
|
|
49342
|
-
)),
|
|
49343
|
-
selectedView && /* @__PURE__ */ jsxRuntime.jsx(
|
|
49344
|
-
InfoPanel,
|
|
49345
|
-
{
|
|
49346
|
-
view: selectedView,
|
|
49347
|
-
crossLinks,
|
|
49348
|
-
color
|
|
49574
|
+
children: [
|
|
49575
|
+
/* @__PURE__ */ jsxRuntime.jsx(Button, { variant: "secondary", size: "sm", onClick: zoomIn, title: "Zoom in", action: "COSMIC_ZOOM_IN", children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "plus", size: "sm" }) }),
|
|
49576
|
+
/* @__PURE__ */ jsxRuntime.jsx(Button, { variant: "secondary", size: "sm", onClick: zoomOut, title: "Zoom out", action: "COSMIC_ZOOM_OUT", children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "minus", size: "sm" }) }),
|
|
49577
|
+
/* @__PURE__ */ jsxRuntime.jsx(Button, { variant: "secondary", size: "sm", onClick: resetZoom, title: "Reset", action: "COSMIC_ZOOM_RESET", children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "maximize", size: "sm" }) })
|
|
49578
|
+
]
|
|
49349
49579
|
}
|
|
49350
49580
|
)
|
|
49351
49581
|
]
|
package/dist/avl/index.d.cts
CHANGED
|
@@ -1210,6 +1210,30 @@ interface FlowCanvasProps {
|
|
|
1210
1210
|
transition?: string;
|
|
1211
1211
|
}) => void;
|
|
1212
1212
|
onLevelChange?: (level: ViewLevel, orbital?: string) => void;
|
|
1213
|
+
/**
|
|
1214
|
+
* GAP-52: fired when the user double-clicks an orbital. Consumers (e.g. the
|
|
1215
|
+
* builder workspace) use this as the trigger to enter cosmic mode
|
|
1216
|
+
* (`AvlOrbitalsCosmicZoom`) for the focused orbital.
|
|
1217
|
+
*
|
|
1218
|
+
* The level at which this fires is controlled by `cosmicEntryLevel` (default
|
|
1219
|
+
* `'expanded'`). At `'expanded'` the existing overview→expanded drill is
|
|
1220
|
+
* preserved — the callback fires only on the second double-click. At
|
|
1221
|
+
* `'overview'` the callback fires on the FIRST double-click and the existing
|
|
1222
|
+
* drill is suppressed for that interaction. `'both'` fires at either level.
|
|
1223
|
+
*
|
|
1224
|
+
* The callback runs unconditionally — persona / permission gating is the
|
|
1225
|
+
* consumer's responsibility.
|
|
1226
|
+
*/
|
|
1227
|
+
onOrbitalDoubleClick?: (orbital: string) => void;
|
|
1228
|
+
/**
|
|
1229
|
+
* GAP-53: which level the `onOrbitalDoubleClick` callback fires at.
|
|
1230
|
+
* - `'expanded'` (default, non-breaking) — fires only at L2 expanded; the
|
|
1231
|
+
* first overview double-click still drills overview→expanded.
|
|
1232
|
+
* - `'overview'` — fires at L1 overview on the FIRST double-click. The
|
|
1233
|
+
* overview→expanded drill is suppressed when the callback is provided.
|
|
1234
|
+
* - `'both'` — fires at either level.
|
|
1235
|
+
*/
|
|
1236
|
+
cosmicEntryLevel?: 'expanded' | 'overview' | 'both';
|
|
1213
1237
|
initialOrbital?: string;
|
|
1214
1238
|
/** Start at Level 2 (expanded) when initialOrbital is set. Default: 'overview'. */
|
|
1215
1239
|
initialLevel?: ViewLevel;
|
|
@@ -1368,6 +1392,29 @@ interface AvlOrbitalsCosmicZoomProps {
|
|
|
1368
1392
|
width?: number | string;
|
|
1369
1393
|
/** Container height */
|
|
1370
1394
|
height?: number | string;
|
|
1395
|
+
/**
|
|
1396
|
+
* GAP-52: name of the orbital to highlight with a persistent ring/glow.
|
|
1397
|
+
* Independent from user-driven selection (click). Used by the builder workspace
|
|
1398
|
+
* when entering cosmic mode from a focused orbital — the focused orbital is
|
|
1399
|
+
* highlighted while the user can still click any other orbital to select it.
|
|
1400
|
+
*/
|
|
1401
|
+
highlightedOrbital?: string;
|
|
1402
|
+
/**
|
|
1403
|
+
* GAP-55: fired when the user clicks an orbital tile. Consumers (e.g. the
|
|
1404
|
+
* builder workspace) use this as the trigger to drill INTO the clicked
|
|
1405
|
+
* orbital — typically by switching back to the canvas tab and opening the
|
|
1406
|
+
* clicked orbital at L2 expanded. Local `selected` toggle (visual highlight +
|
|
1407
|
+
* info panel) still fires regardless of whether the callback is provided.
|
|
1408
|
+
*/
|
|
1409
|
+
onOrbitalSelect?: (orbital: string) => void;
|
|
1410
|
+
/**
|
|
1411
|
+
* GAP-54: minimum zoom factor when scroll-wheel zooming. Default 0.4.
|
|
1412
|
+
*/
|
|
1413
|
+
minZoom?: number;
|
|
1414
|
+
/**
|
|
1415
|
+
* GAP-54: maximum zoom factor when scroll-wheel zooming. Default 3.
|
|
1416
|
+
*/
|
|
1417
|
+
maxZoom?: number;
|
|
1371
1418
|
}
|
|
1372
1419
|
declare const AvlOrbitalsCosmicZoom: React__default.FC<AvlOrbitalsCosmicZoomProps>;
|
|
1373
1420
|
|