@shwfed/config 2.11.1 → 2.11.5

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 (139) hide show
  1. package/dist/mcp.mjs +1592 -1220
  2. package/dist/module.json +1 -1
  3. package/dist/preview/assets/{FieldGroup.vue_vue_type_script_setup_true_lang-CosmpPSu.js → FieldGroup.vue_vue_type_script_setup_true_lang-BK4nj6mF.js} +1 -1
  4. package/dist/preview/assets/{badge-BkYCxTFK.js → badge-Df9KgnrB.js} +1 -1
  5. package/dist/preview/assets/config-B3NwVBxT.js +1 -0
  6. package/dist/preview/assets/{config-Dt8k1gnT.js → config-BrtNnMlJ.js} +1 -1
  7. package/dist/preview/assets/{config-Cbp7aAAw.js → config-CUJNegvX.js} +1 -1
  8. package/dist/preview/assets/{config-C_Ia1CDq.js → config-ChrXUmKf.js} +1 -1
  9. package/dist/preview/assets/{config-B62b9dMF.js → config-CmEXMpIU.js} +1 -1
  10. package/dist/preview/assets/{config-Dk9OegYx.js → config-CrBoFiYB.js} +1 -1
  11. package/dist/preview/assets/{config-74YmXQsH.js → config-D-Hf0dls.js} +1 -1
  12. package/dist/preview/assets/{config-Bt6--diX.js → config-D4cXwy75.js} +1 -1
  13. package/dist/preview/assets/{config-BcZe-bR9.js → config-DCj5Qyiq.js} +1 -1
  14. package/dist/preview/assets/{config-sCP15_0f.js → config-DPfx03nM.js} +1 -1
  15. package/dist/preview/assets/{config-Bbbyd5lB.js → config-DWF0bcmF.js} +1 -1
  16. package/dist/preview/assets/{config-CPsd0ppi.js → config-Do4K9hI7.js} +1 -1
  17. package/dist/preview/assets/config-DwblM1r8.js +1 -0
  18. package/dist/preview/assets/{config-CYVafGLc.js → config-MW5Hs8yE.js} +1 -1
  19. package/dist/preview/assets/{config-COr2MFhN.js → config-uNoNEc-1.js} +1 -1
  20. package/dist/preview/assets/{definition.vue_vue_type_script_setup_true_lang-C3NiB99t.js → definition.vue_vue_type_script_setup_true_lang-CbtpddWK.js} +1 -1
  21. package/dist/preview/assets/index-Bm7I4Tr0.css +1 -0
  22. package/dist/preview/assets/{index-DjG-VVR4.js → index-CkyV576r.js} +217 -205
  23. package/dist/preview/assets/{index-BMOizF8g.js → index-CtW2E0ME.js} +1 -1
  24. package/dist/preview/assets/index-xDmBF3zO.js +1 -0
  25. package/dist/preview/assets/{item-C1efxuFt.js → item-D0e9Cx1Q.js} +1 -1
  26. package/dist/preview/assets/{runtime-Du0ghzR2.js → runtime-3tGIbclh.js} +1 -1
  27. package/dist/preview/assets/{runtime-7z9N9JGG.js → runtime-BCePD3XR.js} +1 -1
  28. package/dist/preview/assets/runtime-BMyFUaSM.js +1 -0
  29. package/dist/preview/assets/runtime-BXZU3EqA.js +1 -0
  30. package/dist/preview/assets/{runtime-LgZuN2Tf.js → runtime-BySNFNSO.js} +1 -1
  31. package/dist/preview/assets/{runtime-Dz7SCudL.js → runtime-CI02gDFj.js} +1 -1
  32. package/dist/preview/assets/{runtime-DoLpKFu-.js → runtime-DCo1Qp8a.js} +1 -1
  33. package/dist/preview/assets/runtime-DDSKV70N.js +1 -0
  34. package/dist/preview/assets/runtime-Dc7pytUy.js +1 -0
  35. package/dist/preview/assets/{runtime-S9eZ2nJS.js → runtime-ckLrkTMm.js} +1 -1
  36. package/dist/preview/assets/runtime-y4oJ8VkY.js +1 -0
  37. package/dist/preview/assets/{schema-meta-CYKPEnu9.js → schema-meta-D0y0sKal.js} +1 -1
  38. package/dist/preview/index.html +2 -2
  39. package/dist/runtime/components/actions/buttons/2026-06-25/com.shwfed.actions.button.state.write/config.d.vue.ts +39 -0
  40. package/dist/runtime/components/actions/buttons/2026-06-25/com.shwfed.actions.button.state.write/config.vue +127 -0
  41. package/dist/runtime/components/actions/buttons/2026-06-25/com.shwfed.actions.button.state.write/config.vue.d.ts +39 -0
  42. package/dist/runtime/components/actions/buttons/2026-06-25/com.shwfed.actions.button.state.write/runtime.d.vue.ts +8 -0
  43. package/dist/runtime/components/actions/buttons/2026-06-25/com.shwfed.actions.button.state.write/runtime.vue +62 -0
  44. package/dist/runtime/components/actions/buttons/2026-06-25/com.shwfed.actions.button.state.write/runtime.vue.d.ts +8 -0
  45. package/dist/runtime/components/actions/buttons/2026-06-25/com.shwfed.actions.button.state.write/schema.d.ts +25 -0
  46. package/dist/runtime/components/actions/buttons/2026-06-25/com.shwfed.actions.button.state.write/schema.js +41 -0
  47. package/dist/runtime/components/config/blocks/2026-06-17/com.shwfed.block.tree.single/runtime.vue +5 -22
  48. package/dist/runtime/components/config/blocks/2026-06-25/com.shwfed.block.loop/config.d.vue.ts +70 -0
  49. package/dist/runtime/components/config/blocks/2026-06-25/com.shwfed.block.loop/config.vue +349 -0
  50. package/dist/runtime/components/config/blocks/2026-06-25/com.shwfed.block.loop/config.vue.d.ts +70 -0
  51. package/dist/runtime/components/config/blocks/2026-06-25/com.shwfed.block.loop/loop-item.d.vue.ts +33 -0
  52. package/dist/runtime/components/config/blocks/2026-06-25/com.shwfed.block.loop/loop-item.vue +37 -0
  53. package/dist/runtime/components/config/blocks/2026-06-25/com.shwfed.block.loop/loop-item.vue.d.ts +33 -0
  54. package/dist/runtime/components/config/blocks/2026-06-25/com.shwfed.block.loop/loop-scope-provider.d.vue.ts +13 -0
  55. package/dist/runtime/components/config/blocks/2026-06-25/com.shwfed.block.loop/loop-scope-provider.vue +22 -0
  56. package/dist/runtime/components/config/blocks/2026-06-25/com.shwfed.block.loop/loop-scope-provider.vue.d.ts +13 -0
  57. package/dist/runtime/components/config/blocks/2026-06-25/com.shwfed.block.loop/runtime.d.vue.ts +70 -0
  58. package/dist/runtime/components/config/blocks/2026-06-25/com.shwfed.block.loop/runtime.vue +62 -0
  59. package/dist/runtime/components/config/blocks/2026-06-25/com.shwfed.block.loop/runtime.vue.d.ts +70 -0
  60. package/dist/runtime/components/config/blocks/2026-06-25/com.shwfed.block.loop/schema.d.ts +85 -0
  61. package/dist/runtime/components/config/blocks/2026-06-25/com.shwfed.block.loop/schema.js +60 -0
  62. package/dist/runtime/components/form/fields/2026-04-22/com.shwfed.form.field.textarea/config.d.vue.ts +2 -2
  63. package/dist/runtime/components/form/fields/2026-04-22/com.shwfed.form.field.textarea/config.vue.d.ts +2 -2
  64. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.daterange/config.d.vue.ts +4 -4
  65. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.daterange/config.vue.d.ts +4 -4
  66. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.datetimerange/config.d.vue.ts +6 -6
  67. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.datetimerange/config.vue.d.ts +6 -6
  68. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.timerange/config.d.vue.ts +2 -2
  69. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.timerange/config.vue.d.ts +2 -2
  70. package/dist/runtime/components/form/fields/2026-05-23/com.shwfed.form.field.tree.multi/config.d.vue.ts +22 -22
  71. package/dist/runtime/components/form/fields/2026-05-23/com.shwfed.form.field.tree.multi/config.vue.d.ts +22 -22
  72. package/dist/runtime/components/form/fields/2026-05-24/com.shwfed.form.field.monthrange/config.d.vue.ts +4 -4
  73. package/dist/runtime/components/form/fields/2026-05-24/com.shwfed.form.field.monthrange/config.vue.d.ts +4 -4
  74. package/dist/runtime/components/form/fields/2026-05-26/com.shwfed.form.field.tree.combobox.multi/config.d.vue.ts +22 -22
  75. package/dist/runtime/components/form/fields/2026-05-26/com.shwfed.form.field.tree.combobox.multi/config.vue.d.ts +22 -22
  76. package/dist/runtime/components/form/fields/2026-05-26/com.shwfed.form.field.tree.combobox.single/config.d.vue.ts +22 -22
  77. package/dist/runtime/components/form/fields/2026-05-26/com.shwfed.form.field.tree.combobox.single/config.vue.d.ts +22 -22
  78. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.multi/config.d.vue.ts +22 -22
  79. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.multi/config.vue.d.ts +22 -22
  80. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.single/config.d.vue.ts +22 -22
  81. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.single/config.vue.d.ts +22 -22
  82. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.multi/config.d.vue.ts +22 -22
  83. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.multi/config.vue.d.ts +22 -22
  84. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.multi/runtime.vue +2 -19
  85. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.single/config.d.vue.ts +22 -22
  86. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.single/config.vue.d.ts +22 -22
  87. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.single/runtime.vue +5 -22
  88. package/dist/runtime/components/operations/2026-06-15/com.shwfed.operation.http.download/config.d.vue.ts +2 -0
  89. package/dist/runtime/components/operations/2026-06-15/com.shwfed.operation.http.download/config.vue +49 -22
  90. package/dist/runtime/components/operations/2026-06-15/com.shwfed.operation.http.download/config.vue.d.ts +2 -0
  91. package/dist/runtime/components/operations/2026-06-15/com.shwfed.operation.http.download/runtime.js +17 -10
  92. package/dist/runtime/components/operations/2026-06-15/com.shwfed.operation.http.download/schema.d.ts +1 -0
  93. package/dist/runtime/components/operations/2026-06-15/com.shwfed.operation.http.download/schema.js +25 -3
  94. package/dist/runtime/components/table/columns/2026-05-24/com.shwfed.table.column.combobox-single.remote.options-remote/config.d.vue.ts +2 -2
  95. package/dist/runtime/components/table/columns/2026-05-24/com.shwfed.table.column.combobox-single.remote.options-remote/config.vue.d.ts +2 -2
  96. package/dist/runtime/components/table/columns/2026-05-24/com.shwfed.table.column.combobox-single.remote.options-static/config.d.vue.ts +2 -2
  97. package/dist/runtime/components/table/columns/2026-05-24/com.shwfed.table.column.combobox-single.remote.options-static/config.vue.d.ts +2 -2
  98. package/dist/runtime/components/table/columns/2026-05-25/com.shwfed.table.column.combobox-multi.remote.options-remote/config.d.vue.ts +2 -2
  99. package/dist/runtime/components/table/columns/2026-05-25/com.shwfed.table.column.combobox-multi.remote.options-remote/config.vue.d.ts +2 -2
  100. package/dist/runtime/components/table/columns/2026-05-25/com.shwfed.table.column.combobox-multi.remote.options-static/config.d.vue.ts +2 -2
  101. package/dist/runtime/components/table/columns/2026-05-25/com.shwfed.table.column.combobox-multi.remote.options-static/config.vue.d.ts +2 -2
  102. package/dist/runtime/components/table/columns/2026-05-26/com.shwfed.table.column.combobox-multi.remote/config.d.vue.ts +2 -2
  103. package/dist/runtime/components/table/columns/2026-05-26/com.shwfed.table.column.combobox-multi.remote/config.vue.d.ts +2 -2
  104. package/dist/runtime/components/table/columns/2026-05-26/com.shwfed.table.column.combobox-single.remote/config.d.vue.ts +2 -2
  105. package/dist/runtime/components/table/columns/2026-05-26/com.shwfed.table.column.combobox-single.remote/config.vue.d.ts +2 -2
  106. package/dist/runtime/components/table/columns/2026-06-14/com.shwfed.table.column.combobox-multi/runtime.vue +5 -1
  107. package/dist/runtime/components/table/columns/2026-06-14/com.shwfed.table.column.combobox-single/runtime.vue +5 -1
  108. package/dist/runtime/components/table/columns/2026-06-17/com.shwfed.table.column.date-input/config.vue +81 -2
  109. package/dist/runtime/components/table/columns/2026-06-17/com.shwfed.table.column.date-input/runtime.vue +35 -1
  110. package/dist/runtime/components/table/columns/2026-06-17/com.shwfed.table.column.date-input/schema.d.ts +132 -0
  111. package/dist/runtime/components/table/columns/2026-06-17/com.shwfed.table.column.date-input/schema.js +28 -2
  112. package/dist/runtime/components/ui/date-picker/DatePicker.d.vue.ts +11 -1
  113. package/dist/runtime/components/ui/date-picker/DatePicker.vue +8 -1
  114. package/dist/runtime/components/ui/date-picker/DatePicker.vue.d.ts +11 -1
  115. package/dist/runtime/components/ui/date-picker/DatePickerInput.d.vue.ts +12 -2
  116. package/dist/runtime/components/ui/date-picker/DatePickerInput.vue +4 -0
  117. package/dist/runtime/components/ui/date-picker/DatePickerInput.vue.d.ts +12 -2
  118. package/dist/runtime/components/ui/date-picker/DatePickerTimeInput.d.vue.ts +1 -1
  119. package/dist/runtime/components/ui/date-picker/DatePickerTimeInput.vue.d.ts +1 -1
  120. package/dist/runtime/components/ui/date-range-picker/DateRangePickerInput.d.vue.ts +1 -1
  121. package/dist/runtime/components/ui/date-range-picker/DateRangePickerInput.vue.d.ts +1 -1
  122. package/dist/runtime/components/ui/date-range-picker/DateRangePickerTimeInput.d.vue.ts +2 -2
  123. package/dist/runtime/components/ui/date-range-picker/DateRangePickerTimeInput.vue.d.ts +2 -2
  124. package/dist/runtime/components/ui/expression-editor/ExpressionEditor.vue +1 -1
  125. package/dist/runtime/share/loop-item-var.d.ts +21 -0
  126. package/dist/runtime/share/loop-item-var.js +13 -0
  127. package/dist/runtime/vendor/cel-js/CLAUDE.md +2 -2
  128. package/dist/runtime/vendor/cel-js/PROMPT.md +7 -0
  129. package/dist/runtime/vendor/cel-js/lib/functions.js +25 -1
  130. package/dist/runtime/vendor/cel-js/lib/http-builder.d.ts +38 -3
  131. package/dist/runtime/vendor/cel-js/lib/http-builder.js +33 -0
  132. package/package.json +1 -1
  133. package/dist/preview/assets/config-BHYlKhDX.js +0 -1
  134. package/dist/preview/assets/index-C9G8y6qZ.js +0 -1
  135. package/dist/preview/assets/index-DqRQ67sX.css +0 -1
  136. package/dist/preview/assets/runtime-Bpa1zRxG.js +0 -1
  137. package/dist/preview/assets/runtime-Csv04MYG.js +0 -1
  138. package/dist/preview/assets/runtime-D0bjM4NL.js +0 -1
  139. package/dist/preview/assets/runtime-Dz3ZQYdq.js +0 -1
