@vigilkids/section-renderer-vue 0.2.2 → 0.5.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.
Files changed (71) hide show
  1. package/dist/interactions/vigilkids.d.ts +44 -1
  2. package/dist/interactions/vigilkids.mjs +115 -1
  3. package/dist/sections/article/index.mjs +60 -0
  4. package/dist/sections/article/vigilkids/ArticleFaq.vue +9 -2
  5. package/dist/sections/article/vigilkids/ArticleFaqItem.d.vue.ts +3 -0
  6. package/dist/sections/article/vigilkids/ArticleFaqItem.vue +18 -18
  7. package/dist/sections/article/vigilkids/ArticleFaqItem.vue.d.ts +3 -0
  8. package/dist/sections/article/vigilkids/ArticleHeading.vue +2 -1
  9. package/dist/sections/article/vigilkids/ArticleHighlightParagraph.d.vue.ts +21 -0
  10. package/dist/sections/article/vigilkids/ArticleHighlightParagraph.vue +38 -0
  11. package/dist/sections/article/vigilkids/ArticleHighlightParagraph.vue.d.ts +21 -0
  12. package/dist/sections/article/vigilkids/ArticleProductCard.d.vue.ts +21 -0
  13. package/dist/sections/article/vigilkids/ArticleProductCard.vue +65 -0
  14. package/dist/sections/article/vigilkids/ArticleProductCard.vue.d.ts +21 -0
  15. package/dist/sections/article/vigilkids/ArticleProductInfoBanner.d.vue.ts +21 -0
  16. package/dist/sections/article/vigilkids/ArticleProductInfoBanner.vue +56 -0
  17. package/dist/sections/article/vigilkids/ArticleProductInfoBanner.vue.d.ts +21 -0
  18. package/dist/sections/article/vigilkids/ArticleRelatedArticles.d.vue.ts +21 -0
  19. package/dist/sections/article/vigilkids/ArticleRelatedArticles.vue +86 -0
  20. package/dist/sections/article/vigilkids/ArticleRelatedArticles.vue.d.ts +21 -0
  21. package/dist/sections/article/vigilkids/ArticleRetentionBanner.d.vue.ts +21 -0
  22. package/dist/sections/article/vigilkids/ArticleRetentionBanner.vue +100 -0
  23. package/dist/sections/article/vigilkids/ArticleRetentionBanner.vue.d.ts +21 -0
  24. package/dist/sections/article/vigilkids/ArticleSectionIntro.d.vue.ts +21 -0
  25. package/dist/sections/article/vigilkids/ArticleSectionIntro.vue +56 -0
  26. package/dist/sections/article/vigilkids/ArticleSectionIntro.vue.d.ts +21 -0
  27. package/dist/sections/article/vigilkids/ArticleStepList.vue +11 -6
  28. package/dist/sections/article/vigilkids/ArticleStyledHeading.d.vue.ts +21 -0
  29. package/dist/sections/article/vigilkids/ArticleStyledHeading.vue +48 -0
  30. package/dist/sections/article/vigilkids/ArticleStyledHeading.vue.d.ts +21 -0
  31. package/dist/sections/article/vigilkids/ArticleSubheading.vue +5 -4
  32. package/dist/sections/article/vigilkids/ArticleTable.d.vue.ts +13 -1
  33. package/dist/sections/article/vigilkids/ArticleTable.vue +26 -6
  34. package/dist/sections/article/vigilkids/ArticleTable.vue.d.ts +13 -1
  35. package/dist/sections/article/vigilkids/ArticleTipNote.d.vue.ts +21 -0
  36. package/dist/sections/article/vigilkids/ArticleTipNote.vue +58 -0
  37. package/dist/sections/article/vigilkids/ArticleTipNote.vue.d.ts +21 -0
  38. package/dist/sections/article/vigilkids/ArticleToc.vue +22 -7
  39. package/dist/sections/article/vigilkids/ArticleTocList.d.vue.ts +21 -0
  40. package/dist/sections/article/vigilkids/ArticleTocList.vue +56 -0
  41. package/dist/sections/article/vigilkids/ArticleTocList.vue.d.ts +21 -0
  42. package/dist/sections/article/vigilkids/ArticleTopAd.d.vue.ts +21 -0
  43. package/dist/sections/article/vigilkids/ArticleTopAd.vue +90 -0
  44. package/dist/sections/article/vigilkids/ArticleTopAd.vue.d.ts +21 -0
  45. package/dist/sections/article/vigilkids/product-card/ProductCardCtaGroup.d.vue.ts +6 -0
  46. package/dist/sections/article/vigilkids/product-card/ProductCardCtaGroup.vue +21 -0
  47. package/dist/sections/article/vigilkids/product-card/ProductCardCtaGroup.vue.d.ts +6 -0
  48. package/dist/sections/article/vigilkids/product-card/ProductCardVariantA.d.vue.ts +21 -0
  49. package/dist/sections/article/vigilkids/product-card/ProductCardVariantA.vue +46 -0
  50. package/dist/sections/article/vigilkids/product-card/ProductCardVariantA.vue.d.ts +21 -0
  51. package/dist/sections/article/vigilkids/product-card/ProductCardVariantB.d.vue.ts +21 -0
  52. package/dist/sections/article/vigilkids/product-card/ProductCardVariantB.vue +46 -0
  53. package/dist/sections/article/vigilkids/product-card/ProductCardVariantB.vue.d.ts +21 -0
  54. package/dist/sections/article/vigilkids/product-card/ProductCardVariantC.d.vue.ts +21 -0
  55. package/dist/sections/article/vigilkids/product-card/ProductCardVariantC.vue +46 -0
  56. package/dist/sections/article/vigilkids/product-card/ProductCardVariantC.vue.d.ts +21 -0
  57. package/dist/sections/article/vigilkids/product-card/ProductCardVariantD.d.vue.ts +21 -0
  58. package/dist/sections/article/vigilkids/product-card/ProductCardVariantD.vue +56 -0
  59. package/dist/sections/article/vigilkids/product-card/ProductCardVariantD.vue.d.ts +21 -0
  60. package/dist/sections/article/vigilkids/product-card/ProductCardVariantE.d.vue.ts +21 -0
  61. package/dist/sections/article/vigilkids/product-card/ProductCardVariantE.vue +55 -0
  62. package/dist/sections/article/vigilkids/product-card/ProductCardVariantE.vue.d.ts +21 -0
  63. package/dist/sections/article/vigilkids/product-card/ProductCardVariantF.d.vue.ts +21 -0
  64. package/dist/sections/article/vigilkids/product-card/ProductCardVariantF.vue +56 -0
  65. package/dist/sections/article/vigilkids/product-card/ProductCardVariantF.vue.d.ts +21 -0
  66. package/dist/sections/article/vigilkids/product-card/ProductCardVariantG.d.vue.ts +21 -0
  67. package/dist/sections/article/vigilkids/product-card/ProductCardVariantG.vue +52 -0
  68. package/dist/sections/article/vigilkids/product-card/ProductCardVariantG.vue.d.ts +21 -0
  69. package/dist/styles/products/vigilkids.css +1 -1
  70. package/dist/styles/products/visiva.css +1 -1
  71. package/package.json +4 -1
