@vigilkids/section-renderer-vue 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 +88 -0
- package/dist/assets/images/article/arrow.svg +3 -0
- package/dist/assets/images/article/hot.svg +3 -0
- package/dist/assets/images/article/notice-info-icon.svg +5 -0
- package/dist/assets/images/article/notice-info.svg +3 -0
- package/dist/assets/images/article/notice-warning-icon.svg +5 -0
- package/dist/assets/images/article/notice-warning.svg +10 -0
- package/dist/assets/images/article/question.svg +10 -0
- package/dist/composables/useInlineEdit.d.ts +30 -0
- package/dist/composables/useInlineEdit.mjs +94 -0
- package/dist/composables/useLazyRender.d.ts +18 -0
- package/dist/composables/useLazyRender.mjs +33 -0
- package/dist/composables/useRegistry.d.ts +38 -0
- package/dist/composables/useRegistry.mjs +60 -0
- package/dist/composables/useSectionSEO.d.ts +26 -0
- package/dist/composables/useSectionSEO.mjs +122 -0
- package/dist/composables/useSectionStyle.d.ts +23 -0
- package/dist/composables/useSectionStyle.mjs +111 -0
- package/dist/editor.d.ts +4 -0
- package/dist/editor.mjs +9 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.mjs +14 -0
- package/dist/plugin.d.ts +6 -0
- package/dist/plugin.mjs +14 -0
- package/dist/preview/createPreviewApp.d.ts +20 -0
- package/dist/preview/createPreviewApp.mjs +161 -0
- package/dist/renderer/FallbackSection.d.vue.ts +8 -0
- package/dist/renderer/FallbackSection.vue +17 -0
- package/dist/renderer/FallbackSection.vue.d.ts +8 -0
- package/dist/renderer/LazySection.d.vue.ts +60 -0
- package/dist/renderer/LazySection.vue +115 -0
- package/dist/renderer/LazySection.vue.d.ts +60 -0
- package/dist/renderer/SectionErrorBoundary.d.vue.ts +16 -0
- package/dist/renderer/SectionErrorBoundary.vue +38 -0
- package/dist/renderer/SectionErrorBoundary.vue.d.ts +16 -0
- package/dist/renderer/SectionRenderer.d.vue.ts +29 -0
- package/dist/renderer/SectionRenderer.vue +99 -0
- package/dist/renderer/SectionRenderer.vue.d.ts +29 -0
- package/dist/renderer/SectionWrapper.d.vue.ts +24 -0
- package/dist/renderer/SectionWrapper.vue +52 -0
- package/dist/renderer/SectionWrapper.vue.d.ts +24 -0
- package/dist/sections/RichTextSection.d.vue.ts +9 -0
- package/dist/sections/RichTextSection.vue +135 -0
- package/dist/sections/RichTextSection.vue.d.ts +9 -0
- package/dist/sections/article/index.d.ts +2 -0
- package/dist/sections/article/index.mjs +174 -0
- package/dist/sections/article/prosemirror.d.ts +2 -0
- package/dist/sections/article/prosemirror.mjs +65 -0
- package/dist/sections/article/shared/ArticleCustomHtml.d.vue.ts +9 -0
- package/dist/sections/article/shared/ArticleCustomHtml.vue +32 -0
- package/dist/sections/article/shared/ArticleCustomHtml.vue.d.ts +9 -0
- package/dist/sections/article/shared/ArticleImage.d.vue.ts +21 -0
- package/dist/sections/article/shared/ArticleImage.vue +53 -0
- package/dist/sections/article/shared/ArticleImage.vue.d.ts +21 -0
- package/dist/sections/article/vigilkids/ArticleBulletList.d.vue.ts +21 -0
- package/dist/sections/article/vigilkids/ArticleBulletList.vue +48 -0
- package/dist/sections/article/vigilkids/ArticleBulletList.vue.d.ts +21 -0
- package/dist/sections/article/vigilkids/ArticleCta.d.vue.ts +21 -0
- package/dist/sections/article/vigilkids/ArticleCta.vue +126 -0
- package/dist/sections/article/vigilkids/ArticleCta.vue.d.ts +21 -0
- package/dist/sections/article/vigilkids/ArticleFaq.d.vue.ts +21 -0
- package/dist/sections/article/vigilkids/ArticleFaq.vue +62 -0
- package/dist/sections/article/vigilkids/ArticleFaq.vue.d.ts +21 -0
- package/dist/sections/article/vigilkids/ArticleFaqItem.d.vue.ts +5 -0
- package/dist/sections/article/vigilkids/ArticleFaqItem.vue +24 -0
- package/dist/sections/article/vigilkids/ArticleFaqItem.vue.d.ts +5 -0
- package/dist/sections/article/vigilkids/ArticleFeature.d.vue.ts +21 -0
- package/dist/sections/article/vigilkids/ArticleFeature.vue +77 -0
- package/dist/sections/article/vigilkids/ArticleFeature.vue.d.ts +21 -0
- package/dist/sections/article/vigilkids/ArticleHeading.d.vue.ts +21 -0
- package/dist/sections/article/vigilkids/ArticleHeading.vue +53 -0
- package/dist/sections/article/vigilkids/ArticleHeading.vue.d.ts +21 -0
- package/dist/sections/article/vigilkids/ArticleNotice.d.vue.ts +21 -0
- package/dist/sections/article/vigilkids/ArticleNotice.vue +81 -0
- package/dist/sections/article/vigilkids/ArticleNotice.vue.d.ts +21 -0
- package/dist/sections/article/vigilkids/ArticleProsCons.d.vue.ts +21 -0
- package/dist/sections/article/vigilkids/ArticleProsCons.vue +74 -0
- package/dist/sections/article/vigilkids/ArticleProsCons.vue.d.ts +21 -0
- package/dist/sections/article/vigilkids/ArticleQuestion.d.vue.ts +21 -0
- package/dist/sections/article/vigilkids/ArticleQuestion.vue +58 -0
- package/dist/sections/article/vigilkids/ArticleQuestion.vue.d.ts +21 -0
- package/dist/sections/article/vigilkids/ArticleQuote.d.vue.ts +21 -0
- package/dist/sections/article/vigilkids/ArticleQuote.vue +50 -0
- package/dist/sections/article/vigilkids/ArticleQuote.vue.d.ts +21 -0
- package/dist/sections/article/vigilkids/ArticleStepList.d.vue.ts +21 -0
- package/dist/sections/article/vigilkids/ArticleStepList.vue +49 -0
- package/dist/sections/article/vigilkids/ArticleStepList.vue.d.ts +21 -0
- package/dist/sections/article/vigilkids/ArticleSubheading.d.vue.ts +21 -0
- package/dist/sections/article/vigilkids/ArticleSubheading.vue +56 -0
- package/dist/sections/article/vigilkids/ArticleSubheading.vue.d.ts +21 -0
- package/dist/sections/article/vigilkids/ArticleTable.d.vue.ts +9 -0
- package/dist/sections/article/vigilkids/ArticleTable.vue +75 -0
- package/dist/sections/article/vigilkids/ArticleTable.vue.d.ts +9 -0
- package/dist/sections/article/vigilkids/ArticleToc.d.vue.ts +21 -0
- package/dist/sections/article/vigilkids/ArticleToc.vue +102 -0
- package/dist/sections/article/vigilkids/ArticleToc.vue.d.ts +21 -0
- package/dist/sections/article/visiva/ArticleBulletList.d.vue.ts +21 -0
- package/dist/sections/article/visiva/ArticleBulletList.vue +48 -0
- package/dist/sections/article/visiva/ArticleBulletList.vue.d.ts +21 -0
- package/dist/sections/article/visiva/ArticleCta.d.vue.ts +21 -0
- package/dist/sections/article/visiva/ArticleCta.vue +148 -0
- package/dist/sections/article/visiva/ArticleCta.vue.d.ts +21 -0
- package/dist/sections/article/visiva/ArticleFaq.d.vue.ts +21 -0
- package/dist/sections/article/visiva/ArticleFaq.vue +76 -0
- package/dist/sections/article/visiva/ArticleFaq.vue.d.ts +21 -0
- package/dist/sections/article/visiva/ArticleFeature.d.vue.ts +21 -0
- package/dist/sections/article/visiva/ArticleFeature.vue +79 -0
- package/dist/sections/article/visiva/ArticleFeature.vue.d.ts +21 -0
- package/dist/sections/article/visiva/ArticleHeading.d.vue.ts +21 -0
- package/dist/sections/article/visiva/ArticleHeading.vue +61 -0
- package/dist/sections/article/visiva/ArticleHeading.vue.d.ts +21 -0
- package/dist/sections/article/visiva/ArticleNotice.d.vue.ts +21 -0
- package/dist/sections/article/visiva/ArticleNotice.vue +102 -0
- package/dist/sections/article/visiva/ArticleNotice.vue.d.ts +21 -0
- package/dist/sections/article/visiva/ArticleProsCons.d.vue.ts +21 -0
- package/dist/sections/article/visiva/ArticleProsCons.vue +98 -0
- package/dist/sections/article/visiva/ArticleProsCons.vue.d.ts +21 -0
- package/dist/sections/article/visiva/ArticleQuestion.d.vue.ts +21 -0
- package/dist/sections/article/visiva/ArticleQuestion.vue +80 -0
- package/dist/sections/article/visiva/ArticleQuestion.vue.d.ts +21 -0
- package/dist/sections/article/visiva/ArticleQuote.d.vue.ts +21 -0
- package/dist/sections/article/visiva/ArticleQuote.vue +50 -0
- package/dist/sections/article/visiva/ArticleQuote.vue.d.ts +21 -0
- package/dist/sections/article/visiva/ArticleStepList.d.vue.ts +21 -0
- package/dist/sections/article/visiva/ArticleStepList.vue +48 -0
- package/dist/sections/article/visiva/ArticleStepList.vue.d.ts +21 -0
- package/dist/sections/article/visiva/ArticleSubheading.d.vue.ts +21 -0
- package/dist/sections/article/visiva/ArticleSubheading.vue +91 -0
- package/dist/sections/article/visiva/ArticleSubheading.vue.d.ts +21 -0
- package/dist/sections/article/visiva/ArticleTable.d.vue.ts +9 -0
- package/dist/sections/article/visiva/ArticleTable.vue +140 -0
- package/dist/sections/article/visiva/ArticleTable.vue.d.ts +9 -0
- package/dist/sections/article/visiva/ArticleToc.d.vue.ts +21 -0
- package/dist/sections/article/visiva/ArticleToc.vue +116 -0
- package/dist/sections/article/visiva/ArticleToc.vue.d.ts +21 -0
- package/dist/shims-css.d.ts +4 -0
- package/dist/styles/products/vigilkids.css +1 -0
- package/dist/styles/products/visiva.css +1 -0
- package/package.json +43 -0
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { computed, toValue } from "vue";
|
|
2
|
+
const SAFE_COLOR_PATTERN = /^#[\da-fA-F]{6}$/;
|
|
3
|
+
const SPACING_PRESETS = {
|
|
4
|
+
compact: "py-8 sm:py-12",
|
|
5
|
+
standard: "py-12 sm:py-24",
|
|
6
|
+
spacious: "py-20 sm:py-32"
|
|
7
|
+
};
|
|
8
|
+
const ALIGN_CLASSES = {
|
|
9
|
+
left: "text-left",
|
|
10
|
+
center: "text-center",
|
|
11
|
+
right: "text-right"
|
|
12
|
+
};
|
|
13
|
+
const MAX_WIDTH_CLASSES = {
|
|
14
|
+
prose: "mx-auto max-w-prose",
|
|
15
|
+
wide: "mx-auto max-w-screen-lg",
|
|
16
|
+
full: "w-full"
|
|
17
|
+
};
|
|
18
|
+
const VISIBILITY_CLASSES = {
|
|
19
|
+
visible: "",
|
|
20
|
+
hidden: "hidden",
|
|
21
|
+
"mobile-only": "sm:hidden",
|
|
22
|
+
"desktop-only": "hidden sm:block"
|
|
23
|
+
};
|
|
24
|
+
function safeColor(value) {
|
|
25
|
+
const s = typeof value === "string" ? value : void 0;
|
|
26
|
+
if (s && SAFE_COLOR_PATTERN.test(s)) return s;
|
|
27
|
+
return void 0;
|
|
28
|
+
}
|
|
29
|
+
function safePixel(value) {
|
|
30
|
+
const n = typeof value === "number" ? value : Number(value);
|
|
31
|
+
if (!Number.isNaN(n) && n >= 0 && n <= 500) return n;
|
|
32
|
+
return void 0;
|
|
33
|
+
}
|
|
34
|
+
export function useSectionStyle(sectionId, settings) {
|
|
35
|
+
const style = computed(() => {
|
|
36
|
+
const id = toValue(sectionId);
|
|
37
|
+
const s = toValue(settings) ?? {};
|
|
38
|
+
const classes = [];
|
|
39
|
+
const styles = {};
|
|
40
|
+
const cssParts = [];
|
|
41
|
+
const spacingPreset = s.spacing_preset;
|
|
42
|
+
if (spacingPreset && spacingPreset !== "custom" && SPACING_PRESETS[spacingPreset]) {
|
|
43
|
+
classes.push(SPACING_PRESETS[spacingPreset]);
|
|
44
|
+
}
|
|
45
|
+
const textAlign = s.text_alignment;
|
|
46
|
+
if (textAlign && ALIGN_CLASSES[textAlign]) {
|
|
47
|
+
classes.push(ALIGN_CLASSES[textAlign]);
|
|
48
|
+
}
|
|
49
|
+
const maxWidth = s.max_width;
|
|
50
|
+
if (maxWidth && MAX_WIDTH_CLASSES[maxWidth]) {
|
|
51
|
+
classes.push(MAX_WIDTH_CLASSES[maxWidth]);
|
|
52
|
+
}
|
|
53
|
+
const visibility = s.visibility;
|
|
54
|
+
if (visibility && VISIBILITY_CLASSES[visibility]) {
|
|
55
|
+
classes.push(VISIBILITY_CLASSES[visibility]);
|
|
56
|
+
}
|
|
57
|
+
const bgColor = safeColor(s.background_color);
|
|
58
|
+
if (bgColor) {
|
|
59
|
+
styles["background-color"] = bgColor;
|
|
60
|
+
}
|
|
61
|
+
const textColor = safeColor(s.text_color);
|
|
62
|
+
if (textColor) {
|
|
63
|
+
styles.color = textColor;
|
|
64
|
+
}
|
|
65
|
+
const borderRadius = safePixel(s.border_radius);
|
|
66
|
+
if (borderRadius !== void 0 && borderRadius > 0) {
|
|
67
|
+
styles["border-radius"] = `${borderRadius}px`;
|
|
68
|
+
}
|
|
69
|
+
const marginTop = safePixel(s.margin_top);
|
|
70
|
+
if (marginTop !== void 0 && marginTop > 0) {
|
|
71
|
+
styles["margin-top"] = `${marginTop}px`;
|
|
72
|
+
}
|
|
73
|
+
const marginBottom = safePixel(s.margin_bottom);
|
|
74
|
+
if (marginBottom !== void 0 && marginBottom > 0) {
|
|
75
|
+
styles["margin-bottom"] = `${marginBottom}px`;
|
|
76
|
+
}
|
|
77
|
+
if (spacingPreset === "custom") {
|
|
78
|
+
const pt = safePixel(s.padding_top);
|
|
79
|
+
const pb = safePixel(s.padding_bottom);
|
|
80
|
+
if (pt !== void 0 || pb !== void 0) {
|
|
81
|
+
const mobileRules = [];
|
|
82
|
+
const desktopRules = [];
|
|
83
|
+
if (pt !== void 0) {
|
|
84
|
+
mobileRules.push(`padding-top: ${Math.round(pt * 0.75)}px`);
|
|
85
|
+
desktopRules.push(`padding-top: ${pt}px`);
|
|
86
|
+
}
|
|
87
|
+
if (pb !== void 0) {
|
|
88
|
+
mobileRules.push(`padding-bottom: ${Math.round(pb * 0.75)}px`);
|
|
89
|
+
desktopRules.push(`padding-bottom: ${pb}px`);
|
|
90
|
+
}
|
|
91
|
+
cssParts.push(`#section-${id} { ${mobileRules.join("; ")}; }`);
|
|
92
|
+
cssParts.push(`@media (min-width: 768px) { #section-${id} { ${desktopRules.join("; ")}; } }`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
const customCSS = typeof s.custom_css === "string" ? s.custom_css.trim() : "";
|
|
96
|
+
if (customCSS) {
|
|
97
|
+
const sanitized = customCSS.replace(/[<>]/g, "").slice(0, 2e3);
|
|
98
|
+
if (sanitized) {
|
|
99
|
+
cssParts.push(`#section-${id} { ${sanitized} }`);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
const customClass = typeof s.custom_class === "string" ? s.custom_class.trim() : "";
|
|
103
|
+
return {
|
|
104
|
+
wrapperClasses: classes.join(" "),
|
|
105
|
+
wrapperStyles: styles,
|
|
106
|
+
scopedCSS: cssParts.join("\n"),
|
|
107
|
+
customClass
|
|
108
|
+
};
|
|
109
|
+
});
|
|
110
|
+
return { style };
|
|
111
|
+
}
|
package/dist/editor.d.ts
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export * from './index';
|
|
2
|
+
export { createPreviewApp } from './preview/createPreviewApp';
|
|
3
|
+
export type { EditorToPreviewMessage, PreviewToEditorMessage, } from '@vigilkids/section-core/bridge';
|
|
4
|
+
export { BRIDGE_PROTOCOL_VERSION, HEARTBEAT_INTERVAL_MS, HEARTBEAT_MAX_MISSES, PreviewBridge, PREVIEW_CHANNEL, } from '@vigilkids/section-core/bridge';
|
package/dist/editor.mjs
ADDED
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export type { BlockData, SectionDefinition, SectionInstance, SectionRegistration, SectionsData, } from '@vigilkids/section-core';
|
|
2
|
+
export { safeColor, safeUrl } from '@vigilkids/section-core';
|
|
3
|
+
export { default as FallbackSection } from './renderer/FallbackSection.vue';
|
|
4
|
+
export { default as LazySection } from './renderer/LazySection.vue';
|
|
5
|
+
export { default as SectionErrorBoundary } from './renderer/SectionErrorBoundary.vue';
|
|
6
|
+
export { default as SectionRenderer } from './renderer/SectionRenderer.vue';
|
|
7
|
+
export { default as SectionWrapper } from './renderer/SectionWrapper.vue';
|
|
8
|
+
export { registerSection, useRegistry } from './composables/useRegistry';
|
|
9
|
+
export { useLazyRender } from './composables/useLazyRender';
|
|
10
|
+
export { useSectionStyle } from './composables/useSectionStyle';
|
|
11
|
+
export type { SectionStyleResult } from './composables/useSectionStyle';
|
|
12
|
+
export { useInlineEdit } from './composables/useInlineEdit';
|
|
13
|
+
export type { UseInlineEditOptions } from './composables/useInlineEdit';
|
|
14
|
+
export { generateJsonLdScripts, generateSectionJsonLd } from './composables/useSectionSEO';
|
|
15
|
+
export type { SectionSEOOptions } from './composables/useSectionSEO';
|
|
16
|
+
export { SectionRendererPlugin } from './plugin';
|
|
17
|
+
export { default as RichTextSection } from './sections/RichTextSection.vue';
|
|
18
|
+
export { registerArticleSections } from './sections/article';
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export { safeColor, safeUrl } from "@vigilkids/section-core";
|
|
2
|
+
export { default as FallbackSection } from "./renderer/FallbackSection.vue";
|
|
3
|
+
export { default as LazySection } from "./renderer/LazySection.vue";
|
|
4
|
+
export { default as SectionErrorBoundary } from "./renderer/SectionErrorBoundary.vue";
|
|
5
|
+
export { default as SectionRenderer } from "./renderer/SectionRenderer.vue";
|
|
6
|
+
export { default as SectionWrapper } from "./renderer/SectionWrapper.vue";
|
|
7
|
+
export { registerSection, useRegistry } from "./composables/useRegistry.mjs";
|
|
8
|
+
export { useLazyRender } from "./composables/useLazyRender.mjs";
|
|
9
|
+
export { useSectionStyle } from "./composables/useSectionStyle.mjs";
|
|
10
|
+
export { useInlineEdit } from "./composables/useInlineEdit.mjs";
|
|
11
|
+
export { generateJsonLdScripts, generateSectionJsonLd } from "./composables/useSectionSEO.mjs";
|
|
12
|
+
export { SectionRendererPlugin } from "./plugin.mjs";
|
|
13
|
+
export { default as RichTextSection } from "./sections/RichTextSection.vue";
|
|
14
|
+
export { registerArticleSections } from "./sections/article/index.mjs";
|
package/dist/plugin.d.ts
ADDED
package/dist/plugin.mjs
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { registerSection } from "./composables/useRegistry.mjs";
|
|
2
|
+
function registerBuiltinSections() {
|
|
3
|
+
registerSection({
|
|
4
|
+
name: "rich-text",
|
|
5
|
+
componentName: "RichTextSection",
|
|
6
|
+
component: () => import("./sections/RichTextSection.vue"),
|
|
7
|
+
supportsInlineEdit: true
|
|
8
|
+
});
|
|
9
|
+
}
|
|
10
|
+
export const SectionRendererPlugin = {
|
|
11
|
+
install() {
|
|
12
|
+
registerBuiltinSections();
|
|
13
|
+
}
|
|
14
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/** Preview App 配置 */
|
|
2
|
+
interface PreviewAppOptions {
|
|
3
|
+
/** postMessage bridge 实例 */
|
|
4
|
+
bridge: {
|
|
5
|
+
send: (msg: Record<string, unknown>) => void;
|
|
6
|
+
on: (type: string, handler: (payload: unknown) => void) => () => void;
|
|
7
|
+
};
|
|
8
|
+
/** 点击 Section 事件 */
|
|
9
|
+
onSectionClick?: (sectionId: string) => void;
|
|
10
|
+
/** Hover Section 事件 */
|
|
11
|
+
onSectionHover?: (sectionId: string | null) => void;
|
|
12
|
+
/** 内容渲染完成 */
|
|
13
|
+
onContentReady?: () => void;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* 创建并挂载 Preview App
|
|
17
|
+
* 在 preview-host 的 main.ts 中调用
|
|
18
|
+
*/
|
|
19
|
+
export declare function createPreviewApp(selector: string, options: PreviewAppOptions): void;
|
|
20
|
+
export {};
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { detectUndoRedo, isEditableTarget, isModKey } from "@vigilkids/section-core";
|
|
2
|
+
import { createApp, h, provide, ref } from "vue";
|
|
3
|
+
import { SectionRendererPlugin } from "../plugin.mjs";
|
|
4
|
+
import SectionRenderer from "../renderer/SectionRenderer.vue";
|
|
5
|
+
const loadedProducts = /* @__PURE__ */ new Set();
|
|
6
|
+
const productCSSLoaders = {
|
|
7
|
+
vigilkids: () => import("../styles/products/vigilkids.css"),
|
|
8
|
+
visiva: () => import("../styles/products/visiva.css")
|
|
9
|
+
};
|
|
10
|
+
async function loadProductCSS(productCode) {
|
|
11
|
+
if (loadedProducts.has(productCode)) return;
|
|
12
|
+
const loader = productCSSLoaders[productCode];
|
|
13
|
+
if (loader) {
|
|
14
|
+
await loader();
|
|
15
|
+
loadedProducts.add(productCode);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
export function createPreviewApp(selector, options) {
|
|
19
|
+
const sectionsData = ref({
|
|
20
|
+
sections: {},
|
|
21
|
+
section_order: []
|
|
22
|
+
});
|
|
23
|
+
const selectedSectionId = ref(null);
|
|
24
|
+
const allSectionsSelected = ref(false);
|
|
25
|
+
const rawHtmlContent = ref(null);
|
|
26
|
+
const currentProduct = ref("");
|
|
27
|
+
const inlineEditingField = ref(null);
|
|
28
|
+
const app = createApp({
|
|
29
|
+
setup() {
|
|
30
|
+
provide("currentProduct", currentProduct);
|
|
31
|
+
options.bridge.on("sections:update", (payload) => {
|
|
32
|
+
rawHtmlContent.value = null;
|
|
33
|
+
const data = payload;
|
|
34
|
+
if (inlineEditingField.value) {
|
|
35
|
+
const { sectionId, key } = inlineEditingField.value;
|
|
36
|
+
const currentSection = sectionsData.value.sections[sectionId];
|
|
37
|
+
if (currentSection && data.sections[sectionId]) {
|
|
38
|
+
data.sections[sectionId].settings[key] = currentSection.settings[key];
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
sectionsData.value = data;
|
|
42
|
+
});
|
|
43
|
+
options.bridge.on("html:preview", (payload) => {
|
|
44
|
+
const data = payload;
|
|
45
|
+
rawHtmlContent.value = data.html;
|
|
46
|
+
});
|
|
47
|
+
options.bridge.on("section:select", (payload) => {
|
|
48
|
+
const data = payload;
|
|
49
|
+
selectedSectionId.value = data.sectionId;
|
|
50
|
+
let attempts = 0;
|
|
51
|
+
const tryScroll = () => {
|
|
52
|
+
const el = document.getElementById(`section-${data.sectionId}`);
|
|
53
|
+
if (el) {
|
|
54
|
+
el.scrollIntoView({ behavior: "smooth", block: "center" });
|
|
55
|
+
} else if (attempts++ < 30) {
|
|
56
|
+
requestAnimationFrame(tryScroll);
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
requestAnimationFrame(tryScroll);
|
|
60
|
+
});
|
|
61
|
+
options.bridge.on("section:deselect", () => {
|
|
62
|
+
selectedSectionId.value = null;
|
|
63
|
+
allSectionsSelected.value = false;
|
|
64
|
+
});
|
|
65
|
+
options.bridge.on("section:select-all", () => {
|
|
66
|
+
selectedSectionId.value = null;
|
|
67
|
+
allSectionsSelected.value = true;
|
|
68
|
+
});
|
|
69
|
+
options.bridge.on("preview:ping", () => {
|
|
70
|
+
options.bridge.send({ type: "preview:pong" });
|
|
71
|
+
});
|
|
72
|
+
options.bridge.on("theme:change", (payload) => {
|
|
73
|
+
const data = payload;
|
|
74
|
+
const root = document.documentElement;
|
|
75
|
+
for (const [key, value] of Object.entries(data.tokens)) {
|
|
76
|
+
root.style.setProperty(key, value);
|
|
77
|
+
}
|
|
78
|
+
if (data.productCode) {
|
|
79
|
+
currentProduct.value = data.productCode;
|
|
80
|
+
loadProductCSS(data.productCode);
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
function handleSectionClick(sectionId) {
|
|
84
|
+
options.onSectionClick?.(sectionId);
|
|
85
|
+
}
|
|
86
|
+
return () => rawHtmlContent.value !== null ? h("div", {
|
|
87
|
+
class: `article-content article-content--${currentProduct.value || "vigilkids"}`,
|
|
88
|
+
innerHTML: rawHtmlContent.value
|
|
89
|
+
}) : h(SectionRenderer, {
|
|
90
|
+
sectionsData: sectionsData.value,
|
|
91
|
+
editorMode: true,
|
|
92
|
+
selectedSectionId: selectedSectionId.value,
|
|
93
|
+
allSectionsSelected: allSectionsSelected.value,
|
|
94
|
+
productCode: currentProduct.value || void 0,
|
|
95
|
+
onSectionClick: handleSectionClick,
|
|
96
|
+
onSettingUpdate: (sectionId, key, value) => {
|
|
97
|
+
options.bridge.send({ type: "inline-edit:update", payload: { sectionId, key, value } });
|
|
98
|
+
},
|
|
99
|
+
onBlockSettingUpdate: (sectionId, blockId, key, value) => {
|
|
100
|
+
options.bridge.send({ type: "inline-edit:block-update", payload: { sectionId, blockId, key, value } });
|
|
101
|
+
},
|
|
102
|
+
onInlineEditStart: (sectionId, key) => {
|
|
103
|
+
inlineEditingField.value = { sectionId, key };
|
|
104
|
+
options.bridge.send({ type: "inline-edit:start", payload: { sectionId, key } });
|
|
105
|
+
},
|
|
106
|
+
onInlineEditEnd: () => {
|
|
107
|
+
inlineEditingField.value = null;
|
|
108
|
+
options.bridge.send({ type: "inline-edit:end" });
|
|
109
|
+
},
|
|
110
|
+
onInlineEditUndoRedo: (action) => {
|
|
111
|
+
options.bridge.send({ type: action === "undo" ? "shortcut:undo" : "shortcut:redo" });
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
app.use(SectionRendererPlugin);
|
|
117
|
+
app.mount(selector);
|
|
118
|
+
document.addEventListener("keydown", (e) => {
|
|
119
|
+
if (isEditableTarget(e)) return;
|
|
120
|
+
const undoRedoAction = detectUndoRedo(e);
|
|
121
|
+
if (undoRedoAction) {
|
|
122
|
+
e.preventDefault();
|
|
123
|
+
options.bridge.send({ type: undoRedoAction === "undo" ? "shortcut:undo" : "shortcut:redo" });
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
if (isModKey(e)) {
|
|
127
|
+
const key = e.key.toLowerCase();
|
|
128
|
+
const modShortcuts = {
|
|
129
|
+
c: "shortcut:copy",
|
|
130
|
+
v: "shortcut:paste",
|
|
131
|
+
a: "shortcut:select-all"
|
|
132
|
+
};
|
|
133
|
+
const mapped = modShortcuts[key];
|
|
134
|
+
if (mapped) {
|
|
135
|
+
e.preventDefault();
|
|
136
|
+
options.bridge.send({ type: mapped });
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
if (e.altKey && e.key === "ArrowUp") {
|
|
141
|
+
e.preventDefault();
|
|
142
|
+
options.bridge.send({ type: "shortcut:move-up" });
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
if (e.altKey && e.key === "ArrowDown") {
|
|
146
|
+
e.preventDefault();
|
|
147
|
+
options.bridge.send({ type: "shortcut:move-down" });
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
if (e.key === "Escape") {
|
|
151
|
+
options.bridge.send({ type: "shortcut:escape" });
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
if (e.key === "Delete") {
|
|
155
|
+
options.bridge.send({ type: "shortcut:delete" });
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
options.onContentReady?.();
|
|
159
|
+
options.bridge.send({ type: "preview:ready" });
|
|
160
|
+
options.bridge.send({ type: "preview:styles-ready" });
|
|
161
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
type __VLS_Props = {
|
|
2
|
+
blockOrder?: string[];
|
|
3
|
+
blocks?: Record<string, unknown>;
|
|
4
|
+
editorMode?: boolean;
|
|
5
|
+
settings?: Record<string, unknown>;
|
|
6
|
+
};
|
|
7
|
+
declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
8
|
+
export default _default;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
defineProps<{
|
|
3
|
+
blockOrder?: string[]
|
|
4
|
+
blocks?: Record<string, unknown>
|
|
5
|
+
editorMode?: boolean
|
|
6
|
+
settings?: Record<string, unknown>
|
|
7
|
+
}>()
|
|
8
|
+
</script>
|
|
9
|
+
|
|
10
|
+
<template>
|
|
11
|
+
<div class="flex items-center justify-center rounded border border-dashed border-gray-300 bg-gray-50 p-8 text-gray-400">
|
|
12
|
+
<div class="text-center">
|
|
13
|
+
<div class="mb-2 text-2xl">📦</div>
|
|
14
|
+
<p class="text-sm">组件加载中...</p>
|
|
15
|
+
</div>
|
|
16
|
+
</div>
|
|
17
|
+
</template>
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
type __VLS_Props = {
|
|
2
|
+
blockOrder?: string[];
|
|
3
|
+
blocks?: Record<string, unknown>;
|
|
4
|
+
editorMode?: boolean;
|
|
5
|
+
settings?: Record<string, unknown>;
|
|
6
|
+
};
|
|
7
|
+
declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
8
|
+
export default _default;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
declare const _default: import("vue").DefineComponent<{
|
|
2
|
+
/** Block 实例映射 */
|
|
3
|
+
blocks: Record<string, {
|
|
4
|
+
type: string;
|
|
5
|
+
settings: Record<string, unknown>;
|
|
6
|
+
}>;
|
|
7
|
+
/** Block 排序 */
|
|
8
|
+
blockOrder: string[];
|
|
9
|
+
/** 编辑器模式 */
|
|
10
|
+
editorMode?: boolean;
|
|
11
|
+
/** 是否选中 */
|
|
12
|
+
isSelected?: boolean;
|
|
13
|
+
/** 产品标识,用于解析产品级 Section 组件覆盖 */
|
|
14
|
+
productCode?: string;
|
|
15
|
+
/** IntersectionObserver rootMargin,控制提前加载距离 */
|
|
16
|
+
rootMargin?: string;
|
|
17
|
+
/** Section ID */
|
|
18
|
+
sectionId: string;
|
|
19
|
+
/** Section 类型 */
|
|
20
|
+
sectionType: string;
|
|
21
|
+
/** Section 设置 */
|
|
22
|
+
settings: Record<string, unknown>;
|
|
23
|
+
}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
24
|
+
inlineEditEnd: () => any;
|
|
25
|
+
sectionClick: (sectionId: string) => any;
|
|
26
|
+
inlineEditUndoRedo: (action: "redo" | "undo") => any;
|
|
27
|
+
inlineEditStart: (sectionId: string, key: string) => any;
|
|
28
|
+
blockSettingUpdate: (sectionId: string, blockId: string, key: string, value: unknown) => any;
|
|
29
|
+
settingUpdate: (sectionId: string, key: string, value: unknown) => any;
|
|
30
|
+
}, string, import("vue").PublicProps, Readonly<{
|
|
31
|
+
/** Block 实例映射 */
|
|
32
|
+
blocks: Record<string, {
|
|
33
|
+
type: string;
|
|
34
|
+
settings: Record<string, unknown>;
|
|
35
|
+
}>;
|
|
36
|
+
/** Block 排序 */
|
|
37
|
+
blockOrder: string[];
|
|
38
|
+
/** 编辑器模式 */
|
|
39
|
+
editorMode?: boolean;
|
|
40
|
+
/** 是否选中 */
|
|
41
|
+
isSelected?: boolean;
|
|
42
|
+
/** 产品标识,用于解析产品级 Section 组件覆盖 */
|
|
43
|
+
productCode?: string;
|
|
44
|
+
/** IntersectionObserver rootMargin,控制提前加载距离 */
|
|
45
|
+
rootMargin?: string;
|
|
46
|
+
/** Section ID */
|
|
47
|
+
sectionId: string;
|
|
48
|
+
/** Section 类型 */
|
|
49
|
+
sectionType: string;
|
|
50
|
+
/** Section 设置 */
|
|
51
|
+
settings: Record<string, unknown>;
|
|
52
|
+
}> & Readonly<{
|
|
53
|
+
onInlineEditEnd?: (() => any) | undefined;
|
|
54
|
+
onSectionClick?: ((sectionId: string) => any) | undefined;
|
|
55
|
+
onInlineEditUndoRedo?: ((action: "redo" | "undo") => any) | undefined;
|
|
56
|
+
onInlineEditStart?: ((sectionId: string, key: string) => any) | undefined;
|
|
57
|
+
onBlockSettingUpdate?: ((sectionId: string, blockId: string, key: string, value: unknown) => any) | undefined;
|
|
58
|
+
onSettingUpdate?: ((sectionId: string, key: string, value: unknown) => any) | undefined;
|
|
59
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
60
|
+
export default _default;
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
/** 根据 Section 类型返回占位高度,防止 CLS 布局偏移 */
|
|
3
|
+
function getPlaceholderHeight(type: string): string {
|
|
4
|
+
const heights: Record<string, string> = {
|
|
5
|
+
'hero-banner': '400px',
|
|
6
|
+
'feature-grid': '300px',
|
|
7
|
+
'text-with-image': '250px',
|
|
8
|
+
'testimonials': '280px',
|
|
9
|
+
'faq': '200px',
|
|
10
|
+
'cta': '180px',
|
|
11
|
+
'rich-text': '200px',
|
|
12
|
+
'spacer': '40px',
|
|
13
|
+
}
|
|
14
|
+
return heights[type] ?? '200px'
|
|
15
|
+
}
|
|
16
|
+
</script>
|
|
17
|
+
|
|
18
|
+
<script setup lang="ts">
|
|
19
|
+
import { computed, ref } from 'vue'
|
|
20
|
+
|
|
21
|
+
import { useLazyRender } from '../composables/useLazyRender'
|
|
22
|
+
import { useRegistry } from '../composables/useRegistry'
|
|
23
|
+
import FallbackSection from './FallbackSection.vue'
|
|
24
|
+
import SectionErrorBoundary from './SectionErrorBoundary.vue'
|
|
25
|
+
import SectionWrapper from './SectionWrapper.vue'
|
|
26
|
+
|
|
27
|
+
const props = defineProps<{
|
|
28
|
+
/** Block 实例映射 */
|
|
29
|
+
blocks: Record<string, { type: string; settings: Record<string, unknown> }>
|
|
30
|
+
/** Block 排序 */
|
|
31
|
+
blockOrder: string[]
|
|
32
|
+
/** 编辑器模式 */
|
|
33
|
+
editorMode?: boolean
|
|
34
|
+
/** 是否选中 */
|
|
35
|
+
isSelected?: boolean
|
|
36
|
+
/** 产品标识,用于解析产品级 Section 组件覆盖 */
|
|
37
|
+
productCode?: string
|
|
38
|
+
/** IntersectionObserver rootMargin,控制提前加载距离 */
|
|
39
|
+
rootMargin?: string
|
|
40
|
+
/** Section ID */
|
|
41
|
+
sectionId: string
|
|
42
|
+
/** Section 类型 */
|
|
43
|
+
sectionType: string
|
|
44
|
+
/** Section 设置 */
|
|
45
|
+
settings: Record<string, unknown>
|
|
46
|
+
}>()
|
|
47
|
+
|
|
48
|
+
const emit = defineEmits<{
|
|
49
|
+
(e: 'sectionClick', sectionId: string): void
|
|
50
|
+
(e: 'settingUpdate', sectionId: string, key: string, value: unknown): void
|
|
51
|
+
(e: 'blockSettingUpdate', sectionId: string, blockId: string, key: string, value: unknown): void
|
|
52
|
+
(e: 'inlineEditStart', sectionId: string, key: string): void
|
|
53
|
+
(e: 'inlineEditEnd'): void
|
|
54
|
+
(e: 'inlineEditUndoRedo', action: 'redo' | 'undo'): void
|
|
55
|
+
}>()
|
|
56
|
+
|
|
57
|
+
const containerRef = ref<HTMLElement | null>(null)
|
|
58
|
+
const { isVisible } = useLazyRender(containerRef, {
|
|
59
|
+
rootMargin: props.rootMargin ?? '200px',
|
|
60
|
+
// SSR 输出完整 HTML,客户端 hydration 后再由 Observer 接管
|
|
61
|
+
ssrEager: true,
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
const registry = useRegistry()
|
|
65
|
+
|
|
66
|
+
// 解析注册表中的组件,未注册则降级到 FallbackSection
|
|
67
|
+
const resolvedComponent = computed(() =>
|
|
68
|
+
registry.resolve(props.sectionType, props.productCode) ?? FallbackSection,
|
|
69
|
+
)
|
|
70
|
+
</script>
|
|
71
|
+
|
|
72
|
+
<template>
|
|
73
|
+
<div ref="containerRef">
|
|
74
|
+
<template v-if="isVisible || isSelected">
|
|
75
|
+
<SectionErrorBoundary
|
|
76
|
+
:section-id="sectionId"
|
|
77
|
+
:section-type="sectionType"
|
|
78
|
+
>
|
|
79
|
+
<SectionWrapper
|
|
80
|
+
:section-id="sectionId"
|
|
81
|
+
:section-type="sectionType"
|
|
82
|
+
:editor-mode="editorMode"
|
|
83
|
+
:is-selected="isSelected"
|
|
84
|
+
:settings="settings"
|
|
85
|
+
@click="emit('sectionClick', sectionId)"
|
|
86
|
+
>
|
|
87
|
+
<component
|
|
88
|
+
:is="resolvedComponent"
|
|
89
|
+
:settings="settings"
|
|
90
|
+
:blocks="blocks"
|
|
91
|
+
:block-order="blockOrder"
|
|
92
|
+
:editor-mode="editorMode"
|
|
93
|
+
@update:setting="(key: string, value: unknown) => emit('settingUpdate', sectionId, key, value)"
|
|
94
|
+
@update:block-setting="(blockId: string, key: string, value: unknown) => emit('blockSettingUpdate', sectionId, blockId, key, value)"
|
|
95
|
+
@inline-edit-start="(key: string) => emit('inlineEditStart', sectionId, key)"
|
|
96
|
+
@inline-edit-end="emit('inlineEditEnd')"
|
|
97
|
+
@undo-redo="(action: 'redo' | 'undo') => emit('inlineEditUndoRedo', action)"
|
|
98
|
+
/>
|
|
99
|
+
</SectionWrapper>
|
|
100
|
+
</SectionErrorBoundary>
|
|
101
|
+
</template>
|
|
102
|
+
|
|
103
|
+
<!-- CLS 占位:未加载时保持最小高度,防止内容加载后布局偏移 -->
|
|
104
|
+
<div
|
|
105
|
+
v-else
|
|
106
|
+
class="section-lazy-placeholder"
|
|
107
|
+
:data-section-type="sectionType"
|
|
108
|
+
:style="{ minHeight: getPlaceholderHeight(sectionType) }"
|
|
109
|
+
/>
|
|
110
|
+
</div>
|
|
111
|
+
</template>
|
|
112
|
+
|
|
113
|
+
<style scoped>
|
|
114
|
+
.section-lazy-placeholder{animation:shimmer 1.5s infinite;background:linear-gradient(90deg,#f3f4f6 25%,#e5e7eb 50%,#f3f4f6 75%);background-size:200% 100%;border-radius:4px}@keyframes shimmer{0%{background-position:-200% 0}to{background-position:200% 0}}
|
|
115
|
+
</style>
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
declare const _default: import("vue").DefineComponent<{
|
|
2
|
+
/** Block 实例映射 */
|
|
3
|
+
blocks: Record<string, {
|
|
4
|
+
type: string;
|
|
5
|
+
settings: Record<string, unknown>;
|
|
6
|
+
}>;
|
|
7
|
+
/** Block 排序 */
|
|
8
|
+
blockOrder: string[];
|
|
9
|
+
/** 编辑器模式 */
|
|
10
|
+
editorMode?: boolean;
|
|
11
|
+
/** 是否选中 */
|
|
12
|
+
isSelected?: boolean;
|
|
13
|
+
/** 产品标识,用于解析产品级 Section 组件覆盖 */
|
|
14
|
+
productCode?: string;
|
|
15
|
+
/** IntersectionObserver rootMargin,控制提前加载距离 */
|
|
16
|
+
rootMargin?: string;
|
|
17
|
+
/** Section ID */
|
|
18
|
+
sectionId: string;
|
|
19
|
+
/** Section 类型 */
|
|
20
|
+
sectionType: string;
|
|
21
|
+
/** Section 设置 */
|
|
22
|
+
settings: Record<string, unknown>;
|
|
23
|
+
}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
24
|
+
inlineEditEnd: () => any;
|
|
25
|
+
sectionClick: (sectionId: string) => any;
|
|
26
|
+
inlineEditUndoRedo: (action: "redo" | "undo") => any;
|
|
27
|
+
inlineEditStart: (sectionId: string, key: string) => any;
|
|
28
|
+
blockSettingUpdate: (sectionId: string, blockId: string, key: string, value: unknown) => any;
|
|
29
|
+
settingUpdate: (sectionId: string, key: string, value: unknown) => any;
|
|
30
|
+
}, string, import("vue").PublicProps, Readonly<{
|
|
31
|
+
/** Block 实例映射 */
|
|
32
|
+
blocks: Record<string, {
|
|
33
|
+
type: string;
|
|
34
|
+
settings: Record<string, unknown>;
|
|
35
|
+
}>;
|
|
36
|
+
/** Block 排序 */
|
|
37
|
+
blockOrder: string[];
|
|
38
|
+
/** 编辑器模式 */
|
|
39
|
+
editorMode?: boolean;
|
|
40
|
+
/** 是否选中 */
|
|
41
|
+
isSelected?: boolean;
|
|
42
|
+
/** 产品标识,用于解析产品级 Section 组件覆盖 */
|
|
43
|
+
productCode?: string;
|
|
44
|
+
/** IntersectionObserver rootMargin,控制提前加载距离 */
|
|
45
|
+
rootMargin?: string;
|
|
46
|
+
/** Section ID */
|
|
47
|
+
sectionId: string;
|
|
48
|
+
/** Section 类型 */
|
|
49
|
+
sectionType: string;
|
|
50
|
+
/** Section 设置 */
|
|
51
|
+
settings: Record<string, unknown>;
|
|
52
|
+
}> & Readonly<{
|
|
53
|
+
onInlineEditEnd?: (() => any) | undefined;
|
|
54
|
+
onSectionClick?: ((sectionId: string) => any) | undefined;
|
|
55
|
+
onInlineEditUndoRedo?: ((action: "redo" | "undo") => any) | undefined;
|
|
56
|
+
onInlineEditStart?: ((sectionId: string, key: string) => any) | undefined;
|
|
57
|
+
onBlockSettingUpdate?: ((sectionId: string, blockId: string, key: string, value: unknown) => any) | undefined;
|
|
58
|
+
onSettingUpdate?: ((sectionId: string, key: string, value: unknown) => any) | undefined;
|
|
59
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
60
|
+
export default _default;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
type __VLS_Props = {
|
|
2
|
+
sectionId: string;
|
|
3
|
+
sectionType: string;
|
|
4
|
+
};
|
|
5
|
+
declare var __VLS_1: {};
|
|
6
|
+
type __VLS_Slots = {} & {
|
|
7
|
+
default?: (props: typeof __VLS_1) => any;
|
|
8
|
+
};
|
|
9
|
+
declare const __VLS_component: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
10
|
+
declare const _default: __VLS_WithSlots<typeof __VLS_component, __VLS_Slots>;
|
|
11
|
+
export default _default;
|
|
12
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
13
|
+
new (): {
|
|
14
|
+
$slots: S;
|
|
15
|
+
};
|
|
16
|
+
};
|