@@ -27,21 +27,15 @@ const { locale, t } = useI18n({
27
27
  messages: {
28
28
  zh: {
29
29
  "tree-single-search-label": "\u641C\u7D22",
30
- "tree-single-search-clear": "\u6E05\u9664\u641C\u7D22",
31
- "tree-single-load-error": "\u52A0\u8F7D\u5931\u8D25",
32
- "tree-single-empty": "\u65E0\u53EF\u9009\u9879"
30
+ "tree-single-search-clear": "\u6E05\u9664\u641C\u7D22"
33
31
  },
34
32
  en: {
35
33
  "tree-single-search-label": "Search",
36
- "tree-single-search-clear": "Clear search",
37
- "tree-single-load-error": "Failed to load",
38
- "tree-single-empty": "No options"
34
+ "tree-single-search-clear": "Clear search"
39
35
  },
40
36
  ja: {
41
37
  "tree-single-search-label": "\u691C\u7D22",
42
- "tree-single-search-clear": "\u691C\u7D22\u3092\u30AF\u30EA\u30A2",
43
- "tree-single-load-error": "\u8AAD\u307F\u8FBC\u307F\u306B\u5931\u6557\u3057\u307E\u3057\u305F",
44
- "tree-single-empty": "\u9078\u629E\u80A2\u306A\u3057"
38
+ "tree-single-search-clear": "\u691C\u7D22\u3092\u30AF\u30EA\u30A2"
45
39
  }
46
40
  }
47
41
  });