@@ -0,0 +1,58 @@
1
+ <script setup lang="ts">
2
+ import type { BlockData } from '@vigilkids/section-core'
3
+
4
+ import { computed } from 'vue'
5
+
6
+ import { useInlineEdit } from '../../../composables/useInlineEdit'
7
+
8
+ const props = defineProps<{
9
+ blockOrder: string[]
10
+ blocks: Record<string, BlockData>
11
+ editorMode?: boolean
12
+ settings: Record<string, unknown>
13
+ }>()
14
+
15
+ const emit = defineEmits<{
16
+ (e: 'update:setting', key: string, value: unknown): void
17
+ (e: 'update:block-setting', blockId: string, key: string, value: unknown): void
18
+ (e: 'inline-edit-start', key: string): void
19
+ (e: 'inline-edit-end'): void
20
+ (e: 'undo-redo', action: 'redo' | 'undo'): void
21
+ }>()
22
+
23
+ const s = computed(() => props.settings)
24
+
25
+ const variant = computed(() => String(s.value.variant || 'note'))
26
+
27
+ const containerClass = computed(() => {
28
+ if (variant.value === 'tips')
29
+ return 'tips-box'
30
+ if (variant.value === 'warning')
31
+ return 'note-box note-warning'
32
+ return 'note-box'
33
+ })
34
+
35
+ const labelClass = computed(() => (variant.value === 'tips' ? 'tips-box-label' : 'note-box-label'))
36
+
37
+ const contentClass = computed(() => (variant.value === 'tips' ? 'tips-box-content' : 'note-box-content'))
38
+
39
+ const { editableAttrs } = useInlineEdit({
40
+ editorMode: () => !!props.editorMode,
41
+ onSettingUpdate: (key, value) => emit('update:setting', key, value),
42
+ onBlockSettingUpdate: (blockId, key, value) => emit('update:block-setting', blockId, key, value),
43
+ onEditStart: key => emit('inline-edit-start', key),
44
+ onEditEnd: () => emit('inline-edit-end'),
45
+ onUndoRedo: action => emit('undo-redo', action),
46
+ })
47
+ </script>
48
+
49
+ <template>
50
+ <div :class="containerClass">
51
+ <div :class="labelClass">
52
+ <img v-if="s.icon_url" :src="(s.icon_url as string)" :alt="(s.label_text as string) || ''">
53
+ <span v-bind="editableAttrs('label_text')">{{ s.label_text }}</span>
54
+ </div>
55
+ <!-- eslint-disable-next-line vue/no-v-html -->
56
+ <p :class="contentClass" v-bind="editableAttrs('content')" v-html="s.content" />
57
+ </div>
58
+ </template>
@@ -0,0 +1,21 @@
1
+ import type { BlockData } from '@vigilkids/section-core';
2
+ type __VLS_Props = {
3
+ blockOrder: string[];
4
+ blocks: Record<string, BlockData>;
5
+ editorMode?: boolean;
6
+ settings: Record<string, unknown>;
7
+ };
8
+ declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
9
+ "update:setting": (key: string, value: unknown) => any;
10
+ "update:block-setting": (blockId: string, key: string, value: unknown) => any;
11
+ "inline-edit-start": (key: string) => any;
12
+ "inline-edit-end": () => any;
13
+ "undo-redo": (action: "redo" | "undo") => any;
14
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
15
+ "onUpdate:setting"?: ((key: string, value: unknown) => any) | undefined;
16
+ "onUpdate:block-setting"?: ((blockId: string, key: string, value: unknown) => any) | undefined;
17
+ "onInline-edit-start"?: ((key: string) => any) | undefined;
18
+ "onInline-edit-end"?: (() => any) | undefined;
19
+ "onUndo-redo"?: ((action: "redo" | "undo") => any) | undefined;
20
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
21
+ export default _default;
@@ -28,7 +28,13 @@ const emit = defineEmits<{
28
28
  (e: 'undo-redo', action: 'redo' | 'undo'): void
29
29
  }>()
30
30
 
