@almadar/ui 4.0.1 → 4.1.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 +208 -132
- package/dist/avl/index.js +208 -132
- package/dist/components/index.cjs +204 -100
- package/dist/components/index.js +204 -100
- package/dist/context/index.cjs +204 -100
- package/dist/context/index.js +204 -100
- package/dist/hooks/index.cjs +204 -100
- package/dist/hooks/index.js +204 -100
- package/dist/hooks/useUISlots.d.ts +22 -5
- package/dist/runtime/index.cjs +29 -29
- package/dist/runtime/index.js +29 -29
- package/package.json +1 -1
package/dist/avl/index.cjs
CHANGED
|
@@ -4130,12 +4130,42 @@ var init_EntitySchemaContext = __esm({
|
|
|
4130
4130
|
function generateId() {
|
|
4131
4131
|
return `slot-content-${++idCounter}-${Date.now()}`;
|
|
4132
4132
|
}
|
|
4133
|
+
function aggregateSlot(sources) {
|
|
4134
|
+
if (!sources) return null;
|
|
4135
|
+
const entries = Object.entries(sources);
|
|
4136
|
+
if (entries.length === 0) return null;
|
|
4137
|
+
if (entries.length === 1) return entries[0][1];
|
|
4138
|
+
const children = entries.map(([, entry]) => ({
|
|
4139
|
+
type: entry.pattern,
|
|
4140
|
+
...entry.props
|
|
4141
|
+
}));
|
|
4142
|
+
const stackId = `slot-content-stack-${entries.map(([k]) => k).join("-")}`;
|
|
4143
|
+
return {
|
|
4144
|
+
id: stackId,
|
|
4145
|
+
pattern: "stack",
|
|
4146
|
+
props: {
|
|
4147
|
+
direction: "vertical",
|
|
4148
|
+
gap: "lg",
|
|
4149
|
+
children
|
|
4150
|
+
},
|
|
4151
|
+
priority: 0,
|
|
4152
|
+
animation: "fade",
|
|
4153
|
+
sourceTrait: MULTI_SOURCE_STACK_TRAIT
|
|
4154
|
+
};
|
|
4155
|
+
}
|
|
4133
4156
|
function useUISlotManager() {
|
|
4134
|
-
const [
|
|
4157
|
+
const [sources, setSources] = React126.useState(DEFAULT_SOURCES);
|
|
4135
4158
|
const subscribersRef = React126.useRef(/* @__PURE__ */ new Set());
|
|
4136
4159
|
const timersRef = React126.useRef(/* @__PURE__ */ new Map());
|
|
4137
4160
|
const traitIndexRef = React126.useRef(/* @__PURE__ */ new Map());
|
|
4138
4161
|
const traitSubscribersRef = React126.useRef(/* @__PURE__ */ new Map());
|
|
4162
|
+
const slots = React126.useMemo(() => {
|
|
4163
|
+
const out = { ...DEFAULT_SLOTS };
|
|
4164
|
+
for (const slot of ALL_SLOTS) {
|
|
4165
|
+
out[slot] = aggregateSlot(sources[slot]);
|
|
4166
|
+
}
|
|
4167
|
+
return out;
|
|
4168
|
+
}, [sources]);
|
|
4139
4169
|
React126.useEffect(() => {
|
|
4140
4170
|
return () => {
|
|
4141
4171
|
timersRef.current.forEach((timer) => clearTimeout(timer));
|
|
@@ -4174,103 +4204,160 @@ function useUISlotManager() {
|
|
|
4174
4204
|
const unindexTrait = React126.useCallback((traitName) => {
|
|
4175
4205
|
traitIndexRef.current.delete(traitName);
|
|
4176
4206
|
}, []);
|
|
4177
|
-
const render = React126.useCallback(
|
|
4178
|
-
|
|
4179
|
-
|
|
4180
|
-
|
|
4181
|
-
|
|
4182
|
-
|
|
4183
|
-
|
|
4184
|
-
|
|
4185
|
-
|
|
4186
|
-
|
|
4187
|
-
|
|
4188
|
-
|
|
4189
|
-
|
|
4190
|
-
|
|
4191
|
-
|
|
4192
|
-
|
|
4193
|
-
|
|
4194
|
-
|
|
4195
|
-
|
|
4196
|
-
|
|
4207
|
+
const render = React126.useCallback(
|
|
4208
|
+
(config) => {
|
|
4209
|
+
const id = generateId();
|
|
4210
|
+
const sourceKey = config.sourceTrait ?? DEFAULT_SOURCE_KEY;
|
|
4211
|
+
const content = {
|
|
4212
|
+
id,
|
|
4213
|
+
pattern: config.pattern,
|
|
4214
|
+
props: config.props ?? {},
|
|
4215
|
+
priority: config.priority ?? 0,
|
|
4216
|
+
animation: config.animation ?? "fade",
|
|
4217
|
+
onDismiss: config.onDismiss,
|
|
4218
|
+
sourceTrait: config.sourceTrait
|
|
4219
|
+
};
|
|
4220
|
+
if (config.autoDismissMs && config.autoDismissMs > 0) {
|
|
4221
|
+
content.autoDismissAt = Date.now() + config.autoDismissMs;
|
|
4222
|
+
const timer = setTimeout(() => {
|
|
4223
|
+
setSources((prev) => {
|
|
4224
|
+
const slotSources = prev[config.target];
|
|
4225
|
+
if (slotSources && slotSources[sourceKey]?.id === id) {
|
|
4226
|
+
content.onDismiss?.();
|
|
4227
|
+
const next = { ...slotSources };
|
|
4228
|
+
delete next[sourceKey];
|
|
4229
|
+
const updated = { ...prev, [config.target]: next };
|
|
4230
|
+
notifySubscribers(config.target, aggregateSlot(next));
|
|
4231
|
+
return updated;
|
|
4232
|
+
}
|
|
4233
|
+
return prev;
|
|
4234
|
+
});
|
|
4235
|
+
timersRef.current.delete(id);
|
|
4236
|
+
}, config.autoDismissMs);
|
|
4237
|
+
timersRef.current.set(id, timer);
|
|
4238
|
+
}
|
|
4239
|
+
setSources((prev) => {
|
|
4240
|
+
const slotSources = prev[config.target] ?? {};
|
|
4241
|
+
const existing = slotSources[sourceKey];
|
|
4242
|
+
if (existing && existing.priority > content.priority) {
|
|
4243
|
+
console.warn(
|
|
4244
|
+
`[UISlots] Slot "${config.target}" source "${sourceKey}" already has higher priority content (${existing.priority} > ${content.priority})`
|
|
4245
|
+
);
|
|
4197
4246
|
return prev;
|
|
4198
|
-
});
|
|
4199
|
-
timersRef.current.delete(id);
|
|
4200
|
-
}, config.autoDismissMs);
|
|
4201
|
-
timersRef.current.set(id, timer);
|
|
4202
|
-
}
|
|
4203
|
-
setSlots((prev) => {
|
|
4204
|
-
const existing = prev[config.target];
|
|
4205
|
-
if (existing && existing.priority > content.priority) {
|
|
4206
|
-
console.warn(
|
|
4207
|
-
`[UISlots] Slot "${config.target}" already has higher priority content (${existing.priority} > ${content.priority})`
|
|
4208
|
-
);
|
|
4209
|
-
return prev;
|
|
4210
|
-
}
|
|
4211
|
-
if (content.sourceTrait) {
|
|
4212
|
-
indexTraitRender(content.sourceTrait, content);
|
|
4213
|
-
notifyTraitSubscribers(content.sourceTrait, content);
|
|
4214
|
-
}
|
|
4215
|
-
notifySubscribers(config.target, content);
|
|
4216
|
-
return { ...prev, [config.target]: content };
|
|
4217
|
-
});
|
|
4218
|
-
return id;
|
|
4219
|
-
}, [notifySubscribers, notifyTraitSubscribers, indexTraitRender]);
|
|
4220
|
-
const clear = React126.useCallback((slot) => {
|
|
4221
|
-
setSlots((prev) => {
|
|
4222
|
-
const content = prev[slot];
|
|
4223
|
-
if (content) {
|
|
4224
|
-
const timer = timersRef.current.get(content.id);
|
|
4225
|
-
if (timer) {
|
|
4226
|
-
clearTimeout(timer);
|
|
4227
|
-
timersRef.current.delete(content.id);
|
|
4228
4247
|
}
|
|
4229
|
-
|
|
4248
|
+
const nextSources = {
|
|
4249
|
+
...slotSources,
|
|
4250
|
+
[sourceKey]: content
|
|
4251
|
+
};
|
|
4252
|
+
const nextAll = { ...prev, [config.target]: nextSources };
|
|
4230
4253
|
if (content.sourceTrait) {
|
|
4231
|
-
|
|
4232
|
-
notifyTraitSubscribers(content.sourceTrait,
|
|
4254
|
+
indexTraitRender(content.sourceTrait, content);
|
|
4255
|
+
notifyTraitSubscribers(content.sourceTrait, content);
|
|
4256
|
+
}
|
|
4257
|
+
notifySubscribers(config.target, aggregateSlot(nextSources));
|
|
4258
|
+
return nextAll;
|
|
4259
|
+
});
|
|
4260
|
+
return id;
|
|
4261
|
+
},
|
|
4262
|
+
[notifySubscribers, notifyTraitSubscribers, indexTraitRender]
|
|
4263
|
+
);
|
|
4264
|
+
const clear = React126.useCallback(
|
|
4265
|
+
(slot) => {
|
|
4266
|
+
setSources((prev) => {
|
|
4267
|
+
const slotSources = prev[slot];
|
|
4268
|
+
if (!slotSources || Object.keys(slotSources).length === 0) {
|
|
4269
|
+
return prev;
|
|
4270
|
+
}
|
|
4271
|
+
for (const content of Object.values(slotSources)) {
|
|
4272
|
+
const timer = timersRef.current.get(content.id);
|
|
4273
|
+
if (timer) {
|
|
4274
|
+
clearTimeout(timer);
|
|
4275
|
+
timersRef.current.delete(content.id);
|
|
4276
|
+
}
|
|
4277
|
+
content.onDismiss?.();
|
|
4278
|
+
if (content.sourceTrait) {
|
|
4279
|
+
unindexTrait(content.sourceTrait);
|
|
4280
|
+
notifyTraitSubscribers(content.sourceTrait, null);
|
|
4281
|
+
}
|
|
4233
4282
|
}
|
|
4234
4283
|
notifySubscribers(slot, null);
|
|
4235
|
-
|
|
4236
|
-
|
|
4237
|
-
}
|
|
4238
|
-
|
|
4239
|
-
|
|
4240
|
-
|
|
4241
|
-
|
|
4242
|
-
|
|
4243
|
-
|
|
4244
|
-
const
|
|
4284
|
+
return { ...prev, [slot]: {} };
|
|
4285
|
+
});
|
|
4286
|
+
},
|
|
4287
|
+
[notifySubscribers, notifyTraitSubscribers, unindexTrait]
|
|
4288
|
+
);
|
|
4289
|
+
const clearBySource = React126.useCallback(
|
|
4290
|
+
(slot, sourceTrait) => {
|
|
4291
|
+
const sourceKey = sourceTrait;
|
|
4292
|
+
setSources((prev) => {
|
|
4293
|
+
const slotSources = prev[slot];
|
|
4294
|
+
if (!slotSources || !(sourceKey in slotSources)) return prev;
|
|
4295
|
+
const content = slotSources[sourceKey];
|
|
4296
|
+
const timer = timersRef.current.get(content.id);
|
|
4245
4297
|
if (timer) {
|
|
4246
4298
|
clearTimeout(timer);
|
|
4247
|
-
timersRef.current.delete(id);
|
|
4299
|
+
timersRef.current.delete(content.id);
|
|
4248
4300
|
}
|
|
4249
4301
|
content.onDismiss?.();
|
|
4250
4302
|
if (content.sourceTrait) {
|
|
4251
4303
|
unindexTrait(content.sourceTrait);
|
|
4252
4304
|
notifyTraitSubscribers(content.sourceTrait, null);
|
|
4253
4305
|
}
|
|
4254
|
-
|
|
4255
|
-
|
|
4256
|
-
|
|
4257
|
-
|
|
4258
|
-
|
|
4259
|
-
|
|
4306
|
+
const nextSources = { ...slotSources };
|
|
4307
|
+
delete nextSources[sourceKey];
|
|
4308
|
+
notifySubscribers(slot, aggregateSlot(nextSources));
|
|
4309
|
+
return { ...prev, [slot]: nextSources };
|
|
4310
|
+
});
|
|
4311
|
+
},
|
|
4312
|
+
[notifySubscribers, notifyTraitSubscribers, unindexTrait]
|
|
4313
|
+
);
|
|
4314
|
+
const clearById = React126.useCallback(
|
|
4315
|
+
(id) => {
|
|
4316
|
+
setSources((prev) => {
|
|
4317
|
+
for (const slot of ALL_SLOTS) {
|
|
4318
|
+
const slotSources = prev[slot];
|
|
4319
|
+
if (!slotSources) continue;
|
|
4320
|
+
const matchKey = Object.keys(slotSources).find(
|
|
4321
|
+
(k) => slotSources[k].id === id
|
|
4322
|
+
);
|
|
4323
|
+
if (!matchKey) continue;
|
|
4324
|
+
const content = slotSources[matchKey];
|
|
4325
|
+
const timer = timersRef.current.get(id);
|
|
4326
|
+
if (timer) {
|
|
4327
|
+
clearTimeout(timer);
|
|
4328
|
+
timersRef.current.delete(id);
|
|
4329
|
+
}
|
|
4330
|
+
content.onDismiss?.();
|
|
4331
|
+
if (content.sourceTrait) {
|
|
4332
|
+
unindexTrait(content.sourceTrait);
|
|
4333
|
+
notifyTraitSubscribers(content.sourceTrait, null);
|
|
4334
|
+
}
|
|
4335
|
+
const nextSources = { ...slotSources };
|
|
4336
|
+
delete nextSources[matchKey];
|
|
4337
|
+
notifySubscribers(slot, aggregateSlot(nextSources));
|
|
4338
|
+
return { ...prev, [slot]: nextSources };
|
|
4339
|
+
}
|
|
4340
|
+
return prev;
|
|
4341
|
+
});
|
|
4342
|
+
},
|
|
4343
|
+
[notifySubscribers, notifyTraitSubscribers, unindexTrait]
|
|
4344
|
+
);
|
|
4260
4345
|
const clearAll = React126.useCallback(() => {
|
|
4261
4346
|
timersRef.current.forEach((timer) => clearTimeout(timer));
|
|
4262
4347
|
timersRef.current.clear();
|
|
4263
|
-
|
|
4264
|
-
|
|
4265
|
-
|
|
4348
|
+
setSources((prev) => {
|
|
4349
|
+
for (const slot of ALL_SLOTS) {
|
|
4350
|
+
const slotSources = prev[slot];
|
|
4351
|
+
if (!slotSources) continue;
|
|
4352
|
+
for (const content of Object.values(slotSources)) {
|
|
4266
4353
|
content.onDismiss?.();
|
|
4267
4354
|
if (content.sourceTrait) {
|
|
4268
4355
|
notifyTraitSubscribers(content.sourceTrait, null);
|
|
4269
4356
|
}
|
|
4270
|
-
notifySubscribers(slot, null);
|
|
4271
4357
|
}
|
|
4272
|
-
|
|
4273
|
-
|
|
4358
|
+
notifySubscribers(slot, null);
|
|
4359
|
+
}
|
|
4360
|
+
return DEFAULT_SOURCES;
|
|
4274
4361
|
});
|
|
4275
4362
|
traitIndexRef.current.clear();
|
|
4276
4363
|
}, [notifySubscribers, notifyTraitSubscribers]);
|
|
@@ -4280,16 +4367,16 @@ function useUISlotManager() {
|
|
|
4280
4367
|
subscribersRef.current.delete(callback);
|
|
4281
4368
|
};
|
|
4282
4369
|
}, []);
|
|
4283
|
-
const hasContent = React126.useCallback(
|
|
4284
|
-
|
|
4285
|
-
|
|
4286
|
-
|
|
4287
|
-
|
|
4288
|
-
|
|
4370
|
+
const hasContent = React126.useCallback(
|
|
4371
|
+
(slot) => slots[slot] !== null,
|
|
4372
|
+
[slots]
|
|
4373
|
+
);
|
|
4374
|
+
const getContent = React126.useCallback(
|
|
4375
|
+
(slot) => slots[slot],
|
|
4376
|
+
[slots]
|
|
4377
|
+
);
|
|
4289
4378
|
const getTraitContent = React126.useCallback(
|
|
4290
|
-
(traitName) =>
|
|
4291
|
-
return traitIndexRef.current.get(traitName) ?? null;
|
|
4292
|
-
},
|
|
4379
|
+
(traitName) => traitIndexRef.current.get(traitName) ?? null,
|
|
4293
4380
|
[]
|
|
4294
4381
|
);
|
|
4295
4382
|
const subscribeTrait = React126.useCallback(
|
|
@@ -4315,6 +4402,7 @@ function useUISlotManager() {
|
|
|
4315
4402
|
slots,
|
|
4316
4403
|
render,
|
|
4317
4404
|
clear,
|
|
4405
|
+
clearBySource,
|
|
4318
4406
|
clearById,
|
|
4319
4407
|
clearAll,
|
|
4320
4408
|
subscribe: subscribe2,
|
|
@@ -4324,24 +4412,40 @@ function useUISlotManager() {
|
|
|
4324
4412
|
subscribeTrait
|
|
4325
4413
|
};
|
|
4326
4414
|
}
|
|
4327
|
-
var DEFAULT_SLOTS, idCounter;
|
|
4415
|
+
var DEFAULT_SOURCE_KEY, MULTI_SOURCE_STACK_TRAIT, ALL_SLOTS, DEFAULT_SLOTS, DEFAULT_SOURCES, idCounter;
|
|
4328
4416
|
var init_useUISlots = __esm({
|
|
4329
4417
|
"hooks/useUISlots.ts"() {
|
|
4330
4418
|
"use client";
|
|
4331
|
-
|
|
4332
|
-
|
|
4333
|
-
|
|
4334
|
-
|
|
4335
|
-
|
|
4336
|
-
|
|
4337
|
-
|
|
4338
|
-
|
|
4339
|
-
"
|
|
4340
|
-
"
|
|
4341
|
-
"hud-
|
|
4342
|
-
"hud-
|
|
4343
|
-
|
|
4344
|
-
|
|
4419
|
+
DEFAULT_SOURCE_KEY = "__default__";
|
|
4420
|
+
MULTI_SOURCE_STACK_TRAIT = "__multi_source_stack__";
|
|
4421
|
+
ALL_SLOTS = [
|
|
4422
|
+
"main",
|
|
4423
|
+
"sidebar",
|
|
4424
|
+
"modal",
|
|
4425
|
+
"drawer",
|
|
4426
|
+
"overlay",
|
|
4427
|
+
"center",
|
|
4428
|
+
"toast",
|
|
4429
|
+
"hud-top",
|
|
4430
|
+
"hud-bottom",
|
|
4431
|
+
"hud-left",
|
|
4432
|
+
"hud-right",
|
|
4433
|
+
"floating"
|
|
4434
|
+
];
|
|
4435
|
+
DEFAULT_SLOTS = ALL_SLOTS.reduce(
|
|
4436
|
+
(acc, slot) => {
|
|
4437
|
+
acc[slot] = null;
|
|
4438
|
+
return acc;
|
|
4439
|
+
},
|
|
4440
|
+
{}
|
|
4441
|
+
);
|
|
4442
|
+
DEFAULT_SOURCES = ALL_SLOTS.reduce(
|
|
4443
|
+
(acc, slot) => {
|
|
4444
|
+
acc[slot] = {};
|
|
4445
|
+
return acc;
|
|
4446
|
+
},
|
|
4447
|
+
{}
|
|
4448
|
+
);
|
|
4345
4449
|
idCounter = 0;
|
|
4346
4450
|
}
|
|
4347
4451
|
});
|
|
@@ -51610,7 +51714,7 @@ function useTraitStateMachine(traitBindings, slotsActions, options) {
|
|
|
51610
51714
|
canHandleEvent
|
|
51611
51715
|
};
|
|
51612
51716
|
}
|
|
51613
|
-
var
|
|
51717
|
+
var DEFAULT_SOURCE_KEY2 = "__default__";
|
|
51614
51718
|
function slotEntriesInOrder(slot) {
|
|
51615
51719
|
if (!slot) return [];
|
|
51616
51720
|
const out = [];
|
|
@@ -51626,7 +51730,7 @@ var SlotsActionsContext = React126.createContext(null);
|
|
|
51626
51730
|
function SlotsProvider({ children }) {
|
|
51627
51731
|
const [slots, setSlots] = React126.useState({});
|
|
51628
51732
|
const setSlotPatterns = React126.useCallback((slot, patterns, source) => {
|
|
51629
|
-
const sourceKey = source?.trait ??
|
|
51733
|
+
const sourceKey = source?.trait ?? DEFAULT_SOURCE_KEY2;
|
|
51630
51734
|
setSlots((prev) => {
|
|
51631
51735
|
const prevSlot = prev[slot] ?? {};
|
|
51632
51736
|
return {
|
|
@@ -51952,13 +52056,11 @@ function SlotBridge() {
|
|
|
51952
52056
|
return null;
|
|
51953
52057
|
}
|
|
51954
52058
|
function applyServerEffects(effects, uiSlots, onNavigate) {
|
|
51955
|
-
const perSlotRenders = /* @__PURE__ */ new Map();
|
|
51956
52059
|
for (const eff of effects) {
|
|
51957
52060
|
if (eff.type === "render-ui" && eff.slot && eff.pattern) {
|
|
51958
52061
|
const patternRecord = eff.pattern;
|
|
51959
52062
|
const { type: patternType, children, ...inlineProps } = patternRecord;
|
|
51960
52063
|
const normalizedChildren = Array.isArray(children) ? children.map((c) => normalizeChild(c)) : children;
|
|
51961
|
-
const sourceTrait = eff.traitName ?? "server";
|
|
51962
52064
|
uiSlots.render({
|
|
51963
52065
|
target: eff.slot,
|
|
51964
52066
|
pattern: patternType,
|
|
@@ -51966,38 +52068,12 @@ function applyServerEffects(effects, uiSlots, onNavigate) {
|
|
|
51966
52068
|
...inlineProps,
|
|
51967
52069
|
...normalizedChildren !== void 0 ? { children: normalizedChildren } : {}
|
|
51968
52070
|
},
|
|
51969
|
-
sourceTrait
|
|
52071
|
+
sourceTrait: eff.traitName ?? "server"
|
|
51970
52072
|
});
|
|
51971
|
-
const bucket = perSlotRenders.get(eff.slot) ?? [];
|
|
51972
|
-
bucket.push({
|
|
51973
|
-
sourceTrait,
|
|
51974
|
-
pattern: {
|
|
51975
|
-
type: patternType,
|
|
51976
|
-
...inlineProps,
|
|
51977
|
-
...normalizedChildren !== void 0 ? { children: normalizedChildren } : {}
|
|
51978
|
-
}
|
|
51979
|
-
});
|
|
51980
|
-
perSlotRenders.set(eff.slot, bucket);
|
|
51981
52073
|
} else if (eff.type === "navigate" && eff.route && onNavigate) {
|
|
51982
52074
|
onNavigate(eff.route, eff.params);
|
|
51983
52075
|
}
|
|
51984
52076
|
}
|
|
51985
|
-
for (const [slot, bucket] of perSlotRenders) {
|
|
51986
|
-
const distinctSources = new Set(bucket.map((b) => b.sourceTrait));
|
|
51987
|
-
if (distinctSources.size <= 1) continue;
|
|
51988
|
-
uiSlots.render({
|
|
51989
|
-
target: slot,
|
|
51990
|
-
pattern: "stack",
|
|
51991
|
-
props: {
|
|
51992
|
-
direction: "vertical",
|
|
51993
|
-
gap: "lg",
|
|
51994
|
-
children: bucket.map((b) => b.pattern)
|
|
51995
|
-
},
|
|
51996
|
-
// Use a synthetic wrapper source trait; individual traits' frames
|
|
51997
|
-
// already live in the per-trait index from the per-effect loop.
|
|
51998
|
-
sourceTrait: "__multi_source_stack__"
|
|
51999
|
-
});
|
|
52000
|
-
}
|
|
52001
52077
|
}
|
|
52002
52078
|
function TraitInitializer({ traits: traits2, orbitalNames, onNavigate, onLocalFallback, persistence }) {
|
|
52003
52079
|
const slotsActions = useSlotsActions();
|