@@ -63,7 +57,6 @@ const styleValue = computed(() => {
63
57
  const model = ref(void 0);
64
58
  const roots = ref([]);
65
59
  const loading = ref(false);
66
- const fetchError = ref(null);
67
60
  async function fetchTree() {
68
61
  const dataSource = block.value.dataSource;
69
62
  if (!dataSource) {
@@ -93,10 +86,8 @@ async function fetchTree() {
93
86
  try {
94
87
  const result = await Effect.runPromise(Effect.provide(program, Fetch.layer));
95
88
  roots.value = result;
96
- fetchError.value = null;
97
89
  } catch (e) {
98
90
  console.warn("[shwfed-block] tree dataSource fetch failed", e);
99
- fetchError.value = e;
100
91
  }
101
92
  }
102
93
  watch(
@@ -279,13 +270,7 @@ const hasNodeActions = computed(() => block.value.nodeActions.items.length > 0);
279
270
  </Field>
280
271
 
281
272
  <div
282
- v-if="fetchError && roots.length === 0"
283
- class="py-1.5 text-sm text-red-500"
284
- >
285
- {{ t("tree-single-load-error") }}
286
- </div>
287
- <div
288
- v-else-if="loading && roots.length === 0"
273
+ v-if="loading && roots.length === 0"
289
274
  class="flex flex-col gap-1.5 py-1"
290
275
  aria-busy="true"
291
276
  >
@@ -347,9 +332,7 @@ const hasNodeActions = computed(() => block.value.nodeActions.items.length > 0);
347
332
  </template>
348
333
 
349
334
  <template #empty>
350
- <div class="py-1.5 text-sm text-zinc-400">
351
- {{ t("tree-single-empty") }}
352
- </div>
335
+ <span />
353
336
  </template>
354
337
  </UiTree>
355
338
  </div>
@@ -0,0 +1,70 @@
1
+ import type { Environment } from '../../../../../vendor/cel-js/lib/index.js';
2
+ import { type Value } from './schema.js';
3
+ type __VLS_Props = {
4
+ configure?: (env: Environment) => void;
5
+ };
6
+ type __VLS_ModelProps = {
7
+ modelValue: Value;
8
+ };
9
+ type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
10
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
11
+ "update:modelValue": (value: {
12
+ readonly type: "com.shwfed.block.loop";
13
+ readonly style?: string | undefined;
14
+ readonly id: string;
15
+ readonly slot: {
16
+ readonly blocks: readonly any[];
17
+ readonly layouts: readonly {
18
+ readonly name: string;
19
+ readonly layout: {
20
+ readonly style?: string | undefined;
21
+ readonly columns: number;
22
+ readonly gap?: number | undefined;
23
+ readonly rows?: number | undefined;
24
+ readonly placements: {
25
+ readonly [x: string]: {
26
+ readonly area: readonly [readonly [number, number], readonly [number, number]];
27
+ readonly v?: "stretch" | "center" | "end" | "start" | undefined;
28
+ readonly h?: "stretch" | "center" | "end" | "start" | undefined;
29
+ };
30
+ };
31
+ };
32
+ readonly media?: string | undefined;
33
+ }[];
34
+ };
35
+ readonly displayName?: string | undefined;
36
+ readonly compatibilityDate: "2026-06-25";
37
+ readonly items: string;
38
+ }) => any;
39
+ }, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
40
+ "onUpdate:modelValue"?: ((value: {
41
+ readonly type: "com.shwfed.block.loop";
42
+ readonly style?: string | undefined;
43
+ readonly id: string;
44
+ readonly slot: {
45
+ readonly blocks: readonly any[];
46
+ readonly layouts: readonly {
47
+ readonly name: string;
48
+ readonly layout: {
49
+ readonly style?: string | undefined;
50
+ readonly columns: number;
51
+ readonly gap?: number | undefined;
52
+ readonly rows?: number | undefined;
53
+ readonly placements: {
54
+ readonly [x: string]: {
55
+ readonly area: readonly [readonly [number, number], readonly [number, number]];
56
+ readonly v?: "stretch" | "center" | "end" | "start" | undefined;
57
+ readonly h?: "stretch" | "center" | "end" | "start" | undefined;
58
+ };
59
+ };
60
+ };
61
+ readonly media?: string | undefined;
62
+ }[];
63
+ };
64
+ readonly displayName?: string | undefined;
65
+ readonly compatibilityDate: "2026-06-25";
66
+ readonly items: string;
67
+ }) => any) | undefined;
68
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
69
+ declare const _default: typeof __VLS_export;
70
+ export default _default;
@@ -0,0 +1,349 @@
1
+ <script setup>
2
+ import { computed, inject, onBeforeUnmount, ref, watch } from "vue";
3
+ import { Schema } from "effect";
4
+ import { Icon } from "@iconify/vue";
5
+ import { registerLoopVariablesIfAbsent } from "../../../../../share/loop-item-var";
6
+ import BlockLayoutEditor from "../../../../block-layout-editor/index.vue";
7
+ import LayoutsSidebar from "../../../../block-layout-editor/sidebar.vue";
8
+ import LayoutMetaStrip from "../../../../block-layout-editor/meta-strip.vue";
9
+ import { Button } from "../../../../ui/button";
10
+ import { ExpressionEditor } from "../../../../ui/expression-editor";
11
+ import { Field, FieldLabel } from "../../../../ui/field";
12
+ import { InputGroup, InputGroupInput } from "../../../../ui/input-group";
13
+ import { Markdown } from "../../../../ui/markdown";
14
+ import { ScrollArea } from "../../../../ui/scroll-area";
15
+ import { Separator } from "../../../../ui/separator";
16
+ import { BREADCRUMB_EXTENSION_KEY } from "../../../breadcrumb-extension";
17
+ import { findBlock } from "../../../utils/resolve";
18
+ import { useSlotEditor, useSlotClipboard } from "../../../use-editor";
19
+ import LoopScopeProvider from "./loop-scope-provider.vue";
20
+ import {
21
+ getStructFieldDescription,
22
+ getStructFieldTitle,
23
+ schema
24
+ } from "./schema";
25
+ defineOptions({ name: "ShwfedBlockLoopConfig" });
26
+ const block = defineModel({ type: null, ...{ required: true } });
27
+ const props = defineProps({
28
+ configure: { type: Function, required: false }
29
+ });
30
+ const configure = computed(() => props.configure ?? (() => {
31
+ }));
32
+ const itemConfigure = (env) => {
33
+ configure.value(env);
34
+ registerLoopVariablesIfAbsent(env);
35
+ };
36
+ const blockSchema = schema(() => {
37
+ }, Schema.Any);
38
+ const fieldTitle = (f) => getStructFieldTitle(blockSchema, f) ?? f;
39
+ const fieldDescription = (f) => getStructFieldDescription(blockSchema, f);
40
+ const slotAccessor = computed({
41
+ get: () => block.value.slot,
42
+ set: (next) => {
43
+ block.value = { ...block.value, slot: next };
44
+ }
45
+ });
46
+ const editor = useSlotEditor(slotAccessor, { configure: itemConfigure });
47
+ const { copy: copyBlocks, paste: pasteBlocks } = useSlotClipboard(editor);
48
+ const viewMode = ref("general");
49
+ function selectContent() {
50
+ viewMode.value = "content";
51
+ drilledBlockId.value = null;
52
+ }
53
+ function selectGeneral() {
54
+ viewMode.value = "general";
55
+ drilledBlockId.value = null;
56
+ }
57
+ function setDisplayName(v) {
58
+ const s = String(v ?? "");
59
+ block.value = { ...block.value, displayName: s.length > 0 ? s : void 0 };
60
+ }
61
+ function setItems(v) {
62
+ block.value = { ...block.value, items: v };
63
+ }
64
+ function setStyle(v) {
65
+ block.value = { ...block.value, style: v.trim().length > 0 ? v : void 0 };
66
+ }
67
+ function selectLayout(index) {
68
+ editor.activeLayoutIndex.value = index;
69
+ viewMode.value = "content";
70
+ drilledBlockId.value = null;
71
+ }
72
+ function addLayout() {
73
+ const cur = editor.layouts.value;
74
+ editor.layouts.value = [
75
+ ...cur,
76
+ { name: "\u65B0\u5E03\u5C40", layout: { columns: 1, placements: {} } }
77
+ ];
78
+ editor.activeLayoutIndex.value = cur.length;
79
+ viewMode.value = "content";
80
+ }
81
+ function addBlock(entry, options) {
82
+ editor.addBlock(entry, options);
83
+ }
84
+ const drilledBlockId = ref(null);
85
+ const drilledBlock = computed(() => {
86
+ const id = drilledBlockId.value;
87
+ if (!id) return null;
88
+ return editor.blocks.value.find((b) => b.id === id) ?? null;
89
+ });
90
+ const drilledEntry = computed(() => {
91
+ const b = drilledBlock.value;
92
+ return b ? findBlock(b.type, b.compatibilityDate) ?? null : null;
93
+ });
94
+ function onDrillDown(id) {
95
+ drilledBlockId.value = id;
96
+ }
97
+ function popDrill() {
98
+ drilledBlockId.value = null;
99
+ }
100
+ watch(
101
+ () => editor.blocks.value.map((b) => b.id),
102
+ (ids) => {
103
+ const id = drilledBlockId.value;
104
+ if (id && !ids.includes(id)) drilledBlockId.value = null;
105
+ }
106
+ );
107
+ function updateDrilledBlock(next) {
108
+ const id = drilledBlockId.value;
109
+ if (!id) return;
110
+ editor.updateBlock(id, next);
111
+ }
112
+ const breadcrumbExt = inject(BREADCRUMB_EXTENSION_KEY, null);
113
+ if (breadcrumbExt) {
114
+ const blockCrumb = breadcrumbExt.add();
115
+ watch(
116
+ drilledBlock,
117
+ (drilled) => {
118
+ if (drilled) {
119
+ blockCrumb.label.value = editor.getBlockLabel(drilled);
120
+ blockCrumb.back.value = popDrill;
121
+ } else {
122
+ blockCrumb.label.value = null;
123
+ blockCrumb.back.value = null;
124
+ }
125
+ },
126
+ { immediate: true }
127
+ );
128
+ onBeforeUnmount(() => {
129
+ blockCrumb.dispose();
130
+ });
131
+ }
132
+ </script>
133
+
134
+ <template>
135
+ <div class="flex min-w-0 gap-2 min-h-128">
136
+ <!-- Left rail: setting rows (top) + the slot's layouts (bottom). Hidden
137
+ while drilled into a child block so the drilled view owns the width. -->
138
+ <div
139
+ v-if="!drilledBlockId"
140
+ class="flex w-56 shrink-0 flex-col"
141
+ >
142
+ <div
143
+ class="row pl-2"
144
+ :class="viewMode === 'general' ? 'bg-[color-mix(in_srgb,var(--primary)_10%,white)] text-(--primary)' : 'text-zinc-700 hover:bg-zinc-50'"
145
+ @click="selectGeneral()"
146
+ >
147
+ <Icon
148
+ icon="fluent:settings-20-regular"
149
+ class="size-4 shrink-0"
150
+ />
151
+ <span class="flex-1 truncate">通用配置</span>
152
+ </div>
153
+
154
+ <div
155
+ class="row pl-2"
156
+ :class="viewMode === 'content' ? 'bg-[color-mix(in_srgb,var(--primary)_10%,white)] text-(--primary)' : 'text-zinc-700 hover:bg-zinc-50'"
157
+ @click="selectContent()"
158
+ >
159
+ <Icon
160
+ icon="fluent:apps-list-20-regular"
161
+ class="size-4 shrink-0"
162
+ />
163
+ <span class="flex-1 truncate">内容</span>
164
+ </div>
165
+
166
+ <Separator class="my-2" />
167
+
168
+ <!-- Layouts of the slot -->
169
+ <div class="flex flex-1 min-h-0 flex-col">
170
+ <ScrollArea class="flex-1">
171
+ <LayoutsSidebar
172
+ :model-value="editor.layouts.value"
173
+ :active-index="editor.activeLayoutIndex.value"
174
+ @update:model-value="(v) => {
175
+ editor.layouts.value = v;
176
+ }"
177
+ @update:active-index="selectLayout"
178
+ />
179
+ </ScrollArea>
180
+ <Button
181
+ variant="ghost"
182
+ size="sm"
183
+ class="w-full justify-start"
184
+ @click="addLayout()"
185
+ >
186
+ <Icon
187
+ icon="fluent:add-20-regular"
188
+ class="size-4"
189
+ />
190
+ <span>新增布局</span>
191
+ </Button>
192
+ </div>
193
+ </div>
194
+
195
+ <!-- Right pane -->
196
+ <div class="flex min-w-0 flex-1 flex-col gap-3">
197
+ <!-- Drilled into a child block. Deliberately NOT wrapped in
198
+ LoopScopeProvider and given the bare page `configure`: a nested block's
199
+ own CEL fields are validated at decode against the page's ROOT
200
+ configure (the block union is pre-built there, without item/index), so
201
+ advertising item/index here would be green-in-editor / red-on-save.
202
+ The drilled child sees only the page context — matching what its fields
203
+ can actually save. (item/index reach inner blocks at runtime via
204
+ loop-item.vue, and inner markdown `{{ }}` interpolation is freeform, so
205
+ the headline use case still works.) -->
206
+ <template v-if="drilledBlockId">
207
+ <div
208
+ v-if="!drilledBlock"
209
+ class="flex min-h-96 items-center justify-center p-8 text-sm text-zinc-400"
210
+ >
211
+ 块已不存在
212
+ </div>
213
+ <div v-else-if="drilledEntry">
214
+ <component
215
+ :is="drilledEntry.config"
216
+ :model-value="drilledBlock"
217
+ :configure="configure"
218
+ @update:model-value="(next) => updateDrilledBlock(next)"
219
+ />
220
+ </div>
221
+ <div
222
+ v-else
223
+ class="p-6 text-sm text-red-500"
224
+ >
225
+ 未注册的块类型:{{ drilledBlock.type }}@{{ drilledBlock.compatibilityDate }}
226
+ </div>
227
+ </template>
228
+
229
+ <!-- General block-level settings — `items` / `style` evaluate at page
230
+ scope, so this branch is deliberately OUTSIDE LoopScopeProvider. -->
231
+ <template v-else-if="viewMode === 'general'">
232
+ <Field orientation="vertical">
233
+ <FieldLabel class="text-xs text-zinc-500">
234
+ <template
235
+ v-if="fieldDescription('displayName')"
236
+ #tooltip
237
+ >
238
+ <Markdown
239
+ :source="fieldDescription('displayName')"
240
+ block
241
+ class="prose prose-sm prose-zinc"
242
+ />
243
+ </template>
244
+ {{ fieldTitle("displayName") }}
245
+ </FieldLabel>
246
+ <InputGroup>
247
+ <InputGroupInput
248
+ :model-value="block.displayName ?? ''"
249
+ placeholder="例:流转意见"
250
+ @update:model-value="setDisplayName"
251
+ />
252
+ </InputGroup>
253
+ </Field>
254
+
255
+ <Field orientation="vertical">
256
+ <FieldLabel class="text-xs text-zinc-500">
257
+ <template
258
+ v-if="fieldDescription('items')"
259
+ #tooltip
260
+ >
261
+ <Markdown
262
+ :source="fieldDescription('items')"
263
+ block
264
+ class="prose prose-sm prose-zinc"
265
+ />
266
+ </template>
267
+ {{ fieldTitle("items") }}
268
+ </FieldLabel>
269
+ <ExpressionEditor
270
+ :model-value="block.items"
271
+ placeholder="返回列表的表达式,如 task.flowExecuteRecordList.filter(n, n.taskStatus == 'DONE')"
272
+ multiline
273
+ class="min-h-16"
274
+ @update:model-value="(v) => setItems(v)"
275
+ />
276
+ </Field>
277
+
278
+ <Field orientation="vertical">
279
+ <FieldLabel class="text-xs text-zinc-500">
280
+ <template
281
+ v-if="fieldDescription('style')"
282
+ #tooltip
283
+ >
284
+ <Markdown
285
+ :source="fieldDescription('style')"
286
+ block
287
+ class="prose prose-sm prose-zinc"
288
+ />
289
+ </template>
290
+ {{ fieldTitle("style") }}
291
+ </FieldLabel>
292
+ <ExpressionEditor
293
+ :model-value="block.style ?? ''"
294
+ placeholder="可选;返回 CSS 字符串或样式对象的表达式,如 'gap: 1.5rem'"
295
+ multiline
296
+ class="min-h-12"
297
+ @update:model-value="(v) => setStyle(v)"
298
+ />
299
+ </Field>
300
+ </template>
301
+
302
+ <!-- Content: slot layout editor — wrapped so the layout `media` editor
303
+ (in the meta-strip) advertises `item` / `index`. The inner slot
304
+ registers them via `itemConfigure`, so decode accepts a media like
305
+ `index == 0`; this keeps that editor consistent with the save. -->
306
+ <LoopScopeProvider v-else>
307
+ <LayoutMetaStrip
308
+ :model-value="editor.layouts.value"
309
+ :index="editor.activeLayoutIndex.value"
310
+ @update:model-value="(v) => {
311
+ editor.layouts.value = v;
312
+ }"
313
+ />
314
+ <div class="flex-1">
315
+ <BlockLayoutEditor
316
+ :model-value="editor.layouts.value"
317
+ :active-index="editor.activeLayoutIndex.value"
318
+ :selected-item-ids="editor.selectedBlockIds.value"
319
+ :items="editor.blocks.value"
320
+ :find-entry="editor.findBlockMeta"
321
+ :get-item-label="editor.getBlockLabel"
322
+ :picker-entries="editor.pickerEntries.value"
323
+ :can-delete="true"
324
+ item-noun="块"
325
+ @update:model-value="(v) => {
326
+ editor.layouts.value = v;
327
+ }"
328
+ @update:active-index="(v) => {
329
+ editor.activeLayoutIndex.value = v;
330
+ }"
331
+ @update:selected-item-ids="(v) => {
332
+ editor.selectedBlockIds.value = v;
333
+ }"
334
+ @add-new="addBlock"
335
+ @drill-down="onDrillDown"
336
+ @delete-item="(id) => editor.removeBlock(id)"
337
+ @delete-items="(ids) => editor.removeBlocks(ids)"
338
+ @copy-items="copyBlocks"
339
+ @paste="pasteBlocks"
340
+ />
341
+ </div>
342
+ </LoopScopeProvider>
343
+ </div>
344
+ </div>
345
+ </template>
346
+
347
+ <style scoped>
348
+ .row{align-items:center;border-radius:.25rem;cursor:pointer;display:flex;font-size:.875rem;gap:.375rem;padding-block:.375rem;padding-left:.5rem;padding-right:.5rem;position:relative;transition:background-color .1s ease;-webkit-user-select:none;-moz-user-select:none;user-select:none}
349
+ </style>
@@ -0,0 +1,70 @@
1
+ import type { Environment } from '../../../../../vendor/cel-js/lib/index.js';
2
+ import { type Value } from './schema.js';
3
+ type __VLS_Props = {
4
+ configure?: (env: Environment) => void;
5
+ };
6
+ type __VLS_ModelProps = {
7
+ modelValue: Value;
8
+ };
9
+ type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
10
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
11
+ "update:modelValue": (value: {
12
+ readonly type: "com.shwfed.block.loop";
13
+ readonly style?: string | undefined;
14
+ readonly id: string;
15
+ readonly slot: {
16
+ readonly blocks: readonly any[];
17
+ readonly layouts: readonly {
18
+ readonly name: string;
19
+ readonly layout: {
20
+ readonly style?: string | undefined;
21
+ readonly columns: number;
22
+ readonly gap?: number | undefined;
23
+ readonly rows?: number | undefined;
24
+ readonly placements: {
25
+ readonly [x: string]: {
26
+ readonly area: readonly [readonly [number, number], readonly [number, number]];
27
+ readonly v?: "stretch" | "center" | "end" | "start" | undefined;
28
+ readonly h?: "stretch" | "center" | "end" | "start" | undefined;
29
+ };
30
+ };
31
+ };
32
+ readonly media?: string | undefined;
33
+ }[];
34
+ };
35
+ readonly displayName?: string | undefined;
36
+ readonly compatibilityDate: "2026-06-25";
37
+ readonly items: string;
38
+ }) => any;
39
+ }, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
40
+ "onUpdate:modelValue"?: ((value: {
41
+ readonly type: "com.shwfed.block.loop";
42
+ readonly style?: string | undefined;
43
+ readonly id: string;
44
+ readonly slot: {
45
+ readonly blocks: readonly any[];
46
+ readonly layouts: readonly {
47
+ readonly name: string;
48
+ readonly layout: {
49
+ readonly style?: string | undefined;
50
+ readonly columns: number;
51
+ readonly gap?: number | undefined;
52
+ readonly rows?: number | undefined;
53
+ readonly placements: {
54
+ readonly [x: string]: {
55
+ readonly area: readonly [readonly [number, number], readonly [number, number]];
56
+ readonly v?: "stretch" | "center" | "end" | "start" | undefined;
57
+ readonly h?: "stretch" | "center" | "end" | "start" | undefined;
58
+ };
59
+ };
60
+ };
61
+ readonly media?: string | undefined;
62
+ }[];
63
+ };
64
+ readonly displayName?: string | undefined;
65
+ readonly compatibilityDate: "2026-06-25";
66
+ readonly items: string;
67
+ }) => any) | undefined;
68
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
69
+ declare const _default: typeof __VLS_export;
70
+ export default _default;
@@ -0,0 +1,33 @@
1
+ import type { Environment } from '../../../../../vendor/cel-js/lib/index.js';
2
+ import type { SlotValue } from '../../../../../share/layout.js';
3
+ type __VLS_Props = {
4
+ item: unknown;
5
+ index: number;
6
+ slotValue: SlotValue;
7
+ configure?: (env: Environment) => void;
8
+ };
9
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
10
+ "update:slotValue": (next: Readonly<{
11
+ blocks: ReadonlyArray<Readonly<{
12
+ id: string;
13
+ } & Record<string, unknown>>>;
14
+ layouts: readonly Readonly<{
15
+ name: string;
16
+ media?: string;
17
+ layout: import("../../../../form/schema.js").LayoutValue;
18
+ }>[];
19
+ }>) => any;
20
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
21
+ "onUpdate:slotValue"?: ((next: Readonly<{
22
+ blocks: ReadonlyArray<Readonly<{
23
+ id: string;
24
+ } & Record<string, unknown>>>;
25
+ layouts: readonly Readonly<{
26
+ name: string;
27
+ media?: string;
28
+ layout: import("../../../../form/schema.js").LayoutValue;
29
+ }>[];
30
+ }>) => any) | undefined;
31
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
32
+ declare const _default: typeof __VLS_export;
33
+ export default _default;
@@ -0,0 +1,37 @@
1
+ <script setup>
2
+ import { provideCELContext } from "../../../../../utils/cel-context";
3
+ import SlotRenderer from "../../../../../share/slot-renderer.vue";
4
+ import { findBlock } from "../../../utils/resolve";
5
+ defineOptions({ name: "ShwfedBlockLoopItem" });
6
+ const props = defineProps({
7
+ item: { type: null, required: true },
8
+ index: { type: Number, required: true },
9
+ slotValue: { type: Object, required: true },
10
+ configure: { type: Function, required: false }
11
+ });
12
+ const emit = defineEmits(["update:slotValue"]);
13
+ provideCELContext({
14
+ item: {
15
+ type: "dyn",
16
+ label: "item",
17
+ description: "\u5F53\u524D\u5FAA\u73AF\u9879",
18
+ value: () => props.item
19
+ },
20
+ index: {
21
+ type: "number",
22
+ label: "index",
23
+ description: "\u5F53\u524D\u5FAA\u73AF\u9879\u7D22\u5F15\uFF0C\u4ECE 0 \u5F00\u59CB",
24
+ value: () => props.index
25
+ }
26
+ });
27
+ </script>
28
+
29
+ <template>
30
+ <SlotRenderer
31
+ :slot-value="slotValue"
32
+ :configure="configure ?? (() => {
33
+ })"
34
+ :find-entry="findBlock"
35
+ @update:slot-value="(s) => emit('update:slotValue', s)"
36
+ />
37
+ </template>
@@ -0,0 +1,33 @@
1
+ import type { Environment } from '../../../../../vendor/cel-js/lib/index.js';
2
+ import type { SlotValue } from '../../../../../share/layout.js';
3
+ type __VLS_Props = {
4
+ item: unknown;
5
+ index: number;
6
+ slotValue: SlotValue;
7
+ configure?: (env: Environment) => void;
8
+ };
9
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
10
+ "update:slotValue": (next: Readonly<{
11
+ blocks: ReadonlyArray<Readonly<{
12
+ id: string;
13
+ } & Record<string, unknown>>>;
14
+ layouts: readonly Readonly<{
15
+ name: string;
16
+ media?: string;
17
+ layout: import("../../../../form/schema.js").LayoutValue;
18
+ }>[];
19
+ }>) => any;
20
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
21
+ "onUpdate:slotValue"?: ((next: Readonly<{
22
+ blocks: ReadonlyArray<Readonly<{
23
+ id: string;
24
+ } & Record<string, unknown>>>;
25
+ layouts: readonly Readonly<{
26
+ name: string;
27
+ media?: string;
28
+ layout: import("../../../../form/schema.js").LayoutValue;
29
+ }>[];
30
+ }>) => any) | undefined;
31
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
32
+ declare const _default: typeof __VLS_export;
33
+ export default _default;
@@ -0,0 +1,13 @@
1
+ declare var __VLS_1: {};
2
+ type __VLS_Slots = {} & {
3
+ default?: (props: typeof __VLS_1) => any;
4
+ };
5
+ declare const __VLS_base: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
6
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
7
+ declare const _default: typeof __VLS_export;
8
+ export default _default;
9
+ type __VLS_WithSlots<T, S> = T & {
10
+ new (): {
11
+ $slots: S;
12
+ };
13
+ };