@tixxin/nuxt-theme-engine 0.0.2 → 0.0.3
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/README.md +2 -0
- package/dist/module.json +1 -1
- package/dist/runtime/components/ThemeComponent.vue +87 -17
- package/package.json +1 -1
package/README.md
CHANGED
package/dist/module.json
CHANGED
|
@@ -1,8 +1,54 @@
|
|
|
1
1
|
<script>
|
|
2
|
-
import { computed, defineAsyncComponent, defineComponent, h, useAttrs, useSlots } from "vue";
|
|
2
|
+
import { computed, defineAsyncComponent, defineComponent, h, onServerPrefetch, shallowRef, useAttrs, useSlots, watch } from "vue";
|
|
3
3
|
import { themeComponentLoaders, themeComponentRegistry } from "#build/theme-engine.registry.mjs";
|
|
4
4
|
import { useThemeEngine } from "../composables/useThemeEngine";
|
|
5
5
|
const asyncComponentCache = /* @__PURE__ */ new Map();
|
|
6
|
+
const loadedComponentCache = /* @__PURE__ */ new Map();
|
|
7
|
+
const loadingTaskCache = /* @__PURE__ */ new Map();
|
|
8
|
+
function resolveThemeComponent(themeName, componentName, firstThemeName) {
|
|
9
|
+
const entry = themeComponentRegistry[themeName]?.[componentName] ?? themeComponentRegistry[firstThemeName]?.[componentName];
|
|
10
|
+
const loader = themeComponentLoaders[themeName]?.[componentName] ?? themeComponentLoaders[firstThemeName]?.[componentName];
|
|
11
|
+
if (!entry || !loader) {
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
return {
|
|
15
|
+
cacheKey: `${entry.sourceTheme}:${componentName}`,
|
|
16
|
+
loader
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
async function loadThemeComponent(cacheKey, loader) {
|
|
20
|
+
const cachedComponent = loadedComponentCache.get(cacheKey);
|
|
21
|
+
if (cachedComponent) {
|
|
22
|
+
return cachedComponent;
|
|
23
|
+
}
|
|
24
|
+
const loadingTask = loadingTaskCache.get(cacheKey);
|
|
25
|
+
if (loadingTask) {
|
|
26
|
+
return loadingTask;
|
|
27
|
+
}
|
|
28
|
+
const task = loader().then((module) => {
|
|
29
|
+
const component = module.default ?? null;
|
|
30
|
+
if (component) {
|
|
31
|
+
loadedComponentCache.set(cacheKey, component);
|
|
32
|
+
}
|
|
33
|
+
return component;
|
|
34
|
+
}).finally(() => {
|
|
35
|
+
loadingTaskCache.delete(cacheKey);
|
|
36
|
+
});
|
|
37
|
+
loadingTaskCache.set(cacheKey, task);
|
|
38
|
+
return task;
|
|
39
|
+
}
|
|
40
|
+
function getAsyncComponent(cacheKey, loader) {
|
|
41
|
+
if (!asyncComponentCache.has(cacheKey)) {
|
|
42
|
+
asyncComponentCache.set(cacheKey, defineAsyncComponent(async () => {
|
|
43
|
+
const component = await loadThemeComponent(cacheKey, loader);
|
|
44
|
+
if (!component) {
|
|
45
|
+
throw new Error(`Theme component "${cacheKey}" failed to load.`);
|
|
46
|
+
}
|
|
47
|
+
return component;
|
|
48
|
+
}));
|
|
49
|
+
}
|
|
50
|
+
return asyncComponentCache.get(cacheKey) ?? null;
|
|
51
|
+
}
|
|
6
52
|
export default defineComponent({
|
|
7
53
|
name: "ThemeComponent",
|
|
8
54
|
inheritAttrs: false,
|
|
@@ -17,29 +63,53 @@ export default defineComponent({
|
|
|
17
63
|
const slots = useSlots();
|
|
18
64
|
const { currentTheme } = useThemeEngine();
|
|
19
65
|
const firstThemeName = Object.keys(themeComponentRegistry)[0] ?? "";
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
66
|
+
const displayedComponent = shallowRef(null);
|
|
67
|
+
const displayedCacheKey = shallowRef(null);
|
|
68
|
+
const targetComponent = computed(() => resolveThemeComponent(currentTheme.value, props.name, firstThemeName));
|
|
69
|
+
let activeRequestId = 0;
|
|
70
|
+
async function syncDisplayedComponent() {
|
|
71
|
+
const requestId = ++activeRequestId;
|
|
72
|
+
const resolvedTarget = targetComponent.value;
|
|
73
|
+
if (!resolvedTarget) {
|
|
74
|
+
displayedComponent.value = null;
|
|
75
|
+
displayedCacheKey.value = null;
|
|
76
|
+
return;
|
|
27
77
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
return null;
|
|
78
|
+
if (displayedCacheKey.value === resolvedTarget.cacheKey && displayedComponent.value) {
|
|
79
|
+
return;
|
|
31
80
|
}
|
|
32
|
-
const
|
|
33
|
-
if (
|
|
34
|
-
|
|
81
|
+
const cachedComponent = loadedComponentCache.get(resolvedTarget.cacheKey);
|
|
82
|
+
if (cachedComponent) {
|
|
83
|
+
displayedComponent.value = cachedComponent;
|
|
84
|
+
displayedCacheKey.value = resolvedTarget.cacheKey;
|
|
85
|
+
return;
|
|
35
86
|
}
|
|
36
|
-
|
|
87
|
+
const hasDisplayedComponent = Boolean(displayedComponent.value);
|
|
88
|
+
if (!hasDisplayedComponent) {
|
|
89
|
+
displayedComponent.value = getAsyncComponent(resolvedTarget.cacheKey, resolvedTarget.loader);
|
|
90
|
+
displayedCacheKey.value = resolvedTarget.cacheKey;
|
|
91
|
+
}
|
|
92
|
+
const loadedComponent = await loadThemeComponent(resolvedTarget.cacheKey, resolvedTarget.loader);
|
|
93
|
+
if (!loadedComponent || requestId !== activeRequestId) {
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
displayedComponent.value = loadedComponent;
|
|
97
|
+
displayedCacheKey.value = resolvedTarget.cacheKey;
|
|
98
|
+
}
|
|
99
|
+
watch([
|
|
100
|
+
() => currentTheme.value,
|
|
101
|
+
() => props.name
|
|
102
|
+
], () => {
|
|
103
|
+
void syncDisplayedComponent();
|
|
104
|
+
}, {
|
|
105
|
+
immediate: true
|
|
37
106
|
});
|
|
107
|
+
onServerPrefetch(syncDisplayedComponent);
|
|
38
108
|
return () => {
|
|
39
|
-
if (!
|
|
109
|
+
if (!displayedComponent.value) {
|
|
40
110
|
return null;
|
|
41
111
|
}
|
|
42
|
-
return h(
|
|
112
|
+
return h(displayedComponent.value, attrs, slots);
|
|
43
113
|
};
|
|
44
114
|
}
|
|
45
115
|
});
|