vue-layerx 0.0.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/LICENSE +21 -0
- package/README.md +85 -0
- package/dist/index.cjs +546 -0
- package/dist/index.d.cts +107 -0
- package/dist/index.d.ts +107 -0
- package/dist/index.js +521 -0
- package/package.json +61 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,521 @@
|
|
|
1
|
+
// src/runtime/create-use-layer.ts
|
|
2
|
+
import {
|
|
3
|
+
getCurrentInstance,
|
|
4
|
+
onUnmounted,
|
|
5
|
+
reactive,
|
|
6
|
+
shallowRef
|
|
7
|
+
} from "vue";
|
|
8
|
+
|
|
9
|
+
// src/vue/instance/instance-registry.ts
|
|
10
|
+
var registry = /* @__PURE__ */ new WeakMap();
|
|
11
|
+
function attachInternal(instance, internal) {
|
|
12
|
+
registry.set(instance, internal);
|
|
13
|
+
}
|
|
14
|
+
function getInternal(instance) {
|
|
15
|
+
const internal = registry.get(instance);
|
|
16
|
+
if (!internal) {
|
|
17
|
+
throw new Error("[vue-layerx] Invalid LayerInstance passed to LayerBind");
|
|
18
|
+
}
|
|
19
|
+
return internal;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// src/vue/instance/internal-state.ts
|
|
23
|
+
import { ref } from "vue";
|
|
24
|
+
function warnDuplicate(name, scope) {
|
|
25
|
+
if (typeof process !== "undefined" && process.env?.NODE_ENV === "production") return;
|
|
26
|
+
console.warn(
|
|
27
|
+
`[vue-layerx] Duplicate LayerTemplate name="${name}" in ${scope} scope; latter wins`
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
function createLayerInternalState() {
|
|
31
|
+
const slotsVersion = ref(0);
|
|
32
|
+
const layerTemplates = {};
|
|
33
|
+
const contentTemplates = {};
|
|
34
|
+
const bumpSlots = () => {
|
|
35
|
+
slotsVersion.value++;
|
|
36
|
+
};
|
|
37
|
+
const registerLayerTemplate = (name, entry) => {
|
|
38
|
+
if (layerTemplates[name]) warnDuplicate(name, "layer");
|
|
39
|
+
layerTemplates[name] = entry;
|
|
40
|
+
bumpSlots();
|
|
41
|
+
};
|
|
42
|
+
const registerContentTemplate = (name, entry) => {
|
|
43
|
+
if (contentTemplates[name]) warnDuplicate(name, "content");
|
|
44
|
+
contentTemplates[name] = entry;
|
|
45
|
+
bumpSlots();
|
|
46
|
+
};
|
|
47
|
+
return {
|
|
48
|
+
layerTemplates,
|
|
49
|
+
contentTemplates,
|
|
50
|
+
slotsVersion,
|
|
51
|
+
bumpSlots,
|
|
52
|
+
registerLayerTemplate,
|
|
53
|
+
registerContentTemplate
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// src/runtime/layer-root.ts
|
|
58
|
+
import { defineComponent, provide } from "vue";
|
|
59
|
+
|
|
60
|
+
// src/core/config/merge-node-config.ts
|
|
61
|
+
function mergeProps(...sources) {
|
|
62
|
+
const result = {};
|
|
63
|
+
for (const source of sources) {
|
|
64
|
+
if (!source) continue;
|
|
65
|
+
Object.assign(result, source);
|
|
66
|
+
}
|
|
67
|
+
return result;
|
|
68
|
+
}
|
|
69
|
+
function mergeNodeConfig(...sources) {
|
|
70
|
+
const result = {};
|
|
71
|
+
for (const source of sources) {
|
|
72
|
+
if (!source) continue;
|
|
73
|
+
if (source.component !== void 0) result.component = source.component;
|
|
74
|
+
result.props = mergeProps(result.props, source.props);
|
|
75
|
+
if (source.slots) {
|
|
76
|
+
result.slots = { ...result.slots, ...source.slots };
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return result;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// src/core/config/merge-config.ts
|
|
83
|
+
function pickContentConfig(payload) {
|
|
84
|
+
if (!payload) return void 0;
|
|
85
|
+
const result = {};
|
|
86
|
+
if (payload.component !== void 0) result.component = payload.component;
|
|
87
|
+
if (payload.props !== void 0) result.props = payload.props;
|
|
88
|
+
if (payload.slots !== void 0) result.slots = payload.slots;
|
|
89
|
+
if (Object.keys(result).length === 0) return void 0;
|
|
90
|
+
return result;
|
|
91
|
+
}
|
|
92
|
+
function pickLayerConfig(payload) {
|
|
93
|
+
return payload?.layer;
|
|
94
|
+
}
|
|
95
|
+
function defineLayerToConfig(defineLayer2) {
|
|
96
|
+
if (!defineLayer2) return void 0;
|
|
97
|
+
const result = {
|
|
98
|
+
layer: mergeNodeConfig(
|
|
99
|
+
defineLayer2.props ? { props: defineLayer2.props } : void 0,
|
|
100
|
+
defineLayer2.layer
|
|
101
|
+
)
|
|
102
|
+
};
|
|
103
|
+
if (defineLayer2.hideOn) result.hideOn = defineLayer2.hideOn;
|
|
104
|
+
return result;
|
|
105
|
+
}
|
|
106
|
+
function mergeConfig(ctx) {
|
|
107
|
+
const defineLayerConfig = defineLayerToConfig(ctx.defineLayer);
|
|
108
|
+
const content = mergeNodeConfig(
|
|
109
|
+
ctx.layerDefaults.content,
|
|
110
|
+
pickContentConfig(ctx.useOptions),
|
|
111
|
+
pickContentConfig(ctx.partial),
|
|
112
|
+
pickContentConfig(ctx.showOptions)
|
|
113
|
+
);
|
|
114
|
+
const layer = mergeNodeConfig(
|
|
115
|
+
ctx.layerDefaults.layer,
|
|
116
|
+
defineLayerConfig?.layer,
|
|
117
|
+
pickLayerConfig(ctx.useOptions),
|
|
118
|
+
pickLayerConfig(ctx.partial),
|
|
119
|
+
pickLayerConfig(ctx.showOptions)
|
|
120
|
+
);
|
|
121
|
+
const hideOn = ctx.showOptions.hideOn ?? ctx.partial?.hideOn ?? ctx.useOptions.hideOn ?? defineLayerConfig?.hideOn;
|
|
122
|
+
return { content, layer, hideOn };
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// src/core/config/bind-hide-on.ts
|
|
126
|
+
function bindHideOn(contentProps, events, hide) {
|
|
127
|
+
if (!events?.length) return contentProps;
|
|
128
|
+
const listeners = {};
|
|
129
|
+
for (const event of events) {
|
|
130
|
+
const key = `on${event.charAt(0).toUpperCase()}${event.slice(1)}`;
|
|
131
|
+
const prev = contentProps[key];
|
|
132
|
+
listeners[key] = (...args) => {
|
|
133
|
+
prev?.(...args);
|
|
134
|
+
hide();
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
return { ...contentProps, ...listeners };
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// src/core/config/default-resolve.ts
|
|
141
|
+
function materializeTemplates(templates) {
|
|
142
|
+
const slots = {};
|
|
143
|
+
for (const [name, entry] of Object.entries(templates)) {
|
|
144
|
+
slots[name] = (slotProps) => entry.render(slotProps ?? {});
|
|
145
|
+
}
|
|
146
|
+
return slots;
|
|
147
|
+
}
|
|
148
|
+
function resolveNodeSlots(templates, mergedSlots) {
|
|
149
|
+
return {
|
|
150
|
+
...materializeTemplates(templates),
|
|
151
|
+
...mergedSlots
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
function defaultResolve(ctx) {
|
|
155
|
+
const { merged, LayerComponent, boundContent, layerTemplates, contentTemplates, hide } = ctx;
|
|
156
|
+
const contentComponent = merged.content.component ?? boundContent;
|
|
157
|
+
const layerNormalized = {
|
|
158
|
+
component: merged.layer.component ?? LayerComponent,
|
|
159
|
+
props: merged.layer.props ?? {},
|
|
160
|
+
slots: resolveNodeSlots(layerTemplates, merged.layer.slots)
|
|
161
|
+
};
|
|
162
|
+
if (!contentComponent) {
|
|
163
|
+
return {
|
|
164
|
+
layer: layerNormalized,
|
|
165
|
+
content: {
|
|
166
|
+
component: LayerComponent,
|
|
167
|
+
props: {},
|
|
168
|
+
slots: {}
|
|
169
|
+
}
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
const contentProps = bindHideOn(merged.content.props ?? {}, merged.hideOn, hide);
|
|
173
|
+
return {
|
|
174
|
+
layer: layerNormalized,
|
|
175
|
+
content: {
|
|
176
|
+
component: contentComponent,
|
|
177
|
+
props: contentProps,
|
|
178
|
+
slots: resolveNodeSlots(contentTemplates, merged.content.slots)
|
|
179
|
+
}
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
function hasContentComponent(ctx) {
|
|
183
|
+
return !!(ctx.merged.content.component ?? ctx.boundContent);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// src/vue/render/render-layer-tree.ts
|
|
187
|
+
import { h } from "vue";
|
|
188
|
+
|
|
189
|
+
// src/core/constants/markers.ts
|
|
190
|
+
var LAYERX_DIRECT_CONTENT = "__layerxDirect";
|
|
191
|
+
|
|
192
|
+
// src/vue/render/build-visible-props.ts
|
|
193
|
+
function buildVisibleProps(layerProps, visible, visibleProp, visibleEvent, hide) {
|
|
194
|
+
return {
|
|
195
|
+
...layerProps,
|
|
196
|
+
[visibleProp]: visible,
|
|
197
|
+
[visibleEvent]: (value) => {
|
|
198
|
+
if (value === false || value === void 0) hide();
|
|
199
|
+
}
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// src/vue/render/render-layer-tree.ts
|
|
204
|
+
function renderLayerTree({
|
|
205
|
+
plan,
|
|
206
|
+
hasContent,
|
|
207
|
+
contentMountKey
|
|
208
|
+
}) {
|
|
209
|
+
const layerProps = buildVisibleProps(
|
|
210
|
+
plan.layer.props,
|
|
211
|
+
plan.visible,
|
|
212
|
+
plan.visibleProp,
|
|
213
|
+
plan.visibleEvent,
|
|
214
|
+
plan.onHide
|
|
215
|
+
);
|
|
216
|
+
const defaultSlot = hasContent ? () => h(
|
|
217
|
+
plan.content.component,
|
|
218
|
+
{
|
|
219
|
+
...plan.content.props,
|
|
220
|
+
key: contentMountKey,
|
|
221
|
+
[LAYERX_DIRECT_CONTENT]: true
|
|
222
|
+
},
|
|
223
|
+
plan.content.slots
|
|
224
|
+
) : () => null;
|
|
225
|
+
return h(plan.layer.component, layerProps, {
|
|
226
|
+
default: defaultSlot,
|
|
227
|
+
...plan.layer.slots
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// src/vue/di/injection-keys.ts
|
|
232
|
+
var LAYER_DEFINE_KEY = /* @__PURE__ */ Symbol("vue-layerx-define");
|
|
233
|
+
var LAYER_TEMPLATE_REGISTRY_KEY = /* @__PURE__ */ Symbol("vue-layerx-layer-template");
|
|
234
|
+
var LAYER_BIND_REGISTRY_KEY = /* @__PURE__ */ Symbol("vue-layerx-content-template");
|
|
235
|
+
|
|
236
|
+
// src/runtime/layer-root.ts
|
|
237
|
+
function buildLayerRoot(ctx, opts, internal, state, defineLayerConfig, hide) {
|
|
238
|
+
return defineComponent({
|
|
239
|
+
name: `LayerRoot_${opts.Content ? opts.Content.name ?? "Anonymous" : "Shell"}`,
|
|
240
|
+
setup() {
|
|
241
|
+
provide(LAYER_DEFINE_KEY, {
|
|
242
|
+
register(config) {
|
|
243
|
+
defineLayerConfig.value = config;
|
|
244
|
+
internal.bumpSlots();
|
|
245
|
+
}
|
|
246
|
+
});
|
|
247
|
+
provide(LAYER_TEMPLATE_REGISTRY_KEY, {
|
|
248
|
+
registerLayerTemplate: internal.registerLayerTemplate
|
|
249
|
+
});
|
|
250
|
+
return () => {
|
|
251
|
+
if (!state.visible) return null;
|
|
252
|
+
void internal.slotsVersion.value;
|
|
253
|
+
const merged = mergeConfig({
|
|
254
|
+
layerDefaults: ctx.layerDefaults,
|
|
255
|
+
defineLayer: defineLayerConfig.value,
|
|
256
|
+
useOptions: opts.useOptions,
|
|
257
|
+
showOptions: state.showOptions,
|
|
258
|
+
partial: opts.partial
|
|
259
|
+
});
|
|
260
|
+
const resolveCtx = {
|
|
261
|
+
merged,
|
|
262
|
+
LayerComponent: ctx.LayerComponent,
|
|
263
|
+
boundContent: opts.Content,
|
|
264
|
+
layerTemplates: internal.layerTemplates,
|
|
265
|
+
contentTemplates: internal.contentTemplates,
|
|
266
|
+
hide
|
|
267
|
+
};
|
|
268
|
+
const resolved = defaultResolve(resolveCtx);
|
|
269
|
+
const normalized = ctx.adapt ? ctx.adapt(resolved) : resolved;
|
|
270
|
+
const contentPresent = hasContentComponent(resolveCtx);
|
|
271
|
+
const plan = {
|
|
272
|
+
...normalized,
|
|
273
|
+
visible: true,
|
|
274
|
+
visibleProp: ctx.visibleProp,
|
|
275
|
+
visibleEvent: ctx.visibleEvent,
|
|
276
|
+
onHide: hide
|
|
277
|
+
};
|
|
278
|
+
return renderLayerTree({
|
|
279
|
+
plan,
|
|
280
|
+
hasContent: contentPresent,
|
|
281
|
+
contentMountKey: contentPresent ? state.contentMountKey : void 0
|
|
282
|
+
});
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
// src/runtime/layer-runtime.ts
|
|
289
|
+
import { h as h2, render } from "vue";
|
|
290
|
+
function createLayerRuntime(root, appContext) {
|
|
291
|
+
let container = null;
|
|
292
|
+
return {
|
|
293
|
+
get mounted() {
|
|
294
|
+
return container !== null;
|
|
295
|
+
},
|
|
296
|
+
mount() {
|
|
297
|
+
if (!container) {
|
|
298
|
+
container = document.createElement("div");
|
|
299
|
+
document.body.appendChild(container);
|
|
300
|
+
}
|
|
301
|
+
const vnode = h2(root);
|
|
302
|
+
if (appContext) vnode.appContext = appContext;
|
|
303
|
+
render(vnode, container);
|
|
304
|
+
},
|
|
305
|
+
unmount() {
|
|
306
|
+
if (!container) return;
|
|
307
|
+
render(null, container);
|
|
308
|
+
container.remove();
|
|
309
|
+
container = null;
|
|
310
|
+
}
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// src/runtime/create-use-layer.ts
|
|
315
|
+
function createInstanceLifecycle() {
|
|
316
|
+
const disposers = [];
|
|
317
|
+
return {
|
|
318
|
+
register(dispose) {
|
|
319
|
+
disposers.push(dispose);
|
|
320
|
+
},
|
|
321
|
+
dispose() {
|
|
322
|
+
for (const dispose of disposers.splice(0)) dispose();
|
|
323
|
+
}
|
|
324
|
+
};
|
|
325
|
+
}
|
|
326
|
+
function createInstance(ctx, opts) {
|
|
327
|
+
const internal = createLayerInternalState();
|
|
328
|
+
const state = reactive({
|
|
329
|
+
visible: false,
|
|
330
|
+
showOptions: {},
|
|
331
|
+
contentMountKey: 0
|
|
332
|
+
});
|
|
333
|
+
const defineLayerConfig = shallowRef(null);
|
|
334
|
+
const hide = () => {
|
|
335
|
+
state.visible = false;
|
|
336
|
+
};
|
|
337
|
+
const LayerRoot = buildLayerRoot(ctx, opts, internal, state, defineLayerConfig, hide);
|
|
338
|
+
const runtime = createLayerRuntime(LayerRoot, opts.appContext);
|
|
339
|
+
const dispose = () => {
|
|
340
|
+
state.visible = false;
|
|
341
|
+
runtime.unmount();
|
|
342
|
+
};
|
|
343
|
+
const show = (payload) => {
|
|
344
|
+
defineLayerConfig.value = null;
|
|
345
|
+
if (payload) state.showOptions = payload;
|
|
346
|
+
state.contentMountKey++;
|
|
347
|
+
state.visible = true;
|
|
348
|
+
if (!runtime.mounted) runtime.mount();
|
|
349
|
+
};
|
|
350
|
+
const instance = {
|
|
351
|
+
show,
|
|
352
|
+
hide,
|
|
353
|
+
clone(partial) {
|
|
354
|
+
const bundle = createInstance(ctx, {
|
|
355
|
+
Content: opts.Content,
|
|
356
|
+
useOptions: opts.useOptions,
|
|
357
|
+
partial: partial ?? {},
|
|
358
|
+
appContext: opts.appContext,
|
|
359
|
+
lifecycle: opts.lifecycle
|
|
360
|
+
});
|
|
361
|
+
opts.lifecycle.register(bundle.dispose);
|
|
362
|
+
return bundle.instance;
|
|
363
|
+
},
|
|
364
|
+
get visible() {
|
|
365
|
+
return state.visible;
|
|
366
|
+
}
|
|
367
|
+
};
|
|
368
|
+
attachInternal(instance, internal);
|
|
369
|
+
return { instance, dispose };
|
|
370
|
+
}
|
|
371
|
+
function createUseLayer(ctx) {
|
|
372
|
+
return function useLayer(Content, useOptions = {}) {
|
|
373
|
+
const hostInstance = getCurrentInstance();
|
|
374
|
+
const appContext = hostInstance?.appContext ?? null;
|
|
375
|
+
const lifecycle = createInstanceLifecycle();
|
|
376
|
+
const { instance, dispose } = createInstance(ctx, {
|
|
377
|
+
Content,
|
|
378
|
+
useOptions,
|
|
379
|
+
partial: {},
|
|
380
|
+
appContext,
|
|
381
|
+
lifecycle
|
|
382
|
+
});
|
|
383
|
+
lifecycle.register(dispose);
|
|
384
|
+
if (hostInstance) {
|
|
385
|
+
onUnmounted(() => lifecycle.dispose());
|
|
386
|
+
}
|
|
387
|
+
return instance;
|
|
388
|
+
};
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
// src/api/create-layer.ts
|
|
392
|
+
var DEFAULT_VISIBLE = ["modelValue", "onUpdate:modelValue"];
|
|
393
|
+
function createLayer(LayerComponent, defaults = {}, adapt) {
|
|
394
|
+
const [visibleProp, visibleEvent] = defaults.visible ?? DEFAULT_VISIBLE;
|
|
395
|
+
return createUseLayer({
|
|
396
|
+
LayerComponent,
|
|
397
|
+
layerDefaults: defaults,
|
|
398
|
+
visibleProp,
|
|
399
|
+
visibleEvent,
|
|
400
|
+
adapt
|
|
401
|
+
});
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
// src/api/define-layer.ts
|
|
405
|
+
import { getCurrentInstance as getCurrentInstance2, inject } from "vue";
|
|
406
|
+
|
|
407
|
+
// src/vue/context/layer-marker.ts
|
|
408
|
+
function hasDirectLayerMarker(instance) {
|
|
409
|
+
if (!instance) return false;
|
|
410
|
+
if (instance.props?.[LAYERX_DIRECT_CONTENT] === true) return true;
|
|
411
|
+
const attrs = instance.attrs;
|
|
412
|
+
if (attrs?.[LAYERX_DIRECT_CONTENT] === true) return true;
|
|
413
|
+
const vnodeProps = instance.vnode?.props;
|
|
414
|
+
if (vnodeProps?.[LAYERX_DIRECT_CONTENT] === true) return true;
|
|
415
|
+
return false;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
// src/api/define-layer.ts
|
|
419
|
+
function defineLayer(options = {}) {
|
|
420
|
+
const registry2 = inject(LAYER_DEFINE_KEY, null);
|
|
421
|
+
const instance = getCurrentInstance2();
|
|
422
|
+
if (!registry2 || !hasDirectLayerMarker(instance)) return;
|
|
423
|
+
registry2.register(options);
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
// src/components/layer-template.ts
|
|
427
|
+
import { computed, defineComponent as defineComponent2, getCurrentInstance as getCurrentInstance3, inject as inject2, onMounted } from "vue";
|
|
428
|
+
|
|
429
|
+
// src/vue/context/owning-content.ts
|
|
430
|
+
function getOwningContentInstance(instance) {
|
|
431
|
+
let cur = instance?.parent ?? null;
|
|
432
|
+
while (cur) {
|
|
433
|
+
const type = cur.type;
|
|
434
|
+
if (typeof type === "object" || typeof type === "function") {
|
|
435
|
+
return cur;
|
|
436
|
+
}
|
|
437
|
+
cur = cur.parent;
|
|
438
|
+
}
|
|
439
|
+
return null;
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
// src/vue/context/in-layer-content.ts
|
|
443
|
+
function isInDirectLayerContent(instance) {
|
|
444
|
+
return hasDirectLayerMarker(getOwningContentInstance(instance));
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
// src/components/layer-template.ts
|
|
448
|
+
function buildTemplateScope(slotProps, layer) {
|
|
449
|
+
return {
|
|
450
|
+
slotProps,
|
|
451
|
+
inLayer: layer.inLayer,
|
|
452
|
+
outsideLayer: layer.outsideLayer
|
|
453
|
+
};
|
|
454
|
+
}
|
|
455
|
+
var LayerTemplate = defineComponent2({
|
|
456
|
+
name: "LayerTemplate",
|
|
457
|
+
props: {
|
|
458
|
+
name: {
|
|
459
|
+
type: String,
|
|
460
|
+
required: true
|
|
461
|
+
},
|
|
462
|
+
visibleOutside: {
|
|
463
|
+
type: Boolean,
|
|
464
|
+
default: false
|
|
465
|
+
}
|
|
466
|
+
},
|
|
467
|
+
setup(props, { slots }) {
|
|
468
|
+
const layerRegistry = inject2(LAYER_TEMPLATE_REGISTRY_KEY, null);
|
|
469
|
+
const bindRegistry = inject2(LAYER_BIND_REGISTRY_KEY, null);
|
|
470
|
+
const instance = getCurrentInstance3();
|
|
471
|
+
const inLayer = computed(
|
|
472
|
+
() => layerRegistry !== null && isInDirectLayerContent(instance)
|
|
473
|
+
);
|
|
474
|
+
const inBind = computed(() => bindRegistry !== null);
|
|
475
|
+
const renderSlot = (templateScope) => slots.default?.(templateScope) ?? null;
|
|
476
|
+
onMounted(() => {
|
|
477
|
+
const renderWithScope = (layer) => (slotProps = {}) => renderSlot(buildTemplateScope(slotProps, layer));
|
|
478
|
+
if (inLayer.value && layerRegistry) {
|
|
479
|
+
layerRegistry.registerLayerTemplate(props.name, {
|
|
480
|
+
render: renderWithScope({ inLayer: true, outsideLayer: false })
|
|
481
|
+
});
|
|
482
|
+
return;
|
|
483
|
+
}
|
|
484
|
+
if (inBind.value && bindRegistry) {
|
|
485
|
+
bindRegistry.registerContentTemplate(props.name, {
|
|
486
|
+
render: renderWithScope({ inLayer: true, outsideLayer: false })
|
|
487
|
+
});
|
|
488
|
+
}
|
|
489
|
+
});
|
|
490
|
+
return () => {
|
|
491
|
+
if (inLayer.value || inBind.value) return null;
|
|
492
|
+
if (!props.visibleOutside) return null;
|
|
493
|
+
return renderSlot(buildTemplateScope({}, { inLayer: false, outsideLayer: true }));
|
|
494
|
+
};
|
|
495
|
+
}
|
|
496
|
+
});
|
|
497
|
+
|
|
498
|
+
// src/components/layer-bind.ts
|
|
499
|
+
import { defineComponent as defineComponent3, provide as provide2 } from "vue";
|
|
500
|
+
var LayerBind = defineComponent3({
|
|
501
|
+
name: "LayerBind",
|
|
502
|
+
props: {
|
|
503
|
+
to: {
|
|
504
|
+
type: Object,
|
|
505
|
+
required: true
|
|
506
|
+
}
|
|
507
|
+
},
|
|
508
|
+
setup(props, { slots }) {
|
|
509
|
+
const internal = getInternal(props.to);
|
|
510
|
+
provide2(LAYER_BIND_REGISTRY_KEY, {
|
|
511
|
+
registerContentTemplate: internal.registerContentTemplate
|
|
512
|
+
});
|
|
513
|
+
return () => slots.default?.();
|
|
514
|
+
}
|
|
515
|
+
});
|
|
516
|
+
export {
|
|
517
|
+
LayerBind,
|
|
518
|
+
LayerTemplate,
|
|
519
|
+
createLayer,
|
|
520
|
+
defineLayer
|
|
521
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "vue-layerx",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Vue 3 hook factory for declarative + imperative layered UI (dialogs, drawers, etc.)",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.cjs",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.js",
|
|
13
|
+
"require": "./dist/index.cjs"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"dist"
|
|
18
|
+
],
|
|
19
|
+
"scripts": {
|
|
20
|
+
"build": "tsup",
|
|
21
|
+
"dev": "tsup --watch",
|
|
22
|
+
"test": "vitest run",
|
|
23
|
+
"test:watch": "vitest",
|
|
24
|
+
"test:coverage": "vitest run --coverage",
|
|
25
|
+
"playground": "pnpm build && pnpm --filter playground dev",
|
|
26
|
+
"docs:dev": "vitepress dev docs",
|
|
27
|
+
"docs:build": "vitepress build docs",
|
|
28
|
+
"docs:preview": "vitepress preview docs"
|
|
29
|
+
},
|
|
30
|
+
"repository": {
|
|
31
|
+
"type": "git",
|
|
32
|
+
"url": "git+https://github.com/xuyimingwork/vue-layerx.git"
|
|
33
|
+
},
|
|
34
|
+
"homepage": "https://github.com/xuyimingwork/vue-layerx#readme",
|
|
35
|
+
"bugs": {
|
|
36
|
+
"url": "https://github.com/xuyimingwork/vue-layerx/issues"
|
|
37
|
+
},
|
|
38
|
+
"keywords": [
|
|
39
|
+
"vue",
|
|
40
|
+
"vue3",
|
|
41
|
+
"dialog",
|
|
42
|
+
"modal",
|
|
43
|
+
"layer",
|
|
44
|
+
"composable"
|
|
45
|
+
],
|
|
46
|
+
"license": "MIT",
|
|
47
|
+
"peerDependencies": {
|
|
48
|
+
"vue": "^3.5.0"
|
|
49
|
+
},
|
|
50
|
+
"devDependencies": {
|
|
51
|
+
"@vitest/coverage-v8": "^3.2.4",
|
|
52
|
+
"@vue/test-utils": "^2.4.6",
|
|
53
|
+
"element-plus": "^2.11.4",
|
|
54
|
+
"jsdom": "^26.1.0",
|
|
55
|
+
"tsup": "^8.5.0",
|
|
56
|
+
"typescript": "^5.8.3",
|
|
57
|
+
"vitepress": "^1.6.3",
|
|
58
|
+
"vitest": "^3.2.4",
|
|
59
|
+
"vue": "^3.5.16"
|
|
60
|
+
}
|
|
61
|
+
}
|