@almadar/ui 6.6.0 → 6.7.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 +97 -22
- package/dist/runtime/index.d.cts +1 -0
- package/dist/runtime/index.d.ts +1 -0
- package/dist/runtime/index.js +97 -23
- 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.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,22 @@ function PluginRuntimeMount({
|
|
|
54169
54207
|
() => new Set(plugin.schema.orbitals.map((o) => o.name)),
|
|
54170
54208
|
[plugin.schema]
|
|
54171
54209
|
);
|
|
54210
|
+
const snapshotAllStates = useCallback(() => {
|
|
54211
|
+
const states = [];
|
|
54212
|
+
if (!mockRuntime) return states;
|
|
54213
|
+
for (const orbital of plugin.schema.orbitals) {
|
|
54214
|
+
for (const traitName of traitNamesOf(orbital)) {
|
|
54215
|
+
const raw = mockRuntime.getState(orbital.name, traitName);
|
|
54216
|
+
if (isTraitState(raw)) states.push([orbital.name, traitName, raw]);
|
|
54217
|
+
}
|
|
54218
|
+
}
|
|
54219
|
+
return states;
|
|
54220
|
+
}, [mockRuntime, plugin.schema]);
|
|
54172
54221
|
useEffect(() => {
|
|
54173
54222
|
let cancelled = false;
|
|
54174
54223
|
void registrationReady.then(() => {
|
|
54175
54224
|
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
|
-
}
|
|
54225
|
+
const states = snapshotAllStates();
|
|
54183
54226
|
if (states.length > 0) onDispatched(plugin.id, null, states);
|
|
54184
54227
|
}).catch((err) => {
|
|
54185
54228
|
if (!cancelled) onError(plugin.id, err instanceof Error ? err.message : String(err));
|
|
@@ -54187,7 +54230,24 @@ function PluginRuntimeMount({
|
|
|
54187
54230
|
return () => {
|
|
54188
54231
|
cancelled = true;
|
|
54189
54232
|
};
|
|
54190
|
-
}, [registrationReady, mockRuntime, plugin, onDispatched, onError]);
|
|
54233
|
+
}, [registrationReady, mockRuntime, plugin, onDispatched, onError, snapshotAllStates]);
|
|
54234
|
+
useEffect(() => {
|
|
54235
|
+
if (!mockRuntime) return;
|
|
54236
|
+
let timer = null;
|
|
54237
|
+
const scheduleResync = () => {
|
|
54238
|
+
if (timer !== null) return;
|
|
54239
|
+
timer = setTimeout(() => {
|
|
54240
|
+
timer = null;
|
|
54241
|
+
const states = snapshotAllStates();
|
|
54242
|
+
if (states.length > 0) onDispatched(plugin.id, null, states);
|
|
54243
|
+
}, 0);
|
|
54244
|
+
};
|
|
54245
|
+
const unsub = mockRuntime.getEventBus().onAny(scheduleResync);
|
|
54246
|
+
return () => {
|
|
54247
|
+
unsub();
|
|
54248
|
+
if (timer !== null) clearTimeout(timer);
|
|
54249
|
+
};
|
|
54250
|
+
}, [mockRuntime, plugin.id, onDispatched, snapshotAllStates]);
|
|
54191
54251
|
const dispatch = useCallback(
|
|
54192
54252
|
async (row, payload) => {
|
|
54193
54253
|
await registrationReady;
|
|
@@ -54304,7 +54364,21 @@ function OrbitalPluginHost({
|
|
|
54304
54364
|
] });
|
|
54305
54365
|
}
|
|
54306
54366
|
|
|
54367
|
+
// types/slot-host.ts
|
|
54368
|
+
function assertUniqueSlotsPerHost(manifest) {
|
|
54369
|
+
const seenBySlot = /* @__PURE__ */ new Map();
|
|
54370
|
+
for (const [regionId, region] of Object.entries(manifest.regions)) {
|
|
54371
|
+
const existingRegionId = seenBySlot.get(region.slot);
|
|
54372
|
+
if (existingRegionId !== void 0) {
|
|
54373
|
+
throw new Error(
|
|
54374
|
+
`assertUniqueSlotsPerHost: regions "${existingRegionId}" and "${regionId}" both bind slot "${region.slot}" \u2014 a slot may be mounted by only one region per host.`
|
|
54375
|
+
);
|
|
54376
|
+
}
|
|
54377
|
+
seenBySlot.set(region.slot, regionId);
|
|
54378
|
+
}
|
|
54379
|
+
}
|
|
54380
|
+
|
|
54307
54381
|
// runtime/index.ts
|
|
54308
54382
|
init_perf();
|
|
54309
54383
|
|
|
54310
|
-
export { BrowserPlayground, OrbPreview, OrbitalPluginHost, clearSchemaCache, createClientEffectHandlers, profilerOnRender, useDeclaredCaptureTable, useOrbitalPluginHost, usePerfBuffer, useResolvedSchema, useTraitStateMachine };
|
|
54384
|
+
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.7.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.204.0",
|
|
126
126
|
"@almadar/syntax": "^1.16.0",
|
|
127
127
|
"@dnd-kit/core": "^6.3.1",
|
|
128
128
|
"@dnd-kit/sortable": "^10.0.0",
|