31
- const title = computed(() => String(props.settings.title || 'Table Of Contents'))
31
+ // 标题允许富文本(例如带 <b>);空值时回退默认文案
32
+ const title = computed(() => {
33
+ const raw = props.settings.title
34
+ if (typeof raw === 'string' && raw.trim() !== '')
35
+ return raw
36
+ return 'Table Of Contents'
37
+ })
32
38
 
33
39
  // 将 blockOrder 中连续的 toc-h3 归组到前一个 toc-h2 下
34
40
  const tocGroups = computed<TocGroup[]>(() => {
@@ -63,7 +69,7 @@ const tocGroups = computed<TocGroup[]>(() => {
63
69
  const hotIconSrc
64
70
  = 'data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMjAgMjAiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTEwLjU0NzkgMTEuOTcwMkMxMC4wOTY2IDExLjk3MDIgOS43MTQ1NiAxMi41Mzg5IDkuNzE0NTYgMTMuMjE4OEM5LjcxNDU2IDEzLjg5NDggMTAuMDk2NiAxNC40NjY4IDEwLjU0NzkgMTQuNDY2OEMxMC45OTkyIDE0LjQ2NjggMTEuMzgxOSAxMy44OTY4IDExLjM4MTkgMTMuMjE3NUMxMS4zODE5IDEyLjUzODkgMTAuOTk5OSAxMS45Njg5IDEwLjU0ODUgMTEuOTY4OUwxMC41NDc5IDExLjk3MDJaTTE1LjM5NzcgMy41NDg0MUMxNS4zMjU4IDMuNDY4MTcgMTUuMjMzOCAzLjQwODQ4IDE1LjEzMTIgMy4zNzU0NUMxNS4wMjg2IDMuMzQyNDIgMTQuOTE5IDMuMzM3MjMgMTQuODEzOCAzLjM2MDQyQzE0LjYwMTggMy40MTEwOCAxNC40MjcxIDMuNTczNzQgMTQuMzQ3MSAzLjc5NTA3QzE0LjE2ODggNC4zMTgxNiAxNC4wMDM2IDQuODQ1NjUgMTMuODUxOCA1LjM3NzA0QzEzLjYzODUgNC45MzQzOCAxMy4zOTg1IDQuNTA5NzIgMTMuMTMxOCA0LjEwMzc0QzEyLjE0NzggMi42MDQ0NCAxMC43OTg1IDEuMzMxOCA4Ljg4NjU3IDAuMDk4NTAzN0M4Ljc5NTYgMC4wMzkxOTE2IDguNjkwMzIgMC4wMDU0NzcyOCA4LjU4MTgyIDAuMDAwOTAyOTA5QzguNDczMzEgLTAuMDAzNjcxNDYgOC4zNjU1OCAwLjAyMTA2MyA4LjI2OTkzIDAuMDcyNTA3NkM4LjE3MTE2IDAuMTI5NTgzIDguMDg3NjcgMC4yMDk3MjMgOC4wMjY2MSAwLjMwNjA3OUM3Ljk2NTU0IDAuNDAyNDM1IDcuOTI4NzEgMC41MTIxNDMgNy45MTkyNyAwLjYyNTgyOEM3LjY1MzI3IDMuMjI5NzMgNy4xNjM5NSA1Ljg2OTAxIDUuNDkyIDcuNzI2OTZMNS4yNzAwMSA3LjI1MzY0QzUuMDc0NyA2Ljg0NDMyIDQuODkyMDIgNi40NTkwMSA0Ljc3NDcgNi4xMjkwMUM0LjY0ODAyIDUuNzY1NjkgNC4yNzY3MSA1LjU4MzcgMy45NDUzOCA1LjcyMjM3QzMuNzkzMSA1Ljc4ODQ4IDMuNjcwOTMgNS45MDg5OCAzLjYwMjcyIDYuMDYwMzRMMy40NjgwNiA2LjM0N0MyLjY0NzQxIDguMDg2OTYgMS41MjU0NCAxMC40NzM2IDEuMzU2MSAxMi40OTE1QzEuMDA0NzcgMTYuNzY4NyA0LjU1NjY5IDE5LjQ1NjcgOC4yNTA1OSAxOS45MDMzQzkuMDYxOTIgMjAuMDAxMyA5Ljg3NzIyIDIwLjAyMzMgMTAuNjkxOSAxOS45NzMzQzEzLjU5NjUgMTkuNzg0IDE3LjEyNSAxOC4xNTU0IDE4LjMxNDMgMTQuMTQ2OEMxOS4wODQzIDExLjU0NDkgMTguNzgzNyA3LjIxMDMyIDE1LjM5NzcgMy41NDcwOFYzLjU0Nzc0VjMuNTQ4NDFaTTcuODI3OTQgMTUuMTUyMUM3LjgyNzk0IDE1LjQ5MDEgNy41NzUyOCAxNS43NjU1IDcuMjY0NjIgMTUuNzY1NUM2Ljk1NDY0IDE1Ljc2NjggNi43MDMyOSAxNS40OTIxIDYuNzAxOTYgMTUuMTUyMVYxMy43NTg4TDUuNTQyIDEzLjc3ODhWMTUuMTg2MUM1LjU0MiAxNS41MjM0IDUuMjg5MzQgMTUuNzk5NCA0Ljk3ODY4IDE1Ljc5OTRDNC42NjkzNiAxNS44MDA4IDQuNDE2NjkgMTUuNTI2MSA0LjQxNTM2IDE1LjE4NjFWMTEuNDE4OUM0LjQxNTM2IDExLjA4MDIgNC42NjczNSAxMC44MDU2IDQuOTc4NjggMTAuODA1NkM1LjI4OTM0IDEwLjgwNTYgNS41NDEzNCAxMS4wODAyIDUuNTQxMzQgMTEuNDE4OVYxMi41NTE1TDYuNzAxOTYgMTIuNTMyMlYxMS4zODU1QzYuNzAxOTYgMTEuMDQ2OSA2Ljk1Mzk1IDEwLjc3MTYgNy4yNjQ2MiAxMC43NzE2QzcuNTc1MjggMTAuNzcxNiA3LjgyNzI3IDExLjA0NjkgNy44MjcyNyAxMS4zODQ5VjE1LjE1MTVINy44Mjc5NFYxNS4xNTIxWk0xMC41NDc5IDE1LjY5MDhDOS40Njc5IDE1LjY5MDggOC41OTA1OSAxNC41ODAxIDguNTkwNTkgMTMuMjE1NUM4LjU5MDU5IDExLjg1MDkgOS40Njc5IDEwLjc0MDIgMTAuNTQ3OSAxMC43NDAyQzExLjYyNzggMTAuNzQwMiAxMi41MDc4IDExLjg1MDkgMTIuNTA3OCAxMy4yMTU1QzEyLjUwNjUgMTQuNTgwMSAxMS42Mjc4IDE1LjY5MDggMTAuNTQ3OSAxNS42OTA4VjE1LjY5MDhaTTE1LjY1MDQgMTIuMTAyMkgxNC45MzUxVjE1LjExODhDMTQuOTM1MSAxNS40NTY4IDE0LjY4MzggMTUuNzMyMSAxNC4zNzMxIDE1LjczMjFDMTQuMDYzMSAxNS43MzM0IDEzLjgxMTEgMTUuNDU4OCAxMy44MDkxIDE1LjExODhWMTIuMTAyMkgxMy4wOTUxQzEzLjAyMDIgMTIuMTAyMiAxMi45NDYxIDEyLjA4NjIgMTIuODc3OCAxMi4wNTUzQzEyLjgwOTUgMTIuMDI0NCAxMi43NDg2IDExLjk3OTIgMTIuNjk5MSAxMS45MjI5QzEyLjU5MzEgMTEuODAyMyAxMi41MzM5IDExLjY0NzUgMTIuNTMyNSAxMS40ODY5QzEyLjUzMjUgMTEuMTQ4MiAxMi43ODQ1IDEwLjg3MzYgMTMuMDk1MSAxMC44NzM2SDE1LjY0ODRDMTUuOTU5MSAxMC44NzM2IDE2LjIxMDQgMTEuMTQ4MiAxNi4yMTA0IDExLjQ4NjlDMTYuMjA5OSAxMS42NDc3IDE2LjE1MDYgMTEuODAyOCAxNi4wNDM3IDExLjkyMjlDMTUuOTk1MSAxMS45Nzk2IDE1LjkzNDggMTIuMDI1MSAxNS44NjY5IDEyLjA1NjJDMTUuNzk5IDEyLjA4NzIgMTUuNzI1MSAxMi4xMDMyIDE1LjY1MDQgMTIuMTAyOVYxMi4xMDIyWiIgZmlsbD0iI0Y3NDM0MyIvPjwvc3ZnPg=='
65
71
 
66
- const { editableAttrs } = useInlineEdit({
72
+ const { editableAttrs, blockEditableAttrs } = useInlineEdit({
67
73
  editorMode: () => !!props.editorMode,
68
74
  onSettingUpdate: (key, value) => emit('update:setting', key, value),
69
75
  onBlockSettingUpdate: (blockId, key, value) => emit('update:block-setting', blockId, key, value),
@@ -75,13 +81,17 @@ const { editableAttrs } = useInlineEdit({
75
81
 
76
82
  <template>
77
83
  <ul class="level-1">
78
- <li class="table-of-contents" v-bind="editableAttrs('title')">
79
- {{ title }}
80
- </li>
84
+ <!-- eslint-disable-next-line vue/no-v-html -->
85
+ <li
86
+ class="table-of-contents"
87
+ v-bind="editableAttrs('title')"
88
+ v-html="title"
89
+ />
81
90
  <template v-for="group in tocGroups" :key="group.id">
82
91
  <li :class="{ 'hot-link': group.hot }">
83
92
  <a :href="`#${group.anchor}`">
84
- {{ group.text }}
93
+ <!-- eslint-disable-next-line vue/no-v-html -->
94
+ <span v-bind="blockEditableAttrs(group.id, 'text')" v-html="group.text" />
85
95
  <img
86
96
  v-if="group.hot"
87
97
  class="hot-icon"
@@ -94,7 +104,12 @@ const { editableAttrs } = useInlineEdit({
94
104
  </li>
95
105
  <ul v-if="group.children.length > 0" class="level-2">
96
106
  <li v-for="child in group.children" :key="child.id">
97
- <a :href="`#${child.anchor}`">{{ child.text }}</a>
107
+ <!-- eslint-disable-next-line vue/no-v-html -->
108
+ <a
109
+ :href="`#${child.anchor}`"
110
+ v-bind="blockEditableAttrs(child.id, 'text')"
111
+ v-html="child.text"
112
+ />
98
113
  </li>
99
114
  </ul>
100
115
  </template>
@@ -0,0 +1,21 @@
1
+ import type { BlockData } from '@vigilkids/section-core';
2
+ type __VLS_Props = {
3
+ blockOrder: string[];
4
+ blocks: Record<string, BlockData>;
5
+ editorMode?: boolean;
6
+ settings: Record<string, unknown>;
7
+ };
8
+ declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
9
+ "update:setting": (key: string, value: unknown) => any;
10
+ "update:block-setting": (blockId: string, key: string, value: unknown) => any;
11
+ "inline-edit-start": (key: string) => any;
12
+ "inline-edit-end": () => any;
13
+ "undo-redo": (action: "redo" | "undo") => any;
14
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
15
+ "onUpdate:setting"?: ((key: string, value: unknown) => any) | undefined;
16
+ "onUpdate:block-setting"?: ((blockId: string, key: string, value: unknown) => any) | undefined;
17
+ "onInline-edit-start"?: ((key: string) => any) | undefined;
18
+ "onInline-edit-end"?: (() => any) | undefined;
19
+ "onUndo-redo"?: ((action: "redo" | "undo") => any) | undefined;
20
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
21
+ export default _default;
@@ -0,0 +1,56 @@
1
+ <script setup lang="ts">
2
+ import type { BlockData } from '@vigilkids/section-core'
3
+
4
+ import { computed } from 'vue'
5
+
6
+ import { useInlineEdit } from '../../../composables/useInlineEdit'
7
+
8
+ const props = defineProps<{
9
+ blockOrder: string[]
10
+ blocks: Record<string, BlockData>
11
+ editorMode?: boolean
12
+ settings: Record<string, unknown>
13
+ }>()
14
+
15
+ const emit = defineEmits<{
16
+ (e: 'update:setting', key: string, value: unknown): void
17
+ (e: 'update:block-setting', blockId: string, key: string, value: unknown): void
18
+ (e: 'inline-edit-start', key: string): void
19
+ (e: 'inline-edit-end'): void
20
+ (e: 'undo-redo', action: 'redo' | 'undo'): void
21
+ }>()
22
+
23
+ const s = computed(() => props.settings)
24
+
25
+ const variant = computed(() => String(s.value.variant || 'dot'))
26
+
27
+ const listClass = computed(() => `toc-list-${variant.value}`)
28
+
29
+ const isOrdered = computed(() => variant.value === 'ordered')
30
+
31
+ const items = computed(() =>
32
+ props.blockOrder
33
+ .filter(id => props.blocks[id]?.type === 'toc_item')
34
+ .map(id => ({ id, block: props.blocks[id]! })),
35
+ )
36
+
37
+ const { blockEditableAttrs } = useInlineEdit({
38
+ editorMode: () => !!props.editorMode,
39
+ onSettingUpdate: (key, value) => emit('update:setting', key, value),
40
+ onBlockSettingUpdate: (blockId, key, value) => emit('update:block-setting', blockId, key, value),
41
+ onEditStart: key => emit('inline-edit-start', key),
42
+ onEditEnd: () => emit('inline-edit-end'),
43
+ onUndoRedo: action => emit('undo-redo', action),
44
+ })
45
+ </script>
46
+
47
+ <template>
48
+ <ol v-if="isOrdered" :class="listClass">
49
+ <!-- eslint-disable-next-line vue/no-v-html -->
50
+ <li v-for="item in items" :key="item.id" v-bind="blockEditableAttrs(item.id, 'text')" v-html="item.block.settings.text" />
51
+ </ol>
52
+ <ul v-else :class="listClass">
53
+ <!-- eslint-disable-next-line vue/no-v-html -->
54
+ <li v-for="item in items" :key="item.id" v-bind="blockEditableAttrs(item.id, 'text')" v-html="item.block.settings.text" />
55
+ </ul>
56
+ </template>
@@ -0,0 +1,21 @@
1
+ import type { BlockData } from '@vigilkids/section-core';
2
+ type __VLS_Props = {
3
+ blockOrder: string[];
4
+ blocks: Record<string, BlockData>;
5
+ editorMode?: boolean;
6
+ settings: Record<string, unknown>;
7
+ };
8
+ declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
9
+ "update:setting": (key: string, value: unknown) => any;
10
+ "update:block-setting": (blockId: string, key: string, value: unknown) => any;
11
+ "inline-edit-start": (key: string) => any;
12
+ "inline-edit-end": () => any;
13
+ "undo-redo": (action: "redo" | "undo") => any;
14
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
15
+ "onUpdate:setting"?: ((key: string, value: unknown) => any) | undefined;
16
+ "onUpdate:block-setting"?: ((blockId: string, key: string, value: unknown) => any) | undefined;
17
+ "onInline-edit-start"?: ((key: string) => any) | undefined;
18
+ "onInline-edit-end"?: (() => any) | undefined;
19
+ "onUndo-redo"?: ((action: "redo" | "undo") => any) | undefined;
20
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
21
+ export default _default;
@@ -0,0 +1,21 @@
1
+ import type { BlockData } from '@vigilkids/section-core';
2
+ type __VLS_Props = {
3
+ blockOrder: string[];
4
+ blocks: Record<string, BlockData>;
5
+ editorMode?: boolean;
6
+ settings: Record<string, unknown>;
7
+ };
8
+ declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
9
+ "update:setting": (key: string, value: unknown) => any;
10
+ "update:block-setting": (blockId: string, key: string, value: unknown) => any;
11
+ "inline-edit-start": (key: string) => any;
12
+ "inline-edit-end": () => any;
13
+ "undo-redo": (action: "redo" | "undo") => any;
14
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
15
+ "onUpdate:setting"?: ((key: string, value: unknown) => any) | undefined;
16
+ "onUpdate:block-setting"?: ((blockId: string, key: string, value: unknown) => any) | undefined;
17
+ "onInline-edit-start"?: ((key: string) => any) | undefined;
18
+ "onInline-edit-end"?: (() => any) | undefined;
19
+ "onUndo-redo"?: ((action: "redo" | "undo") => any) | undefined;
20
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
21
+ export default _default;
@@ -0,0 +1,90 @@
1
+ <script setup lang="ts">
2
+ import type { BlockData } from '@vigilkids/section-core'
3
+
4
+ import { computed } from 'vue'
5
+
6
+ import { useInlineEdit } from '../../../composables/useInlineEdit'
7
+
8
+ const props = defineProps<{
9
+ blockOrder: string[]
10
+ blocks: Record<string, BlockData>
11
+ editorMode?: boolean
12
+ settings: Record<string, unknown>
13
+ }>()
14
+
15
+ const emit = defineEmits<{
16
+ (e: 'update:setting', key: string, value: unknown): void
17
+ (e: 'update:block-setting', blockId: string, key: string, value: unknown): void
18
+ (e: 'inline-edit-start', key: string): void
19
+ (e: 'inline-edit-end'): void
20
+ (e: 'undo-redo', action: 'redo' | 'undo'): void
21
+ }>()
22
+
23
+ const s = computed(() => props.settings)
24
+
25
+ const features = computed(() =>
26
+ props.blockOrder
27
+ .filter(id => props.blocks[id]?.type === 'feature')
28
+ .map(id => ({ id, block: props.blocks[id]! })),
29
+ )
30
+
31
+ const { editableAttrs, blockEditableAttrs } = useInlineEdit({
32
+ editorMode: () => !!props.editorMode,
33
+ onSettingUpdate: (key, value) => emit('update:setting', key, value),
34
+ onBlockSettingUpdate: (blockId, key, value) => emit('update:block-setting', blockId, key, value),
35
+ onEditStart: key => emit('inline-edit-start', key),
36
+ onEditEnd: () => emit('inline-edit-end'),
37
+ onUndoRedo: action => emit('undo-redo', action),
38
+ })
39
+ </script>
40
+
41
+ <template>
42
+ <section class="top-banner">
43
+ <div class="top-banner-info">
44
+ <img
45
+ v-if="s.header_image_url"
46
+ class="top-banner-header"
47
+ :src="(s.header_image_url as string)"
48
+ :alt="(s.header_alt as string) || ''"
49
+ >
50
+ <!-- eslint-disable-next-line vue/no-v-html -->
51
+ <p
52
+ v-if="s.description"
53
+ class="top-banner-desc"
54
+ v-bind="editableAttrs('description')"
55
+ v-html="s.description"
56
+ />
57
+ <ul v-if="features.length" class="top-banner-features">
58
+ <!-- eslint-disable-next-line vue/no-v-html -->
59
+ <li
60
+ v-for="item in features"
61
+ :key="item.id"
62
+ v-bind="blockEditableAttrs(item.id, 'text')"
63
+ v-html="item.block.settings.text"
64
+ />
65
+ </ul>
66
+ <a
67
+ v-if="s.cta_primary_label"
68
+ class="top-banner-btn-primary"
69
+ :href="(s.cta_primary_url as string) || '#'"
70
+ v-bind="editableAttrs('cta_primary_label')"
71
+ >
72
+ {{ s.cta_primary_label }}
73
+ </a>
74
+ <a
75
+ v-if="s.cta_outline_label"
76
+ class="top-banner-btn-outline"
77
+ :href="(s.cta_outline_url as string) || '#'"
78
+ v-bind="editableAttrs('cta_outline_label')"
79
+ >
80
+ {{ s.cta_outline_label }}
81
+ </a>
82
+ </div>
83
+ <img
84
+ v-if="s.mockup_image_url"
85
+ class="top-banner-mockup"
86
+ :src="(s.mockup_image_url as string)"
87
+ :alt="(s.mockup_alt as string) || ''"
88
+ >
89
+ </section>
90
+ </template>
@@ -0,0 +1,21 @@
1
+ import type { BlockData } from '@vigilkids/section-core';
2
+ type __VLS_Props = {
3
+ blockOrder: string[];
4
+ blocks: Record<string, BlockData>;
5
+ editorMode?: boolean;
6
+ settings: Record<string, unknown>;
7
+ };
8
+ declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
9
+ "update:setting": (key: string, value: unknown) => any;
10
+ "update:block-setting": (blockId: string, key: string, value: unknown) => any;
11
+ "inline-edit-start": (key: string) => any;
12
+ "inline-edit-end": () => any;
13
+ "undo-redo": (action: "redo" | "undo") => any;
14
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
15
+ "onUpdate:setting"?: ((key: string, value: unknown) => any) | undefined;
16
+ "onUpdate:block-setting"?: ((blockId: string, key: string, value: unknown) => any) | undefined;
17
+ "onInline-edit-start"?: ((key: string) => any) | undefined;
18
+ "onInline-edit-end"?: (() => any) | undefined;
19
+ "onUndo-redo"?: ((action: "redo" | "undo") => any) | undefined;
20
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
21
+ export default _default;
@@ -0,0 +1,6 @@
1
+ type __VLS_Props = {
2
+ s: Record<string, unknown>;
3
+ editableAttrs: (settingKey: string) => Record<string, unknown>;
4
+ };
5
+ 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>;
6
+ export default _default;
@@ -0,0 +1,21 @@
1
+ <script setup lang="ts">
2
+ // CTA 按钮组:7 个 variant 共用同一套主/次按钮 DOM 结构
3
+ // 通过 props 接收 settings 和 editableAttrs(由父组件内的 useInlineEdit 生成)
4
+ // 拆出此组件是为了消除 v-if 链中的 CTA 重复(原文件有 7 次相同的 action-buttons 块)
5
+ const props = defineProps<{
6
+ s: Record<string, unknown>
7
+ editableAttrs: (settingKey: string) => Record<string, unknown>
8
+ }>()
9
+
10
+ // 解构响应式数据仅用于模板引用简写,不破坏 props 响应性(props 本身是 reactive)
11
+ const { s, editableAttrs } = props
12
+ </script>
13
+
14
+ <template>
15
+ <div class="action-buttons">
16
+ <!-- eslint-disable-next-line vue/no-v-html -->
17
+ <a :href="(s.cta_primary_url as string) || '#'" class="article-btn-primary" v-bind="editableAttrs('cta_primary_label')" v-html="s.cta_primary_label" />
18
+ <!-- eslint-disable-next-line vue/no-v-html -->
19
+ <a :href="(s.cta_outline_url as string) || '#'" class="article-btn-outline" v-bind="editableAttrs('cta_outline_label')" v-html="s.cta_outline_label" />
20
+ </div>
21
+ </template>
@@ -0,0 +1,6 @@
1
+ type __VLS_Props = {
2
+ s: Record<string, unknown>;
3
+ editableAttrs: (settingKey: string) => Record<string, unknown>;
4
+ };
5
+ 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>;
6
+ export default _default;
@@ -0,0 +1,21 @@
1
+ import type { BlockData } from '@vigilkids/section-core';
2
+ type __VLS_Props = {
3
+ blockOrder: string[];
4
+ blocks: Record<string, BlockData>;
5
+ editorMode?: boolean;
6
+ settings: Record<string, unknown>;
7
+ };
8
+ declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
9
+ "update:setting": (key: string, value: unknown) => any;
10
+ "update:block-setting": (blockId: string, key: string, value: unknown) => any;
11
+ "inline-edit-start": (key: string) => any;
12
+ "inline-edit-end": () => any;
13
+ "undo-redo": (action: "redo" | "undo") => any;
14
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
15
+ "onUpdate:setting"?: ((key: string, value: unknown) => any) | undefined;
16
+ "onUpdate:block-setting"?: ((blockId: string, key: string, value: unknown) => any) | undefined;
17
+ "onInline-edit-start"?: ((key: string) => any) | undefined;
18
+ "onInline-edit-end"?: (() => any) | undefined;
19
+ "onUndo-redo"?: ((action: "redo" | "undo") => any) | undefined;
20
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
21
+ export default _default;
@@ -0,0 +1,46 @@
1
+ <script setup lang="ts">
2
+ import type { BlockData } from '@vigilkids/section-core'
3
+
4
+ import { computed } from 'vue'
5
+
6
+ import { useInlineEdit } from '../../../../composables/useInlineEdit'
7
+ import ProductCardCtaGroup from './ProductCardCtaGroup.vue'
8
+
9
+ // Variant A: 无图,标准型(product-card)
10
+ // 契约与主组件对齐:每个 variant 独立完整 emit + useInlineEdit,保证可单独测试/替换
11
+ const props = defineProps<{
12
+ blockOrder: string[]
13
+ blocks: Record<string, BlockData>
14
+ editorMode?: boolean
15
+ settings: Record<string, unknown>
16
+ }>()
17
+
18
+ const emit = defineEmits<{
19
+ (e: 'update:setting', key: string, value: unknown): void
20
+ (e: 'update:block-setting', blockId: string, key: string, value: unknown): void
21
+ (e: 'inline-edit-start', key: string): void
22
+ (e: 'inline-edit-end'): void
23
+ (e: 'undo-redo', action: 'redo' | 'undo'): void
24
+ }>()
25
+
26
+ const s = computed(() => props.settings)
27
+
28
+ const { editableAttrs } = useInlineEdit({
29
+ editorMode: () => !!props.editorMode,
30
+ onSettingUpdate: (key, value) => emit('update:setting', key, value),
31
+ onBlockSettingUpdate: (blockId, key, value) => emit('update:block-setting', blockId, key, value),
32
+ onEditStart: key => emit('inline-edit-start', key),
33
+ onEditEnd: () => emit('inline-edit-end'),
34
+ onUndoRedo: action => emit('undo-redo', action),
35
+ })
36
+ </script>
37
+
38
+ <template>
39
+ <div class="product-card-content">
40
+ <!-- eslint-disable-next-line vue/no-v-html -->
41
+ <p class="product-name" v-bind="editableAttrs('product_name')" v-html="s.product_name" />
42
+ <!-- eslint-disable-next-line vue/no-v-html -->
43
+ <p class="product-desc" v-bind="editableAttrs('product_desc')" v-html="s.product_desc" />
44
+ </div>
45
+ <ProductCardCtaGroup :s="s" :editable-attrs="editableAttrs" />
46
+ </template>
@@ -0,0 +1,21 @@
1
+ import type { BlockData } from '@vigilkids/section-core';
2
+ type __VLS_Props = {
3
+ blockOrder: string[];
4
+ blocks: Record<string, BlockData>;
5
+ editorMode?: boolean;
6
+ settings: Record<string, unknown>;
7
+ };
8
+ declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
9
+ "update:setting": (key: string, value: unknown) => any;
10
+ "update:block-setting": (blockId: string, key: string, value: unknown) => any;
11
+ "inline-edit-start": (key: string) => any;
12
+ "inline-edit-end": () => any;
13
+ "undo-redo": (action: "redo" | "undo") => any;
14
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
15
+ "onUpdate:setting"?: ((key: string, value: unknown) => any) | undefined;
16
+ "onUpdate:block-setting"?: ((blockId: string, key: string, value: unknown) => any) | undefined;
17
+ "onInline-edit-start"?: ((key: string) => any) | undefined;
18
+ "onInline-edit-end"?: (() => any) | undefined;
19
+ "onUndo-redo"?: ((action: "redo" | "undo") => any) | undefined;
20
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
21
+ export default _default;
@@ -0,0 +1,21 @@
1
+ import type { BlockData } from '@vigilkids/section-core';
2
+ type __VLS_Props = {
3
+ blockOrder: string[];
4
+ blocks: Record<string, BlockData>;
5
+ editorMode?: boolean;
6
+ settings: Record<string, unknown>;
7
+ };
8
+ declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
9
+ "update:setting": (key: string, value: unknown) => any;
10
+ "update:block-setting": (blockId: string, key: string, value: unknown) => any;
11
+ "inline-edit-start": (key: string) => any;
12
+ "inline-edit-end": () => any;
13
+ "undo-redo": (action: "redo" | "undo") => any;
14
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
15
+ "onUpdate:setting"?: ((key: string, value: unknown) => any) | undefined;
16
+ "onUpdate:block-setting"?: ((blockId: string, key: string, value: unknown) => any) | undefined;
17
+ "onInline-edit-start"?: ((key: string) => any) | undefined;
18
+ "onInline-edit-end"?: (() => any) | undefined;
19
+ "onUndo-redo"?: ((action: "redo" | "undo") => any) | undefined;
20
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
21
+ export default _default;
@@ -0,0 +1,46 @@
1
+ <script setup lang="ts">
2
+ import type { BlockData } from '@vigilkids/section-core'
3
+
4
+ import { computed } from 'vue'
5
+
6
+ import { useInlineEdit } from '../../../../composables/useInlineEdit'
7
+ import ProductCardCtaGroup from './ProductCardCtaGroup.vue'
8
+
9
+ // Variant B: 无图,紧凑型(product-card-compact)
10
+ // 与 Variant A 的 DOM 相同,区别仅在根 class(由主分发器提供),因此结构对齐
11
+ const props = defineProps<{
12
+ blockOrder: string[]
13
+ blocks: Record<string, BlockData>
14
+ editorMode?: boolean
15
+ settings: Record<string, unknown>
16
+ }>()
17
+
18
+ const emit = defineEmits<{
19
+ (e: 'update:setting', key: string, value: unknown): void
20
+ (e: 'update:block-setting', blockId: string, key: string, value: unknown): void
21
+ (e: 'inline-edit-start', key: string): void
22
+ (e: 'inline-edit-end'): void
23
+ (e: 'undo-redo', action: 'redo' | 'undo'): void
24
+ }>()
25
+
26
+ const s = computed(() => props.settings)
27
+
28
+ const { editableAttrs } = useInlineEdit({
29
+ editorMode: () => !!props.editorMode,
30
+ onSettingUpdate: (key, value) => emit('update:setting', key, value),
31
+ onBlockSettingUpdate: (blockId, key, value) => emit('update:block-setting', blockId, key, value),
32
+ onEditStart: key => emit('inline-edit-start', key),
33
+ onEditEnd: () => emit('inline-edit-end'),
34
+ onUndoRedo: action => emit('undo-redo', action),
35
+ })
36
+ </script>
37
+
38
+ <template>
39
+ <div class="product-card-content">
40
+ <!-- eslint-disable-next-line vue/no-v-html -->
41
+ <p class="product-name" v-bind="editableAttrs('product_name')" v-html="s.product_name" />
42
+ <!-- eslint-disable-next-line vue/no-v-html -->
43
+ <p class="product-desc" v-bind="editableAttrs('product_desc')" v-html="s.product_desc" />
44
+ </div>
45
+ <ProductCardCtaGroup :s="s" :editable-attrs="editableAttrs" />
46
+ </template>
@@ -0,0 +1,21 @@
1
+ import type { BlockData } from '@vigilkids/section-core';
2
+ type __VLS_Props = {
3
+ blockOrder: string[];
4
+ blocks: Record<string, BlockData>;
5
+ editorMode?: boolean;
6
+ settings: Record<string, unknown>;
7
+ };
8
+ declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
9
+ "update:setting": (key: string, value: unknown) => any;
10
+ "update:block-setting": (blockId: string, key: string, value: unknown) => any;
11
+ "inline-edit-start": (key: string) => any;
12
+ "inline-edit-end": () => any;
13
+ "undo-redo": (action: "redo" | "undo") => any;
14
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
15
+ "onUpdate:setting"?: ((key: string, value: unknown) => any) | undefined;
16
+ "onUpdate:block-setting"?: ((blockId: string, key: string, value: unknown) => any) | undefined;
17
+ "onInline-edit-start"?: ((key: string) => any) | undefined;
18
+ "onInline-edit-end"?: (() => any) | undefined;
19
+ "onUndo-redo"?: ((action: "redo" | "undo") => any) | undefined;
20
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
21
+ export default _default;
@@ -0,0 +1,21 @@
1
+ import type { BlockData } from '@vigilkids/section-core';
2
+ type __VLS_Props = {
3
+ blockOrder: string[];
4
+ blocks: Record<string, BlockData>;
5
+ editorMode?: boolean;
6
+ settings: Record<string, unknown>;
7
+ };
8
+ declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
9
+ "update:setting": (key: string, value: unknown) => any;
10
+ "update:block-setting": (blockId: string, key: string, value: unknown) => any;
11
+ "inline-edit-start": (key: string) => any;
12
+ "inline-edit-end": () => any;
13
+ "undo-redo": (action: "redo" | "undo") => any;
14
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
15
+ "onUpdate:setting"?: ((key: string, value: unknown) => any) | undefined;
16
+ "onUpdate:block-setting"?: ((blockId: string, key: string, value: unknown) => any) | undefined;
17
+ "onInline-edit-start"?: ((key: string) => any) | undefined;
18
+ "onInline-edit-end"?: (() => any) | undefined;
19
+ "onUndo-redo"?: ((action: "redo" | "undo") => any) | undefined;
20
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
21
+ export default _default;