@almadar/ui 6.6.0 → 6.8.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 +52 -14
- package/dist/avl/index.js +52 -14
- package/dist/components/index.cjs +67 -14
- package/dist/components/index.d.cts +18 -1
- package/dist/components/index.d.ts +18 -1
- package/dist/components/index.js +67 -15
- package/dist/providers/index.cjs +52 -14
- package/dist/providers/index.js +52 -14
- package/dist/runtime/index.cjs +129 -28
- package/dist/runtime/index.d.cts +29 -0
- package/dist/runtime/index.d.ts +29 -0
- package/dist/runtime/index.js +129 -29
- package/dist/slot-host-Czc2JAxo.d.cts +47 -0
- package/dist/slot-host-Czc2JAxo.d.ts +47 -0
- package/package.json +4 -4
package/dist/runtime/index.d.ts
CHANGED
|
@@ -9,6 +9,7 @@ import { a as EntityBindingSource, h as ServerBridgeTransport } from '../EntityB
|
|
|
9
9
|
export { b as EntitySchemaContextValue, c as EntitySchemaProvider, d as EntitySchemaProviderProps, e as ServerBridgeContextValue, f as ServerBridgeProvider, i as ServerClientEffect, T as TraitContext, k as TraitContextValue, l as TraitInstance, m as TraitProvider, n as TraitProviderProps, o as useEntitySchema, p as useEntitySchemaOptional, q as useServerBridge, r as useTrait, s as useTraitContext } from '../EntityBindingContext-Bn3ePJQC.js';
|
|
10
10
|
export { PERF_NAMESPACE, PerfEntry, PreparedPreviewSchema, adjustSchemaForMockData, buildMockData, clearPerf, perfEnd, perfStart, perfTime, prepareSchemaForPreview, wrapCallbackForEvent } from '@almadar/runtime/ui';
|
|
11
11
|
import React__default, { ReactNode } from 'react';
|
|
12
|
+
export { S as SlotHostManifest, a as SlotHostRegion, b as assertUniqueSlotsPerHost } from '../slot-host-Czc2JAxo.js';
|
|
12
13
|
export { p as profilerOnRender, u as usePerfBuffer } from '../perf-DaVdsbU0.js';
|
|
13
14
|
import '../event-bus-types-Bl78kokd.js';
|
|
14
15
|
import '../useUISlots-GNwGLlW2.js';
|
|
@@ -326,6 +327,34 @@ declare function BrowserPlayground({ schema, mode, initialPagePath, height, clas
|
|
|
326
327
|
* preview has (in-memory persist, mock services); `deny` is an opt-in
|
|
327
328
|
* host policy, never a default sandbox.
|
|
328
329
|
*
|
|
330
|
+
* OUTBOUND = the runtime's internal event bus, not the direct dispatch
|
|
331
|
+
* response. `response.emittedEvents` (mock mode) reflects only the effects
|
|
332
|
+
* of the trait `dispatch()` DIRECTLY targeted — a sibling trait that reacts
|
|
333
|
+
* through the runtime's own cascade (`setupEventListeners`, a SEPARATE
|
|
334
|
+
* `processOrbitalEvent` call whose response is discarded) never shows up
|
|
335
|
+
* there, so its emits never reached the ambient bus (verified 2026-09-04:
|
|
336
|
+
* vim-mode's `Shell` relays `PLUGIN_ENABLED` -> `VimStudioBridge`'s
|
|
337
|
+
* `ENABLED` arm emits `STATUS` + 2x `REGISTER_COMMAND`, none of which
|
|
338
|
+
* reached the studio's status bar/palette). Fix: for `mode: 'mock'`, one
|
|
339
|
+
* `runtime.getEventBus().onAny(...)` subscription per plugin (mounted
|
|
340
|
+
* alongside the runtime, not per-dispatch) is the ONLY outbound path — it
|
|
341
|
+
* sees every emit, direct or cascaded, since every `emit` effect passes
|
|
342
|
+
* through that same bus. `mode: 'server'` has no local bus to subscribe to
|
|
343
|
+
* (the runtime lives on the remote transport), so it keeps reading
|
|
344
|
+
* `response.emittedEvents` for outbound — same single-hop-only limitation
|
|
345
|
+
* this fix removes for mock mode, unaddressed here (no `mode: 'server'`
|
|
346
|
+
* consumer exists yet; see `docs/Almadar_UI_Gaps.md`).
|
|
347
|
+
*
|
|
348
|
+
* RELAY RULE: the plugin's `inbound[]` is its host→plugin vocabulary — one
|
|
349
|
+
* `UI:<busEvent>` bus event per row, dispatching `trigger` at
|
|
350
|
+
* `orbital`/`trait`. Anything a plugin emits under one of those SAME
|
|
351
|
+
* busEvent names (or under an inbound `trigger` name) is a relay for its
|
|
352
|
+
* own siblings' `listens {}` (the runtime's internal event bus already
|
|
353
|
+
* carries that fan-out), never a fresh request back to the host, and must
|
|
354
|
+
* NEVER be re-broadcast — doing so re-fires the very `UI:<busEvent>`
|
|
355
|
+
* listener that produced it, a synchronous self-feeding loop (verified
|
|
356
|
+
* 2026-09-04, see `docs/Almadar_UI_Gaps.md`).
|
|
357
|
+
*
|
|
329
358
|
* @packageDocumentation
|
|
330
359
|
*/
|
|
331
360
|
|
package/dist/runtime/index.js
CHANGED
|
@@ -50993,7 +50993,9 @@ function UISlotComponentInner({
|
|
|
50993
50993
|
className,
|
|
50994
50994
|
children,
|
|
50995
50995
|
pattern,
|
|
50996
|
-
sourceTrait
|
|
50996
|
+
sourceTrait,
|
|
50997
|
+
fallback,
|
|
50998
|
+
mode = "replace"
|
|
50997
50999
|
}) {
|
|
50998
51000
|
const { slots, clear } = useUISlots();
|
|
50999
51001
|
const eventBus = useEventBus();
|
|
@@ -51045,12 +51047,26 @@ function UISlotComponentInner({
|
|
|
51045
51047
|
);
|
|
51046
51048
|
}
|
|
51047
51049
|
if (!content) {
|
|
51050
|
+
if (fallback !== void 0) {
|
|
51051
|
+
return /* @__PURE__ */ jsx(
|
|
51052
|
+
Box,
|
|
51053
|
+
{
|
|
51054
|
+
id: `slot-${slot}`,
|
|
51055
|
+
className: cn("ui-slot", `ui-slot-${slot}`, className),
|
|
51056
|
+
"data-testid": `ui-slot-${slot}`,
|
|
51057
|
+
"data-slot-mode": "fallback",
|
|
51058
|
+
children: fallback
|
|
51059
|
+
}
|
|
51060
|
+
);
|
|
51061
|
+
}
|
|
51048
51062
|
if (!portal) {
|
|
51049
51063
|
return /* @__PURE__ */ jsx(
|
|
51050
51064
|
Box,
|
|
51051
51065
|
{
|
|
51052
51066
|
id: `slot-${slot}`,
|
|
51053
|
-
className: cn("ui-slot", `ui-slot-${slot}`, className)
|
|
51067
|
+
className: cn("ui-slot", `ui-slot-${slot}`, className),
|
|
51068
|
+
"data-testid": `ui-slot-${slot}`,
|
|
51069
|
+
"data-slot-mode": "empty"
|
|
51054
51070
|
}
|
|
51055
51071
|
);
|
|
51056
51072
|
}
|
|
@@ -51067,29 +51083,51 @@ function UISlotComponentInner({
|
|
|
51067
51083
|
clear(slot);
|
|
51068
51084
|
};
|
|
51069
51085
|
if (portal) {
|
|
51070
|
-
|
|
51071
|
-
|
|
51072
|
-
}
|
|
51073
|
-
return /* @__PURE__ */ jsx(
|
|
51074
|
-
SlotPortal,
|
|
51086
|
+
const inlineFallback = mode === "append" && fallback !== void 0 ? /* @__PURE__ */ jsx(
|
|
51087
|
+
Box,
|
|
51075
51088
|
{
|
|
51076
|
-
slot
|
|
51077
|
-
|
|
51078
|
-
|
|
51079
|
-
|
|
51089
|
+
id: `slot-${slot}-fallback`,
|
|
51090
|
+
className: cn("ui-slot", `ui-slot-${slot}-fallback`, className),
|
|
51091
|
+
"data-testid": `ui-slot-${slot}-fallback`,
|
|
51092
|
+
"data-slot-mode": "append",
|
|
51093
|
+
children: fallback
|
|
51080
51094
|
}
|
|
51081
|
-
);
|
|
51095
|
+
) : null;
|
|
51096
|
+
if (contained) {
|
|
51097
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
51098
|
+
inlineFallback,
|
|
51099
|
+
renderContainedPortal(t, slot, content, handleDismiss)
|
|
51100
|
+
] });
|
|
51101
|
+
}
|
|
51102
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
51103
|
+
inlineFallback,
|
|
51104
|
+
/* @__PURE__ */ jsx(
|
|
51105
|
+
SlotPortal,
|
|
51106
|
+
{
|
|
51107
|
+
slot,
|
|
51108
|
+
content,
|
|
51109
|
+
position,
|
|
51110
|
+
onDismiss: handleDismiss
|
|
51111
|
+
}
|
|
51112
|
+
)
|
|
51113
|
+
] });
|
|
51082
51114
|
}
|
|
51083
51115
|
const slotContent = /* @__PURE__ */ jsx(SlotContentRenderer, { content, onDismiss: handleDismiss });
|
|
51084
51116
|
const wrappedContent = suspenseConfig.enabled ? /* @__PURE__ */ jsx(ErrorBoundary, { children: /* @__PURE__ */ jsx(Suspense, { fallback: getSlotFallback(slot, suspenseConfig), children: slotContent }) }) : /* @__PURE__ */ jsx(ErrorBoundary, { children: slotContent });
|
|
51085
|
-
|
|
51117
|
+
const showFallback = mode === "append" && fallback !== void 0;
|
|
51118
|
+
return /* @__PURE__ */ jsxs(
|
|
51086
51119
|
Box,
|
|
51087
51120
|
{
|
|
51088
51121
|
id: `slot-${slot}`,
|
|
51089
51122
|
className: cn("ui-slot", `ui-slot-${slot}`, className),
|
|
51090
51123
|
"data-pattern": content.pattern,
|
|
51091
51124
|
"data-source-trait": content.sourceTrait,
|
|
51092
|
-
|
|
51125
|
+
"data-testid": `ui-slot-${slot}`,
|
|
51126
|
+
"data-slot-mode": showFallback ? "append" : "content",
|
|
51127
|
+
children: [
|
|
51128
|
+
showFallback ? fallback : null,
|
|
51129
|
+
/* @__PURE__ */ jsx(MaybeTraitScope, { sourceTrait: content.sourceTrait, children: wrappedContent })
|
|
51130
|
+
]
|
|
51093
51131
|
}
|
|
51094
51132
|
);
|
|
51095
51133
|
}
|
|
@@ -54169,17 +54207,30 @@ function PluginRuntimeMount({
|
|
|
54169
54207
|
() => new Set(plugin.schema.orbitals.map((o) => o.name)),
|
|
54170
54208
|
[plugin.schema]
|
|
54171
54209
|
);
|
|
54210
|
+
const inboundBusEvents = useMemo(
|
|
54211
|
+
() => new Set(plugin.inbound.map((row) => row.busEvent)),
|
|
54212
|
+
[plugin.inbound]
|
|
54213
|
+
);
|
|
54214
|
+
const inboundTriggerNames = useMemo(
|
|
54215
|
+
() => new Set(plugin.inbound.map((row) => row.trigger)),
|
|
54216
|
+
[plugin.inbound]
|
|
54217
|
+
);
|
|
54218
|
+
const snapshotAllStates = useCallback(() => {
|
|
54219
|
+
const states = [];
|
|
54220
|
+
if (!mockRuntime) return states;
|
|
54221
|
+
for (const orbital of plugin.schema.orbitals) {
|
|
54222
|
+
for (const traitName of traitNamesOf(orbital)) {
|
|
54223
|
+
const raw = mockRuntime.getState(orbital.name, traitName);
|
|
54224
|
+
if (isTraitState(raw)) states.push([orbital.name, traitName, raw]);
|
|
54225
|
+
}
|
|
54226
|
+
}
|
|
54227
|
+
return states;
|
|
54228
|
+
}, [mockRuntime, plugin.schema]);
|
|
54172
54229
|
useEffect(() => {
|
|
54173
54230
|
let cancelled = false;
|
|
54174
54231
|
void registrationReady.then(() => {
|
|
54175
54232
|
if (cancelled || !mockRuntime) return;
|
|
54176
|
-
const states =
|
|
54177
|
-
for (const orbital of plugin.schema.orbitals) {
|
|
54178
|
-
for (const traitName of traitNamesOf(orbital)) {
|
|
54179
|
-
const raw = mockRuntime.getState(orbital.name, traitName);
|
|
54180
|
-
if (isTraitState(raw)) states.push([orbital.name, traitName, raw]);
|
|
54181
|
-
}
|
|
54182
|
-
}
|
|
54233
|
+
const states = snapshotAllStates();
|
|
54183
54234
|
if (states.length > 0) onDispatched(plugin.id, null, states);
|
|
54184
54235
|
}).catch((err) => {
|
|
54185
54236
|
if (!cancelled) onError(plugin.id, err instanceof Error ? err.message : String(err));
|
|
@@ -54187,7 +54238,39 @@ function PluginRuntimeMount({
|
|
|
54187
54238
|
return () => {
|
|
54188
54239
|
cancelled = true;
|
|
54189
54240
|
};
|
|
54190
|
-
}, [registrationReady, mockRuntime, plugin, onDispatched, onError]);
|
|
54241
|
+
}, [registrationReady, mockRuntime, plugin, onDispatched, onError, snapshotAllStates]);
|
|
54242
|
+
useEffect(() => {
|
|
54243
|
+
if (!mockRuntime) return;
|
|
54244
|
+
let timer = null;
|
|
54245
|
+
const scheduleResync = () => {
|
|
54246
|
+
if (timer !== null) return;
|
|
54247
|
+
timer = setTimeout(() => {
|
|
54248
|
+
timer = null;
|
|
54249
|
+
const states = snapshotAllStates();
|
|
54250
|
+
if (states.length > 0) onDispatched(plugin.id, null, states);
|
|
54251
|
+
}, 0);
|
|
54252
|
+
};
|
|
54253
|
+
const unsub = mockRuntime.getEventBus().onAny(scheduleResync);
|
|
54254
|
+
return () => {
|
|
54255
|
+
unsub();
|
|
54256
|
+
if (timer !== null) clearTimeout(timer);
|
|
54257
|
+
};
|
|
54258
|
+
}, [mockRuntime, plugin.id, onDispatched, snapshotAllStates]);
|
|
54259
|
+
useEffect(() => {
|
|
54260
|
+
if (!mockRuntime) return;
|
|
54261
|
+
const rebroadcast = /* @__PURE__ */ new WeakSet();
|
|
54262
|
+
const unsub = mockRuntime.getEventBus().onAny((event) => {
|
|
54263
|
+
if (rebroadcast.has(event)) return;
|
|
54264
|
+
if (inboundBusEvents.has(event.type) || inboundTriggerNames.has(event.type)) return;
|
|
54265
|
+
const sourceOrbital = event.source?.orbital;
|
|
54266
|
+
if (sourceOrbital === void 0 || !ownOrbitals.has(sourceOrbital)) return;
|
|
54267
|
+
rebroadcast.add(event);
|
|
54268
|
+
bus.emit(`UI:${event.type}`, event.payload, event.source);
|
|
54269
|
+
});
|
|
54270
|
+
return () => {
|
|
54271
|
+
unsub();
|
|
54272
|
+
};
|
|
54273
|
+
}, [mockRuntime, bus, ownOrbitals, inboundBusEvents, inboundTriggerNames]);
|
|
54191
54274
|
const dispatch = useCallback(
|
|
54192
54275
|
async (row, payload) => {
|
|
54193
54276
|
await registrationReady;
|
|
@@ -54206,11 +54289,14 @@ function PluginRuntimeMount({
|
|
|
54206
54289
|
if (!response.success) {
|
|
54207
54290
|
onError(plugin.id, response.error ?? `${plugin.id}: ${row.trigger} failed`);
|
|
54208
54291
|
}
|
|
54209
|
-
|
|
54210
|
-
|
|
54211
|
-
|
|
54212
|
-
|
|
54213
|
-
|
|
54292
|
+
if (!mockRuntime) {
|
|
54293
|
+
for (const entry of response.emittedEvents ?? []) {
|
|
54294
|
+
if (entry.event === row.trigger) continue;
|
|
54295
|
+
if (inboundBusEvents.has(entry.event)) continue;
|
|
54296
|
+
const sourceOrbital = entry.source?.orbital;
|
|
54297
|
+
if (sourceOrbital !== void 0 && ownOrbitals.has(sourceOrbital)) {
|
|
54298
|
+
bus.emit(`UI:${entry.event}`, entry.payload, entry.source);
|
|
54299
|
+
}
|
|
54214
54300
|
}
|
|
54215
54301
|
}
|
|
54216
54302
|
const states = [];
|
|
@@ -54220,7 +54306,7 @@ function PluginRuntimeMount({
|
|
|
54220
54306
|
}
|
|
54221
54307
|
onDispatched(plugin.id, row.trigger, states);
|
|
54222
54308
|
},
|
|
54223
|
-
[registrationReady, mockRuntime, mode, transport, plugin, bus, ownOrbitals, onError, onTransition, onDispatched]
|
|
54309
|
+
[registrationReady, mockRuntime, mode, transport, plugin, bus, ownOrbitals, inboundBusEvents, onError, onTransition, onDispatched]
|
|
54224
54310
|
);
|
|
54225
54311
|
useEffect(() => {
|
|
54226
54312
|
const unsubs = plugin.inbound.map(
|
|
@@ -54304,7 +54390,21 @@ function OrbitalPluginHost({
|
|
|
54304
54390
|
] });
|
|
54305
54391
|
}
|
|
54306
54392
|
|
|
54393
|
+
// types/slot-host.ts
|
|
54394
|
+
function assertUniqueSlotsPerHost(manifest) {
|
|
54395
|
+
const seenBySlot = /* @__PURE__ */ new Map();
|
|
54396
|
+
for (const [regionId, region] of Object.entries(manifest.regions)) {
|
|
54397
|
+
const existingRegionId = seenBySlot.get(region.slot);
|
|
54398
|
+
if (existingRegionId !== void 0) {
|
|
54399
|
+
throw new Error(
|
|
54400
|
+
`assertUniqueSlotsPerHost: regions "${existingRegionId}" and "${regionId}" both bind slot "${region.slot}" \u2014 a slot may be mounted by only one region per host.`
|
|
54401
|
+
);
|
|
54402
|
+
}
|
|
54403
|
+
seenBySlot.set(region.slot, regionId);
|
|
54404
|
+
}
|
|
54405
|
+
}
|
|
54406
|
+
|
|
54307
54407
|
// runtime/index.ts
|
|
54308
54408
|
init_perf();
|
|
54309
54409
|
|
|
54310
|
-
export { BrowserPlayground, OrbPreview, OrbitalPluginHost, clearSchemaCache, createClientEffectHandlers, profilerOnRender, useDeclaredCaptureTable, useOrbitalPluginHost, usePerfBuffer, useResolvedSchema, useTraitStateMachine };
|
|
54410
|
+
export { BrowserPlayground, OrbPreview, OrbitalPluginHost, assertUniqueSlotsPerHost, clearSchemaCache, createClientEffectHandlers, profilerOnRender, useDeclaredCaptureTable, useOrbitalPluginHost, usePerfBuffer, useResolvedSchema, useTraitStateMachine };
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { UISlot } from '@almadar/core';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Slot-host manifest types (Studio V4 §14, Part I1/I2).
|
|
5
|
+
*
|
|
6
|
+
* A "slot-host" is any shell that lays out named regions and mounts each
|
|
7
|
+
* one through `UISlotComponent` — e.g. a persona workspace declaring
|
|
8
|
+
* `sidebar`/`main`/`drawer`/... A manifest is the declarative region → slot
|
|
9
|
+
* binding for such a host: which compiler `UISlot` each region mounts, and
|
|
10
|
+
* whether the host's own stock content is replaced by slot content or the
|
|
11
|
+
* two are shown together (`UISlotComponent`'s `mode` prop). Substrate
|
|
12
|
+
* (lives in `@almadar/ui`, re-exported by `@almadar/sdk`) so any host — the
|
|
13
|
+
* studio's three persona shells or an embedding app — describes its
|
|
14
|
+
* regions the same way.
|
|
15
|
+
*
|
|
16
|
+
* @packageDocumentation
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* One host region's binding to a compiler slot. Mirrors `UISlotComponent`'s
|
|
21
|
+
* `mode` prop exactly — a manifest is just that prop's value, keyed by
|
|
22
|
+
* region, declared as data instead of scattered across JSX call sites.
|
|
23
|
+
*/
|
|
24
|
+
interface SlotHostRegion {
|
|
25
|
+
slot: UISlot;
|
|
26
|
+
mode: "replace" | "append";
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* A host's full region map, keyed by the host's own region ids (e.g. a
|
|
30
|
+
* persona shell's `activityBar`/`sidebar`/`main`/...). `RegionId` is left
|
|
31
|
+
* generic so each host supplies its own literal union.
|
|
32
|
+
*/
|
|
33
|
+
interface SlotHostManifest<RegionId extends string = string> {
|
|
34
|
+
regions: Record<RegionId, SlotHostRegion>;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Guards the invariant a slot-host manifest depends on: each `UISlot` may
|
|
38
|
+
* be mounted by at most one region. Two regions sharing a slot would mount
|
|
39
|
+
* `UISlotComponent` twice for the same slot — the second mount clears/reads
|
|
40
|
+
* the same context entry the first one owns, so one of the two regions
|
|
41
|
+
* silently loses its content (or, for a portal slot, double-portals it).
|
|
42
|
+
* Throws naming the two offending regions so the host can find the
|
|
43
|
+
* conflict without re-deriving it from the manifest.
|
|
44
|
+
*/
|
|
45
|
+
declare function assertUniqueSlotsPerHost<RegionId extends string>(manifest: SlotHostManifest<RegionId>): void;
|
|
46
|
+
|
|
47
|
+
export { type SlotHostManifest as S, type SlotHostRegion as a, assertUniqueSlotsPerHost as b };
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { UISlot } from '@almadar/core';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Slot-host manifest types (Studio V4 §14, Part I1/I2).
|
|
5
|
+
*
|
|
6
|
+
* A "slot-host" is any shell that lays out named regions and mounts each
|
|
7
|
+
* one through `UISlotComponent` — e.g. a persona workspace declaring
|
|
8
|
+
* `sidebar`/`main`/`drawer`/... A manifest is the declarative region → slot
|
|
9
|
+
* binding for such a host: which compiler `UISlot` each region mounts, and
|
|
10
|
+
* whether the host's own stock content is replaced by slot content or the
|
|
11
|
+
* two are shown together (`UISlotComponent`'s `mode` prop). Substrate
|
|
12
|
+
* (lives in `@almadar/ui`, re-exported by `@almadar/sdk`) so any host — the
|
|
13
|
+
* studio's three persona shells or an embedding app — describes its
|
|
14
|
+
* regions the same way.
|
|
15
|
+
*
|
|
16
|
+
* @packageDocumentation
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* One host region's binding to a compiler slot. Mirrors `UISlotComponent`'s
|
|
21
|
+
* `mode` prop exactly — a manifest is just that prop's value, keyed by
|
|
22
|
+
* region, declared as data instead of scattered across JSX call sites.
|
|
23
|
+
*/
|
|
24
|
+
interface SlotHostRegion {
|
|
25
|
+
slot: UISlot;
|
|
26
|
+
mode: "replace" | "append";
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* A host's full region map, keyed by the host's own region ids (e.g. a
|
|
30
|
+
* persona shell's `activityBar`/`sidebar`/`main`/...). `RegionId` is left
|
|
31
|
+
* generic so each host supplies its own literal union.
|
|
32
|
+
*/
|
|
33
|
+
interface SlotHostManifest<RegionId extends string = string> {
|
|
34
|
+
regions: Record<RegionId, SlotHostRegion>;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Guards the invariant a slot-host manifest depends on: each `UISlot` may
|
|
38
|
+
* be mounted by at most one region. Two regions sharing a slot would mount
|
|
39
|
+
* `UISlotComponent` twice for the same slot — the second mount clears/reads
|
|
40
|
+
* the same context entry the first one owns, so one of the two regions
|
|
41
|
+
* silently loses its content (or, for a portal slot, double-portals it).
|
|
42
|
+
* Throws naming the two offending regions so the host can find the
|
|
43
|
+
* conflict without re-deriving it from the manifest.
|
|
44
|
+
*/
|
|
45
|
+
declare function assertUniqueSlotsPerHost<RegionId extends string>(manifest: SlotHostManifest<RegionId>): void;
|
|
46
|
+
|
|
47
|
+
export { type SlotHostManifest as S, type SlotHostRegion as a, assertUniqueSlotsPerHost as b };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@almadar/ui",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.8.0",
|
|
4
4
|
"description": "React UI components, hooks, and providers for Almadar",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": [
|
|
@@ -118,11 +118,11 @@
|
|
|
118
118
|
"access": "public"
|
|
119
119
|
},
|
|
120
120
|
"dependencies": {
|
|
121
|
-
"@almadar/core": "^10.
|
|
121
|
+
"@almadar/core": "^10.84.0",
|
|
122
122
|
"@almadar/evaluator": "^2.44.0",
|
|
123
123
|
"@almadar/logger": "^1.12.0",
|
|
124
|
-
"@almadar/runtime": "^6.
|
|
125
|
-
"@almadar/std": "^16.
|
|
124
|
+
"@almadar/runtime": "^6.71.0",
|
|
125
|
+
"@almadar/std": "^16.205.0",
|
|
126
126
|
"@almadar/syntax": "^1.16.0",
|
|
127
127
|
"@dnd-kit/core": "^6.3.1",
|
|
128
128
|
"@dnd-kit/sortable": "^10.0.0",
|