@almadar/ui 4.0.1 → 4.2.1
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 +231 -134
- package/dist/avl/index.js +231 -134
- package/dist/components/index.cjs +227 -102
- package/dist/components/index.js +227 -102
- package/dist/components/molecules/DataGrid.d.ts +10 -0
- 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/providers/index.cjs +23 -2
- package/dist/providers/index.js +23 -2
- package/dist/runtime/index.cjs +52 -31
- package/dist/runtime/index.js +52 -31
- package/package.json +1 -1
package/dist/context/index.cjs
CHANGED
|
@@ -3,30 +3,76 @@
|
|
|
3
3
|
var react = require('react');
|
|
4
4
|
var jsxRuntime = require('react/jsx-runtime');
|
|
5
5
|
|
|
6
|
-
var
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
"
|
|
15
|
-
"
|
|
16
|
-
"hud-
|
|
17
|
-
"hud-
|
|
18
|
-
|
|
19
|
-
|
|
6
|
+
var DEFAULT_SOURCE_KEY = "__default__";
|
|
7
|
+
var MULTI_SOURCE_STACK_TRAIT = "__multi_source_stack__";
|
|
8
|
+
var ALL_SLOTS = [
|
|
9
|
+
"main",
|
|
10
|
+
"sidebar",
|
|
11
|
+
"modal",
|
|
12
|
+
"drawer",
|
|
13
|
+
"overlay",
|
|
14
|
+
"center",
|
|
15
|
+
"toast",
|
|
16
|
+
"hud-top",
|
|
17
|
+
"hud-bottom",
|
|
18
|
+
"hud-left",
|
|
19
|
+
"hud-right",
|
|
20
|
+
"floating"
|
|
21
|
+
];
|
|
22
|
+
var DEFAULT_SLOTS = ALL_SLOTS.reduce(
|
|
23
|
+
(acc, slot) => {
|
|
24
|
+
acc[slot] = null;
|
|
25
|
+
return acc;
|
|
26
|
+
},
|
|
27
|
+
{}
|
|
28
|
+
);
|
|
29
|
+
var DEFAULT_SOURCES = ALL_SLOTS.reduce(
|
|
30
|
+
(acc, slot) => {
|
|
31
|
+
acc[slot] = {};
|
|
32
|
+
return acc;
|
|
33
|
+
},
|
|
34
|
+
{}
|
|
35
|
+
);
|
|
20
36
|
var idCounter = 0;
|
|
21
37
|
function generateId() {
|
|
22
38
|
return `slot-content-${++idCounter}-${Date.now()}`;
|
|
23
39
|
}
|
|
40
|
+
function aggregateSlot(sources) {
|
|
41
|
+
if (!sources) return null;
|
|
42
|
+
const entries = Object.entries(sources);
|
|
43
|
+
if (entries.length === 0) return null;
|
|
44
|
+
if (entries.length === 1) return entries[0][1];
|
|
45
|
+
const children = entries.map(([, entry]) => ({
|
|
46
|
+
type: entry.pattern,
|
|
47
|
+
...entry.props
|
|
48
|
+
}));
|
|
49
|
+
const stackId = `slot-content-stack-${entries.map(([k]) => k).join("-")}`;
|
|
50
|
+
return {
|
|
51
|
+
id: stackId,
|
|
52
|
+
pattern: "stack",
|
|
53
|
+
props: {
|
|
54
|
+
direction: "vertical",
|
|
55
|
+
gap: "lg",
|
|
56
|
+
children
|
|
57
|
+
},
|
|
58
|
+
priority: 0,
|
|
59
|
+
animation: "fade",
|
|
60
|
+
sourceTrait: MULTI_SOURCE_STACK_TRAIT
|
|
61
|
+
};
|
|
62
|
+
}
|
|
24
63
|
function useUISlotManager() {
|
|
25
|
-
const [
|
|
64
|
+
const [sources, setSources] = react.useState(DEFAULT_SOURCES);
|
|
26
65
|
const subscribersRef = react.useRef(/* @__PURE__ */ new Set());
|
|
27
66
|
const timersRef = react.useRef(/* @__PURE__ */ new Map());
|
|
28
67
|
const traitIndexRef = react.useRef(/* @__PURE__ */ new Map());
|
|
29
68
|
const traitSubscribersRef = react.useRef(/* @__PURE__ */ new Map());
|
|
69
|
+
const slots = react.useMemo(() => {
|
|
70
|
+
const out = { ...DEFAULT_SLOTS };
|
|
71
|
+
for (const slot of ALL_SLOTS) {
|
|
72
|
+
out[slot] = aggregateSlot(sources[slot]);
|
|
73
|
+
}
|
|
74
|
+
return out;
|
|
75
|
+
}, [sources]);
|
|
30
76
|
react.useEffect(() => {
|
|
31
77
|
return () => {
|
|
32
78
|
timersRef.current.forEach((timer) => clearTimeout(timer));
|
|
@@ -65,103 +111,160 @@ function useUISlotManager() {
|
|
|
65
111
|
const unindexTrait = react.useCallback((traitName) => {
|
|
66
112
|
traitIndexRef.current.delete(traitName);
|
|
67
113
|
}, []);
|
|
68
|
-
const render = react.useCallback(
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
);
|
|
100
|
-
return prev;
|
|
101
|
-
}
|
|
102
|
-
if (content.sourceTrait) {
|
|
103
|
-
indexTraitRender(content.sourceTrait, content);
|
|
104
|
-
notifyTraitSubscribers(content.sourceTrait, content);
|
|
114
|
+
const render = react.useCallback(
|
|
115
|
+
(config) => {
|
|
116
|
+
const id = generateId();
|
|
117
|
+
const sourceKey = config.sourceTrait ?? DEFAULT_SOURCE_KEY;
|
|
118
|
+
const content = {
|
|
119
|
+
id,
|
|
120
|
+
pattern: config.pattern,
|
|
121
|
+
props: config.props ?? {},
|
|
122
|
+
priority: config.priority ?? 0,
|
|
123
|
+
animation: config.animation ?? "fade",
|
|
124
|
+
onDismiss: config.onDismiss,
|
|
125
|
+
sourceTrait: config.sourceTrait
|
|
126
|
+
};
|
|
127
|
+
if (config.autoDismissMs && config.autoDismissMs > 0) {
|
|
128
|
+
content.autoDismissAt = Date.now() + config.autoDismissMs;
|
|
129
|
+
const timer = setTimeout(() => {
|
|
130
|
+
setSources((prev) => {
|
|
131
|
+
const slotSources = prev[config.target];
|
|
132
|
+
if (slotSources && slotSources[sourceKey]?.id === id) {
|
|
133
|
+
content.onDismiss?.();
|
|
134
|
+
const next = { ...slotSources };
|
|
135
|
+
delete next[sourceKey];
|
|
136
|
+
const updated = { ...prev, [config.target]: next };
|
|
137
|
+
notifySubscribers(config.target, aggregateSlot(next));
|
|
138
|
+
return updated;
|
|
139
|
+
}
|
|
140
|
+
return prev;
|
|
141
|
+
});
|
|
142
|
+
timersRef.current.delete(id);
|
|
143
|
+
}, config.autoDismissMs);
|
|
144
|
+
timersRef.current.set(id, timer);
|
|
105
145
|
}
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
if (content) {
|
|
115
|
-
const timer = timersRef.current.get(content.id);
|
|
116
|
-
if (timer) {
|
|
117
|
-
clearTimeout(timer);
|
|
118
|
-
timersRef.current.delete(content.id);
|
|
146
|
+
setSources((prev) => {
|
|
147
|
+
const slotSources = prev[config.target] ?? {};
|
|
148
|
+
const existing = slotSources[sourceKey];
|
|
149
|
+
if (existing && existing.priority > content.priority) {
|
|
150
|
+
console.warn(
|
|
151
|
+
`[UISlots] Slot "${config.target}" source "${sourceKey}" already has higher priority content (${existing.priority} > ${content.priority})`
|
|
152
|
+
);
|
|
153
|
+
return prev;
|
|
119
154
|
}
|
|
120
|
-
|
|
155
|
+
const nextSources = {
|
|
156
|
+
...slotSources,
|
|
157
|
+
[sourceKey]: content
|
|
158
|
+
};
|
|
159
|
+
const nextAll = { ...prev, [config.target]: nextSources };
|
|
121
160
|
if (content.sourceTrait) {
|
|
122
|
-
|
|
123
|
-
notifyTraitSubscribers(content.sourceTrait,
|
|
161
|
+
indexTraitRender(content.sourceTrait, content);
|
|
162
|
+
notifyTraitSubscribers(content.sourceTrait, content);
|
|
163
|
+
}
|
|
164
|
+
notifySubscribers(config.target, aggregateSlot(nextSources));
|
|
165
|
+
return nextAll;
|
|
166
|
+
});
|
|
167
|
+
return id;
|
|
168
|
+
},
|
|
169
|
+
[notifySubscribers, notifyTraitSubscribers, indexTraitRender]
|
|
170
|
+
);
|
|
171
|
+
const clear = react.useCallback(
|
|
172
|
+
(slot) => {
|
|
173
|
+
setSources((prev) => {
|
|
174
|
+
const slotSources = prev[slot];
|
|
175
|
+
if (!slotSources || Object.keys(slotSources).length === 0) {
|
|
176
|
+
return prev;
|
|
177
|
+
}
|
|
178
|
+
for (const content of Object.values(slotSources)) {
|
|
179
|
+
const timer = timersRef.current.get(content.id);
|
|
180
|
+
if (timer) {
|
|
181
|
+
clearTimeout(timer);
|
|
182
|
+
timersRef.current.delete(content.id);
|
|
183
|
+
}
|
|
184
|
+
content.onDismiss?.();
|
|
185
|
+
if (content.sourceTrait) {
|
|
186
|
+
unindexTrait(content.sourceTrait);
|
|
187
|
+
notifyTraitSubscribers(content.sourceTrait, null);
|
|
188
|
+
}
|
|
124
189
|
}
|
|
125
190
|
notifySubscribers(slot, null);
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
const
|
|
191
|
+
return { ...prev, [slot]: {} };
|
|
192
|
+
});
|
|
193
|
+
},
|
|
194
|
+
[notifySubscribers, notifyTraitSubscribers, unindexTrait]
|
|
195
|
+
);
|
|
196
|
+
const clearBySource = react.useCallback(
|
|
197
|
+
(slot, sourceTrait) => {
|
|
198
|
+
const sourceKey = sourceTrait;
|
|
199
|
+
setSources((prev) => {
|
|
200
|
+
const slotSources = prev[slot];
|
|
201
|
+
if (!slotSources || !(sourceKey in slotSources)) return prev;
|
|
202
|
+
const content = slotSources[sourceKey];
|
|
203
|
+
const timer = timersRef.current.get(content.id);
|
|
136
204
|
if (timer) {
|
|
137
205
|
clearTimeout(timer);
|
|
138
|
-
timersRef.current.delete(id);
|
|
206
|
+
timersRef.current.delete(content.id);
|
|
139
207
|
}
|
|
140
208
|
content.onDismiss?.();
|
|
141
209
|
if (content.sourceTrait) {
|
|
142
210
|
unindexTrait(content.sourceTrait);
|
|
143
211
|
notifyTraitSubscribers(content.sourceTrait, null);
|
|
144
212
|
}
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
213
|
+
const nextSources = { ...slotSources };
|
|
214
|
+
delete nextSources[sourceKey];
|
|
215
|
+
notifySubscribers(slot, aggregateSlot(nextSources));
|
|
216
|
+
return { ...prev, [slot]: nextSources };
|
|
217
|
+
});
|
|
218
|
+
},
|
|
219
|
+
[notifySubscribers, notifyTraitSubscribers, unindexTrait]
|
|
220
|
+
);
|
|
221
|
+
const clearById = react.useCallback(
|
|
222
|
+
(id) => {
|
|
223
|
+
setSources((prev) => {
|
|
224
|
+
for (const slot of ALL_SLOTS) {
|
|
225
|
+
const slotSources = prev[slot];
|
|
226
|
+
if (!slotSources) continue;
|
|
227
|
+
const matchKey = Object.keys(slotSources).find(
|
|
228
|
+
(k) => slotSources[k].id === id
|
|
229
|
+
);
|
|
230
|
+
if (!matchKey) continue;
|
|
231
|
+
const content = slotSources[matchKey];
|
|
232
|
+
const timer = timersRef.current.get(id);
|
|
233
|
+
if (timer) {
|
|
234
|
+
clearTimeout(timer);
|
|
235
|
+
timersRef.current.delete(id);
|
|
236
|
+
}
|
|
237
|
+
content.onDismiss?.();
|
|
238
|
+
if (content.sourceTrait) {
|
|
239
|
+
unindexTrait(content.sourceTrait);
|
|
240
|
+
notifyTraitSubscribers(content.sourceTrait, null);
|
|
241
|
+
}
|
|
242
|
+
const nextSources = { ...slotSources };
|
|
243
|
+
delete nextSources[matchKey];
|
|
244
|
+
notifySubscribers(slot, aggregateSlot(nextSources));
|
|
245
|
+
return { ...prev, [slot]: nextSources };
|
|
246
|
+
}
|
|
247
|
+
return prev;
|
|
248
|
+
});
|
|
249
|
+
},
|
|
250
|
+
[notifySubscribers, notifyTraitSubscribers, unindexTrait]
|
|
251
|
+
);
|
|
151
252
|
const clearAll = react.useCallback(() => {
|
|
152
253
|
timersRef.current.forEach((timer) => clearTimeout(timer));
|
|
153
254
|
timersRef.current.clear();
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
255
|
+
setSources((prev) => {
|
|
256
|
+
for (const slot of ALL_SLOTS) {
|
|
257
|
+
const slotSources = prev[slot];
|
|
258
|
+
if (!slotSources) continue;
|
|
259
|
+
for (const content of Object.values(slotSources)) {
|
|
157
260
|
content.onDismiss?.();
|
|
158
261
|
if (content.sourceTrait) {
|
|
159
262
|
notifyTraitSubscribers(content.sourceTrait, null);
|
|
160
263
|
}
|
|
161
|
-
notifySubscribers(slot, null);
|
|
162
264
|
}
|
|
163
|
-
|
|
164
|
-
|
|
265
|
+
notifySubscribers(slot, null);
|
|
266
|
+
}
|
|
267
|
+
return DEFAULT_SOURCES;
|
|
165
268
|
});
|
|
166
269
|
traitIndexRef.current.clear();
|
|
167
270
|
}, [notifySubscribers, notifyTraitSubscribers]);
|
|
@@ -171,16 +274,16 @@ function useUISlotManager() {
|
|
|
171
274
|
subscribersRef.current.delete(callback);
|
|
172
275
|
};
|
|
173
276
|
}, []);
|
|
174
|
-
const hasContent = react.useCallback(
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
277
|
+
const hasContent = react.useCallback(
|
|
278
|
+
(slot) => slots[slot] !== null,
|
|
279
|
+
[slots]
|
|
280
|
+
);
|
|
281
|
+
const getContent = react.useCallback(
|
|
282
|
+
(slot) => slots[slot],
|
|
283
|
+
[slots]
|
|
284
|
+
);
|
|
180
285
|
const getTraitContent = react.useCallback(
|
|
181
|
-
(traitName) =>
|
|
182
|
-
return traitIndexRef.current.get(traitName) ?? null;
|
|
183
|
-
},
|
|
286
|
+
(traitName) => traitIndexRef.current.get(traitName) ?? null,
|
|
184
287
|
[]
|
|
185
288
|
);
|
|
186
289
|
const subscribeTrait = react.useCallback(
|
|
@@ -206,6 +309,7 @@ function useUISlotManager() {
|
|
|
206
309
|
slots,
|
|
207
310
|
render,
|
|
208
311
|
clear,
|
|
312
|
+
clearBySource,
|
|
209
313
|
clearById,
|
|
210
314
|
clearAll,
|
|
211
315
|
subscribe,
|