@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.js
CHANGED
|
@@ -4084,12 +4084,42 @@ var init_EntitySchemaContext = __esm({
|
|
|
4084
4084
|
function generateId() {
|
|
4085
4085
|
return `slot-content-${++idCounter}-${Date.now()}`;
|
|
4086
4086
|
}
|
|
4087
|
+
function aggregateSlot(sources) {
|
|
4088
|
+
if (!sources) return null;
|
|
4089
|
+
const entries = Object.entries(sources);
|
|
4090
|
+
if (entries.length === 0) return null;
|
|
4091
|
+
if (entries.length === 1) return entries[0][1];
|
|
4092
|
+
const children = entries.map(([, entry]) => ({
|
|
4093
|
+
type: entry.pattern,
|
|
4094
|
+
...entry.props
|
|
4095
|
+
}));
|
|
4096
|
+
const stackId = `slot-content-stack-${entries.map(([k]) => k).join("-")}`;
|
|
4097
|
+
return {
|
|
4098
|
+
id: stackId,
|
|
4099
|
+
pattern: "stack",
|
|
4100
|
+
props: {
|
|
4101
|
+
direction: "vertical",
|
|
4102
|
+
gap: "lg",
|
|
4103
|
+
children
|
|
4104
|
+
},
|
|
4105
|
+
priority: 0,
|
|
4106
|
+
animation: "fade",
|
|
4107
|
+
sourceTrait: MULTI_SOURCE_STACK_TRAIT
|
|
4108
|
+
};
|
|
4109
|
+
}
|
|
4087
4110
|
function useUISlotManager() {
|
|
4088
|
-
const [
|
|
4111
|
+
const [sources, setSources] = useState(DEFAULT_SOURCES);
|
|
4089
4112
|
const subscribersRef = useRef(/* @__PURE__ */ new Set());
|
|
4090
4113
|
const timersRef = useRef(/* @__PURE__ */ new Map());
|
|
4091
4114
|
const traitIndexRef = useRef(/* @__PURE__ */ new Map());
|
|
4092
4115
|
const traitSubscribersRef = useRef(/* @__PURE__ */ new Map());
|
|
4116
|
+
const slots = useMemo(() => {
|
|
4117
|
+
const out = { ...DEFAULT_SLOTS };
|
|
4118
|
+
for (const slot of ALL_SLOTS) {
|
|
4119
|
+
out[slot] = aggregateSlot(sources[slot]);
|
|
4120
|
+
}
|
|
4121
|
+
return out;
|
|
4122
|
+
}, [sources]);
|
|
4093
4123
|
useEffect(() => {
|
|
4094
4124
|
return () => {
|
|
4095
4125
|
timersRef.current.forEach((timer) => clearTimeout(timer));
|
|
@@ -4128,103 +4158,160 @@ function useUISlotManager() {
|
|
|
4128
4158
|
const unindexTrait = useCallback((traitName) => {
|
|
4129
4159
|
traitIndexRef.current.delete(traitName);
|
|
4130
4160
|
}, []);
|
|
4131
|
-
const render = useCallback(
|
|
4132
|
-
|
|
4133
|
-
|
|
4134
|
-
|
|
4135
|
-
|
|
4136
|
-
|
|
4137
|
-
|
|
4138
|
-
|
|
4139
|
-
|
|
4140
|
-
|
|
4141
|
-
|
|
4142
|
-
|
|
4143
|
-
|
|
4144
|
-
|
|
4145
|
-
|
|
4146
|
-
|
|
4147
|
-
|
|
4148
|
-
|
|
4149
|
-
|
|
4150
|
-
|
|
4161
|
+
const render = useCallback(
|
|
4162
|
+
(config) => {
|
|
4163
|
+
const id = generateId();
|
|
4164
|
+
const sourceKey = config.sourceTrait ?? DEFAULT_SOURCE_KEY;
|
|
4165
|
+
const content = {
|
|
4166
|
+
id,
|
|
4167
|
+
pattern: config.pattern,
|
|
4168
|
+
props: config.props ?? {},
|
|
4169
|
+
priority: config.priority ?? 0,
|
|
4170
|
+
animation: config.animation ?? "fade",
|
|
4171
|
+
onDismiss: config.onDismiss,
|
|
4172
|
+
sourceTrait: config.sourceTrait
|
|
4173
|
+
};
|
|
4174
|
+
if (config.autoDismissMs && config.autoDismissMs > 0) {
|
|
4175
|
+
content.autoDismissAt = Date.now() + config.autoDismissMs;
|
|
4176
|
+
const timer = setTimeout(() => {
|
|
4177
|
+
setSources((prev) => {
|
|
4178
|
+
const slotSources = prev[config.target];
|
|
4179
|
+
if (slotSources && slotSources[sourceKey]?.id === id) {
|
|
4180
|
+
content.onDismiss?.();
|
|
4181
|
+
const next = { ...slotSources };
|
|
4182
|
+
delete next[sourceKey];
|
|
4183
|
+
const updated = { ...prev, [config.target]: next };
|
|
4184
|
+
notifySubscribers(config.target, aggregateSlot(next));
|
|
4185
|
+
return updated;
|
|
4186
|
+
}
|
|
4187
|
+
return prev;
|
|
4188
|
+
});
|
|
4189
|
+
timersRef.current.delete(id);
|
|
4190
|
+
}, config.autoDismissMs);
|
|
4191
|
+
timersRef.current.set(id, timer);
|
|
4192
|
+
}
|
|
4193
|
+
setSources((prev) => {
|
|
4194
|
+
const slotSources = prev[config.target] ?? {};
|
|
4195
|
+
const existing = slotSources[sourceKey];
|
|
4196
|
+
if (existing && existing.priority > content.priority) {
|
|
4197
|
+
console.warn(
|
|
4198
|
+
`[UISlots] Slot "${config.target}" source "${sourceKey}" already has higher priority content (${existing.priority} > ${content.priority})`
|
|
4199
|
+
);
|
|
4151
4200
|
return prev;
|
|
4152
|
-
});
|
|
4153
|
-
timersRef.current.delete(id);
|
|
4154
|
-
}, config.autoDismissMs);
|
|
4155
|
-
timersRef.current.set(id, timer);
|
|
4156
|
-
}
|
|
4157
|
-
setSlots((prev) => {
|
|
4158
|
-
const existing = prev[config.target];
|
|
4159
|
-
if (existing && existing.priority > content.priority) {
|
|
4160
|
-
console.warn(
|
|
4161
|
-
`[UISlots] Slot "${config.target}" already has higher priority content (${existing.priority} > ${content.priority})`
|
|
4162
|
-
);
|
|
4163
|
-
return prev;
|
|
4164
|
-
}
|
|
4165
|
-
if (content.sourceTrait) {
|
|
4166
|
-
indexTraitRender(content.sourceTrait, content);
|
|
4167
|
-
notifyTraitSubscribers(content.sourceTrait, content);
|
|
4168
|
-
}
|
|
4169
|
-
notifySubscribers(config.target, content);
|
|
4170
|
-
return { ...prev, [config.target]: content };
|
|
4171
|
-
});
|
|
4172
|
-
return id;
|
|
4173
|
-
}, [notifySubscribers, notifyTraitSubscribers, indexTraitRender]);
|
|
4174
|
-
const clear = useCallback((slot) => {
|
|
4175
|
-
setSlots((prev) => {
|
|
4176
|
-
const content = prev[slot];
|
|
4177
|
-
if (content) {
|
|
4178
|
-
const timer = timersRef.current.get(content.id);
|
|
4179
|
-
if (timer) {
|
|
4180
|
-
clearTimeout(timer);
|
|
4181
|
-
timersRef.current.delete(content.id);
|
|
4182
4201
|
}
|
|
4183
|
-
|
|
4202
|
+
const nextSources = {
|
|
4203
|
+
...slotSources,
|
|
4204
|
+
[sourceKey]: content
|
|
4205
|
+
};
|
|
4206
|
+
const nextAll = { ...prev, [config.target]: nextSources };
|
|
4184
4207
|
if (content.sourceTrait) {
|
|
4185
|
-
|
|
4186
|
-
notifyTraitSubscribers(content.sourceTrait,
|
|
4208
|
+
indexTraitRender(content.sourceTrait, content);
|
|
4209
|
+
notifyTraitSubscribers(content.sourceTrait, content);
|
|
4210
|
+
}
|
|
4211
|
+
notifySubscribers(config.target, aggregateSlot(nextSources));
|
|
4212
|
+
return nextAll;
|
|
4213
|
+
});
|
|
4214
|
+
return id;
|
|
4215
|
+
},
|
|
4216
|
+
[notifySubscribers, notifyTraitSubscribers, indexTraitRender]
|
|
4217
|
+
);
|
|
4218
|
+
const clear = useCallback(
|
|
4219
|
+
(slot) => {
|
|
4220
|
+
setSources((prev) => {
|
|
4221
|
+
const slotSources = prev[slot];
|
|
4222
|
+
if (!slotSources || Object.keys(slotSources).length === 0) {
|
|
4223
|
+
return prev;
|
|
4224
|
+
}
|
|
4225
|
+
for (const content of Object.values(slotSources)) {
|
|
4226
|
+
const timer = timersRef.current.get(content.id);
|
|
4227
|
+
if (timer) {
|
|
4228
|
+
clearTimeout(timer);
|
|
4229
|
+
timersRef.current.delete(content.id);
|
|
4230
|
+
}
|
|
4231
|
+
content.onDismiss?.();
|
|
4232
|
+
if (content.sourceTrait) {
|
|
4233
|
+
unindexTrait(content.sourceTrait);
|
|
4234
|
+
notifyTraitSubscribers(content.sourceTrait, null);
|
|
4235
|
+
}
|
|
4187
4236
|
}
|
|
4188
4237
|
notifySubscribers(slot, null);
|
|
4189
|
-
|
|
4190
|
-
|
|
4191
|
-
}
|
|
4192
|
-
|
|
4193
|
-
|
|
4194
|
-
|
|
4195
|
-
|
|
4196
|
-
|
|
4197
|
-
|
|
4198
|
-
const
|
|
4238
|
+
return { ...prev, [slot]: {} };
|
|
4239
|
+
});
|
|
4240
|
+
},
|
|
4241
|
+
[notifySubscribers, notifyTraitSubscribers, unindexTrait]
|
|
4242
|
+
);
|
|
4243
|
+
const clearBySource = useCallback(
|
|
4244
|
+
(slot, sourceTrait) => {
|
|
4245
|
+
const sourceKey = sourceTrait;
|
|
4246
|
+
setSources((prev) => {
|
|
4247
|
+
const slotSources = prev[slot];
|
|
4248
|
+
if (!slotSources || !(sourceKey in slotSources)) return prev;
|
|
4249
|
+
const content = slotSources[sourceKey];
|
|
4250
|
+
const timer = timersRef.current.get(content.id);
|
|
4199
4251
|
if (timer) {
|
|
4200
4252
|
clearTimeout(timer);
|
|
4201
|
-
timersRef.current.delete(id);
|
|
4253
|
+
timersRef.current.delete(content.id);
|
|
4202
4254
|
}
|
|
4203
4255
|
content.onDismiss?.();
|
|
4204
4256
|
if (content.sourceTrait) {
|
|
4205
4257
|
unindexTrait(content.sourceTrait);
|
|
4206
4258
|
notifyTraitSubscribers(content.sourceTrait, null);
|
|
4207
4259
|
}
|
|
4208
|
-
|
|
4209
|
-
|
|
4210
|
-
|
|
4211
|
-
|
|
4212
|
-
|
|
4213
|
-
|
|
4260
|
+
const nextSources = { ...slotSources };
|
|
4261
|
+
delete nextSources[sourceKey];
|
|
4262
|
+
notifySubscribers(slot, aggregateSlot(nextSources));
|
|
4263
|
+
return { ...prev, [slot]: nextSources };
|
|
4264
|
+
});
|
|
4265
|
+
},
|
|
4266
|
+
[notifySubscribers, notifyTraitSubscribers, unindexTrait]
|
|
4267
|
+
);
|
|
4268
|
+
const clearById = useCallback(
|
|
4269
|
+
(id) => {
|
|
4270
|
+
setSources((prev) => {
|
|
4271
|
+
for (const slot of ALL_SLOTS) {
|
|
4272
|
+
const slotSources = prev[slot];
|
|
4273
|
+
if (!slotSources) continue;
|
|
4274
|
+
const matchKey = Object.keys(slotSources).find(
|
|
4275
|
+
(k) => slotSources[k].id === id
|
|
4276
|
+
);
|
|
4277
|
+
if (!matchKey) continue;
|
|
4278
|
+
const content = slotSources[matchKey];
|
|
4279
|
+
const timer = timersRef.current.get(id);
|
|
4280
|
+
if (timer) {
|
|
4281
|
+
clearTimeout(timer);
|
|
4282
|
+
timersRef.current.delete(id);
|
|
4283
|
+
}
|
|
4284
|
+
content.onDismiss?.();
|
|
4285
|
+
if (content.sourceTrait) {
|
|
4286
|
+
unindexTrait(content.sourceTrait);
|
|
4287
|
+
notifyTraitSubscribers(content.sourceTrait, null);
|
|
4288
|
+
}
|
|
4289
|
+
const nextSources = { ...slotSources };
|
|
4290
|
+
delete nextSources[matchKey];
|
|
4291
|
+
notifySubscribers(slot, aggregateSlot(nextSources));
|
|
4292
|
+
return { ...prev, [slot]: nextSources };
|
|
4293
|
+
}
|
|
4294
|
+
return prev;
|
|
4295
|
+
});
|
|
4296
|
+
},
|
|
4297
|
+
[notifySubscribers, notifyTraitSubscribers, unindexTrait]
|
|
4298
|
+
);
|
|
4214
4299
|
const clearAll = useCallback(() => {
|
|
4215
4300
|
timersRef.current.forEach((timer) => clearTimeout(timer));
|
|
4216
4301
|
timersRef.current.clear();
|
|
4217
|
-
|
|
4218
|
-
|
|
4219
|
-
|
|
4302
|
+
setSources((prev) => {
|
|
4303
|
+
for (const slot of ALL_SLOTS) {
|
|
4304
|
+
const slotSources = prev[slot];
|
|
4305
|
+
if (!slotSources) continue;
|
|
4306
|
+
for (const content of Object.values(slotSources)) {
|
|
4220
4307
|
content.onDismiss?.();
|
|
4221
4308
|
if (content.sourceTrait) {
|
|
4222
4309
|
notifyTraitSubscribers(content.sourceTrait, null);
|
|
4223
4310
|
}
|
|
4224
|
-
notifySubscribers(slot, null);
|
|
4225
4311
|
}
|
|
4226
|
-
|
|
4227
|
-
|
|
4312
|
+
notifySubscribers(slot, null);
|
|
4313
|
+
}
|
|
4314
|
+
return DEFAULT_SOURCES;
|
|
4228
4315
|
});
|
|
4229
4316
|
traitIndexRef.current.clear();
|
|
4230
4317
|
}, [notifySubscribers, notifyTraitSubscribers]);
|
|
@@ -4234,16 +4321,16 @@ function useUISlotManager() {
|
|
|
4234
4321
|
subscribersRef.current.delete(callback);
|
|
4235
4322
|
};
|
|
4236
4323
|
}, []);
|
|
4237
|
-
const hasContent = useCallback(
|
|
4238
|
-
|
|
4239
|
-
|
|
4240
|
-
|
|
4241
|
-
|
|
4242
|
-
|
|
4324
|
+
const hasContent = useCallback(
|
|
4325
|
+
(slot) => slots[slot] !== null,
|
|
4326
|
+
[slots]
|
|
4327
|
+
);
|
|
4328
|
+
const getContent = useCallback(
|
|
4329
|
+
(slot) => slots[slot],
|
|
4330
|
+
[slots]
|
|
4331
|
+
);
|
|
4243
4332
|
const getTraitContent = useCallback(
|
|
4244
|
-
(traitName) =>
|
|
4245
|
-
return traitIndexRef.current.get(traitName) ?? null;
|
|
4246
|
-
},
|
|
4333
|
+
(traitName) => traitIndexRef.current.get(traitName) ?? null,
|
|
4247
4334
|
[]
|
|
4248
4335
|
);
|
|
4249
4336
|
const subscribeTrait = useCallback(
|
|
@@ -4269,6 +4356,7 @@ function useUISlotManager() {
|
|
|
4269
4356
|
slots,
|
|
4270
4357
|
render,
|
|
4271
4358
|
clear,
|
|
4359
|
+
clearBySource,
|
|
4272
4360
|
clearById,
|
|
4273
4361
|
clearAll,
|
|
4274
4362
|
subscribe: subscribe2,
|
|
@@ -4278,24 +4366,40 @@ function useUISlotManager() {
|
|
|
4278
4366
|
subscribeTrait
|
|
4279
4367
|
};
|
|
4280
4368
|
}
|
|
4281
|
-
var DEFAULT_SLOTS, idCounter;
|
|
4369
|
+
var DEFAULT_SOURCE_KEY, MULTI_SOURCE_STACK_TRAIT, ALL_SLOTS, DEFAULT_SLOTS, DEFAULT_SOURCES, idCounter;
|
|
4282
4370
|
var init_useUISlots = __esm({
|
|
4283
4371
|
"hooks/useUISlots.ts"() {
|
|
4284
4372
|
"use client";
|
|
4285
|
-
|
|
4286
|
-
|
|
4287
|
-
|
|
4288
|
-
|
|
4289
|
-
|
|
4290
|
-
|
|
4291
|
-
|
|
4292
|
-
|
|
4293
|
-
"
|
|
4294
|
-
"
|
|
4295
|
-
"hud-
|
|
4296
|
-
"hud-
|
|
4297
|
-
|
|
4298
|
-
|
|
4373
|
+
DEFAULT_SOURCE_KEY = "__default__";
|
|
4374
|
+
MULTI_SOURCE_STACK_TRAIT = "__multi_source_stack__";
|
|
4375
|
+
ALL_SLOTS = [
|
|
4376
|
+
"main",
|
|
4377
|
+
"sidebar",
|
|
4378
|
+
"modal",
|
|
4379
|
+
"drawer",
|
|
4380
|
+
"overlay",
|
|
4381
|
+
"center",
|
|
4382
|
+
"toast",
|
|
4383
|
+
"hud-top",
|
|
4384
|
+
"hud-bottom",
|
|
4385
|
+
"hud-left",
|
|
4386
|
+
"hud-right",
|
|
4387
|
+
"floating"
|
|
4388
|
+
];
|
|
4389
|
+
DEFAULT_SLOTS = ALL_SLOTS.reduce(
|
|
4390
|
+
(acc, slot) => {
|
|
4391
|
+
acc[slot] = null;
|
|
4392
|
+
return acc;
|
|
4393
|
+
},
|
|
4394
|
+
{}
|
|
4395
|
+
);
|
|
4396
|
+
DEFAULT_SOURCES = ALL_SLOTS.reduce(
|
|
4397
|
+
(acc, slot) => {
|
|
4398
|
+
acc[slot] = {};
|
|
4399
|
+
return acc;
|
|
4400
|
+
},
|
|
4401
|
+
{}
|
|
4402
|
+
);
|
|
4299
4403
|
idCounter = 0;
|
|
4300
4404
|
}
|
|
4301
4405
|
});
|
|
@@ -51564,7 +51668,7 @@ function useTraitStateMachine(traitBindings, slotsActions, options) {
|
|
|
51564
51668
|
canHandleEvent
|
|
51565
51669
|
};
|
|
51566
51670
|
}
|
|
51567
|
-
var
|
|
51671
|
+
var DEFAULT_SOURCE_KEY2 = "__default__";
|
|
51568
51672
|
function slotEntriesInOrder(slot) {
|
|
51569
51673
|
if (!slot) return [];
|
|
51570
51674
|
const out = [];
|
|
@@ -51580,7 +51684,7 @@ var SlotsActionsContext = createContext(null);
|
|
|
51580
51684
|
function SlotsProvider({ children }) {
|
|
51581
51685
|
const [slots, setSlots] = useState({});
|
|
51582
51686
|
const setSlotPatterns = useCallback((slot, patterns, source) => {
|
|
51583
|
-
const sourceKey = source?.trait ??
|
|
51687
|
+
const sourceKey = source?.trait ?? DEFAULT_SOURCE_KEY2;
|
|
51584
51688
|
setSlots((prev) => {
|
|
51585
51689
|
const prevSlot = prev[slot] ?? {};
|
|
51586
51690
|
return {
|
|
@@ -51906,13 +52010,11 @@ function SlotBridge() {
|
|
|
51906
52010
|
return null;
|
|
51907
52011
|
}
|
|
51908
52012
|
function applyServerEffects(effects, uiSlots, onNavigate) {
|
|
51909
|
-
const perSlotRenders = /* @__PURE__ */ new Map();
|
|
51910
52013
|
for (const eff of effects) {
|
|
51911
52014
|
if (eff.type === "render-ui" && eff.slot && eff.pattern) {
|
|
51912
52015
|
const patternRecord = eff.pattern;
|
|
51913
52016
|
const { type: patternType, children, ...inlineProps } = patternRecord;
|
|
51914
52017
|
const normalizedChildren = Array.isArray(children) ? children.map((c) => normalizeChild(c)) : children;
|
|
51915
|
-
const sourceTrait = eff.traitName ?? "server";
|
|
51916
52018
|
uiSlots.render({
|
|
51917
52019
|
target: eff.slot,
|
|
51918
52020
|
pattern: patternType,
|
|
@@ -51920,38 +52022,12 @@ function applyServerEffects(effects, uiSlots, onNavigate) {
|
|
|
51920
52022
|
...inlineProps,
|
|
51921
52023
|
...normalizedChildren !== void 0 ? { children: normalizedChildren } : {}
|
|
51922
52024
|
},
|
|
51923
|
-
sourceTrait
|
|
52025
|
+
sourceTrait: eff.traitName ?? "server"
|
|
51924
52026
|
});
|
|
51925
|
-
const bucket = perSlotRenders.get(eff.slot) ?? [];
|
|
51926
|
-
bucket.push({
|
|
51927
|
-
sourceTrait,
|
|
51928
|
-
pattern: {
|
|
51929
|
-
type: patternType,
|
|
51930
|
-
...inlineProps,
|
|
51931
|
-
...normalizedChildren !== void 0 ? { children: normalizedChildren } : {}
|
|
51932
|
-
}
|
|
51933
|
-
});
|
|
51934
|
-
perSlotRenders.set(eff.slot, bucket);
|
|
51935
52027
|
} else if (eff.type === "navigate" && eff.route && onNavigate) {
|
|
51936
52028
|
onNavigate(eff.route, eff.params);
|
|
51937
52029
|
}
|
|
51938
52030
|
}
|
|
51939
|
-
for (const [slot, bucket] of perSlotRenders) {
|
|
51940
|
-
const distinctSources = new Set(bucket.map((b) => b.sourceTrait));
|
|
51941
|
-
if (distinctSources.size <= 1) continue;
|
|
51942
|
-
uiSlots.render({
|
|
51943
|
-
target: slot,
|
|
51944
|
-
pattern: "stack",
|
|
51945
|
-
props: {
|
|
51946
|
-
direction: "vertical",
|
|
51947
|
-
gap: "lg",
|
|
51948
|
-
children: bucket.map((b) => b.pattern)
|
|
51949
|
-
},
|
|
51950
|
-
// Use a synthetic wrapper source trait; individual traits' frames
|
|
51951
|
-
// already live in the per-trait index from the per-effect loop.
|
|
51952
|
-
sourceTrait: "__multi_source_stack__"
|
|
51953
|
-
});
|
|
51954
|
-
}
|
|
51955
52031
|
}
|
|
51956
52032
|
function TraitInitializer({ traits: traits2, orbitalNames, onNavigate, onLocalFallback, persistence }) {
|
|
51957
52033
|
const slotsActions = useSlotsActions();
|