@shwfed/config 2.7.1 → 2.7.2

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 (75) hide show
  1. package/dist/mcp.mjs +1125 -1014
  2. package/dist/module.json +1 -1
  3. package/dist/preview/assets/badge-CJpxWUkB.js +1 -0
  4. package/dist/preview/assets/config-B-uvT_pb.js +1 -0
  5. package/dist/preview/assets/config-BRiILJ2a.js +1 -0
  6. package/dist/preview/assets/config-CbMKku2N.js +1 -0
  7. package/dist/preview/assets/config-D8tXo17l.js +1 -0
  8. package/dist/preview/assets/config-D9pA2oC8.js +1 -0
  9. package/dist/preview/assets/config-DtCRvYa9.js +1 -0
  10. package/dist/preview/assets/config-OQtpit00.js +1 -0
  11. package/dist/preview/assets/config-QHRydAV_.js +1 -0
  12. package/dist/preview/assets/config-dtgP-3mj.js +1 -0
  13. package/dist/preview/assets/definition.vue_vue_type_script_setup_true_lang-Dp8O3US_.js +1 -0
  14. package/dist/preview/assets/{index-BGFrUxgg.js → index-BBJQYeyQ.js} +170 -170
  15. package/dist/preview/assets/{index-Bw16PZhL.js → index-BWNTkzpm.js} +1 -1
  16. package/dist/preview/assets/index-ChitoGhE.js +1 -0
  17. package/dist/preview/assets/index-DFKLSxdT.css +1 -0
  18. package/dist/preview/assets/{item-aVe51Gy6.js → item-BpzTGOEt.js} +1 -1
  19. package/dist/preview/assets/{runtime-3rNI0KDH.js → runtime-B5S6icpw.js} +1 -1
  20. package/dist/preview/assets/{runtime-CYGmRjmI.js → runtime-BDyVuoP3.js} +1 -1
  21. package/dist/preview/assets/{runtime-CfVt6IWe.js → runtime-BjB2wvFX.js} +1 -1
  22. package/dist/preview/assets/{runtime-CXQuhSAX.js → runtime-Busbr90M.js} +1 -1
  23. package/dist/preview/assets/runtime-By0VH4uC.js +1 -0
  24. package/dist/preview/assets/{runtime-DYj-R8SZ.js → runtime-C29fORZL.js} +1 -1
  25. package/dist/preview/assets/runtime-DMsEFiBw.js +1 -0
  26. package/dist/preview/assets/runtime-DfP3qvGT.js +1 -0
  27. package/dist/preview/assets/runtime-DiTvLHpE.js +1 -0
  28. package/dist/preview/index.html +2 -2
  29. package/dist/runtime/components/config/blocks/2026-05-17/com.shwfed.block.chart.xy/schema.d.ts +1 -1
  30. package/dist/runtime/components/config/blocks/2026-05-17/com.shwfed.block.chart.xy/schema.js +1 -1
  31. package/dist/runtime/components/config/blocks/2026-06-02/com.shwfed.block.card/badge.d.vue.ts +7 -0
  32. package/dist/runtime/components/config/blocks/2026-06-02/com.shwfed.block.card/badge.vue +91 -0
  33. package/dist/runtime/components/config/blocks/2026-06-02/com.shwfed.block.card/badge.vue.d.ts +7 -0
  34. package/dist/runtime/components/config/blocks/2026-06-02/com.shwfed.block.card/config.d.vue.ts +96 -0
  35. package/dist/runtime/components/config/blocks/2026-06-02/com.shwfed.block.card/config.vue +522 -0
  36. package/dist/runtime/components/config/blocks/2026-06-02/com.shwfed.block.card/config.vue.d.ts +96 -0
  37. package/dist/runtime/components/config/blocks/2026-06-02/com.shwfed.block.card/runtime.d.vue.ts +96 -0
  38. package/dist/runtime/components/config/blocks/2026-06-02/com.shwfed.block.card/runtime.vue +72 -0
  39. package/dist/runtime/components/config/blocks/2026-06-02/com.shwfed.block.card/runtime.vue.d.ts +96 -0
  40. package/dist/runtime/components/config/blocks/2026-06-02/com.shwfed.block.card/schema.d.ts +121 -0
  41. package/dist/runtime/components/config/blocks/2026-06-02/com.shwfed.block.card/schema.js +100 -0
  42. package/dist/runtime/components/form/config.vue +10 -18
  43. package/dist/runtime/components/table/columns/2026-05-24/com.shwfed.table.column.combobox-single.remote.options-remote/config.d.vue.ts +2 -2
  44. package/dist/runtime/components/table/columns/2026-05-24/com.shwfed.table.column.combobox-single.remote.options-remote/config.vue.d.ts +2 -2
  45. package/dist/runtime/components/table/columns/2026-05-24/com.shwfed.table.column.combobox-single.remote.options-static/config.d.vue.ts +2 -2
  46. package/dist/runtime/components/table/columns/2026-05-24/com.shwfed.table.column.combobox-single.remote.options-static/config.vue.d.ts +2 -2
  47. package/dist/runtime/components/table/columns/2026-05-25/com.shwfed.table.column.combobox-multi.remote.options-remote/config.d.vue.ts +2 -2
  48. package/dist/runtime/components/table/columns/2026-05-25/com.shwfed.table.column.combobox-multi.remote.options-remote/config.vue.d.ts +2 -2
  49. package/dist/runtime/components/table/columns/2026-05-25/com.shwfed.table.column.combobox-multi.remote.options-static/config.d.vue.ts +2 -2
  50. package/dist/runtime/components/table/columns/2026-05-25/com.shwfed.table.column.combobox-multi.remote.options-static/config.vue.d.ts +2 -2
  51. package/dist/runtime/components/table/columns/2026-05-26/com.shwfed.table.column.combobox-multi.remote/config.d.vue.ts +2 -2
  52. package/dist/runtime/components/table/columns/2026-05-26/com.shwfed.table.column.combobox-multi.remote/config.vue.d.ts +2 -2
  53. package/dist/runtime/components/table/columns/2026-05-26/com.shwfed.table.column.combobox-single.remote/config.d.vue.ts +2 -2
  54. package/dist/runtime/components/table/columns/2026-05-26/com.shwfed.table.column.combobox-single.remote/config.vue.d.ts +2 -2
  55. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-multi/config.d.vue.ts +2 -2
  56. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-multi/config.vue.d.ts +2 -2
  57. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-single/config.d.vue.ts +2 -2
  58. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-single/config.vue.d.ts +2 -2
  59. package/package.json +1 -1
  60. package/dist/preview/assets/config-B5FFtD0s.js +0 -1
  61. package/dist/preview/assets/config-BpWP2vu_.js +0 -1
  62. package/dist/preview/assets/config-C2OqUTNd.js +0 -1
  63. package/dist/preview/assets/config-D7cjMBeK.js +0 -1
  64. package/dist/preview/assets/config-DhORWTZC.js +0 -1
  65. package/dist/preview/assets/config-DuuYvFG_.js +0 -1
  66. package/dist/preview/assets/config-dpwN2-UY.js +0 -1
  67. package/dist/preview/assets/config-eP0EblYK.js +0 -1
  68. package/dist/preview/assets/config-hs_pZ5MM.js +0 -1
  69. package/dist/preview/assets/definition.vue_vue_type_script_setup_true_lang-B8-Uydoy.js +0 -1
  70. package/dist/preview/assets/index-BoGW90Pq.css +0 -1
  71. package/dist/preview/assets/index-CG261V86.js +0 -1
  72. package/dist/preview/assets/runtime-BOn8EwHL.js +0 -1
  73. package/dist/preview/assets/runtime-Bwr-rb58.js +0 -1
  74. package/dist/preview/assets/runtime-Ca79Fs6I.js +0 -1
  75. package/dist/preview/assets/runtime-Dd1GqYeP.js +0 -1
@@ -0,0 +1,522 @@
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 BlockLayoutEditor from "../../../../block-layout-editor/index.vue";
6
+ import LayoutsSidebar from "../../../../block-layout-editor/sidebar.vue";
7
+ import LayoutMetaStrip from "../../../../block-layout-editor/meta-strip.vue";
8
+ import { Button } from "../../../../ui/button";
9
+ import { ExpressionEditor } from "../../../../ui/expression-editor";
10
+ import { Field, FieldLabel } from "../../../../ui/field";
11
+ import { InputGroup, InputGroupInput, InputGroupNumberField } from "../../../../ui/input-group";
12
+ import { Locale as LocaleField } from "../../../../ui/locale";
13
+ import { Markdown } from "../../../../ui/markdown";
14
+ import { ScrollArea } from "../../../../ui/scroll-area";
15
+ import {
16
+ Select,
17
+ SelectContent,
18
+ SelectItem,
19
+ SelectTrigger,
20
+ SelectValue
21
+ } from "../../../../ui/select";
22
+ import { Separator } from "../../../../ui/separator";
23
+ import { Switch } from "../../../../ui/switch";
24
+ import { BREADCRUMB_EXTENSION_KEY } from "../../../breadcrumb-extension";
25
+ import { findBlock } from "../../../utils/resolve";
26
+ import { useSlotEditor } from "../../../use-editor";
27
+ import {
28
+ BADGE_VARIANTS,
29
+ badgeSchema,
30
+ getStructFieldDescription,
31
+ getStructFieldTitle,
32
+ schema
33
+ } from "./schema";
34
+ defineOptions({ name: "ShwfedBlockCardConfig" });
35
+ const block = defineModel({ type: null, ...{ required: true } });
36
+ const props = defineProps({
37
+ configure: { type: Function, required: false }
38
+ });
39
+ const configure = computed(() => props.configure ?? (() => {
40
+ }));
41
+ const blockSchema = schema(() => {
42
+ }, Schema.Any);
43
+ const badgeSchemaObj = badgeSchema(() => {
44
+ });
45
+ const fieldTitle = (f) => getStructFieldTitle(blockSchema, f) ?? f;
46
+ const fieldDescription = (f) => getStructFieldDescription(blockSchema, f);
47
+ const badgeTitle = (f) => getStructFieldTitle(badgeSchemaObj, f) ?? f;
48
+ const badgeDescription = (f) => getStructFieldDescription(badgeSchemaObj, f);
49
+ const BADGE_VARIANT_LABELS = {
50
+ default: "\u9ED8\u8BA4",
51
+ secondary: "\u6B21\u8981",
52
+ destructive: "\u8B66\u793A",
53
+ outline: "\u63CF\u8FB9"
54
+ };
55
+ const slotAccessor = computed({
56
+ get: () => block.value.slot,
57
+ set: (next) => {
58
+ block.value = { ...block.value, slot: next };
59
+ }
60
+ });
61
+ const editor = useSlotEditor(slotAccessor, { configure: configure.value });
62
+ const viewMode = ref("content");
63
+ function selectContent() {
64
+ viewMode.value = "content";
65
+ drilledBlockId.value = null;
66
+ }
67
+ function selectBadge() {
68
+ viewMode.value = "badge";
69
+ drilledBlockId.value = null;
70
+ }
71
+ function selectGeneral() {
72
+ viewMode.value = "general";
73
+ drilledBlockId.value = null;
74
+ }
75
+ function setDisplayName(v) {
76
+ const s = String(v ?? "");
77
+ block.value = { ...block.value, displayName: s.length > 0 ? s : void 0 };
78
+ }
79
+ function setStyle(v) {
80
+ block.value = { ...block.value, style: v.trim().length > 0 ? v : void 0 };
81
+ }
82
+ function setUrl(v) {
83
+ block.value = { ...block.value, url: v.trim().length > 0 ? v : void 0 };
84
+ }
85
+ const badge = computed(() => block.value.badge ?? {});
86
+ function isLocaleBlank(v) {
87
+ return !v || v.every((item) => item.message.trim().length === 0);
88
+ }
89
+ function patchBadge(patch) {
90
+ const next = { ...badge.value, ...patch };
91
+ const cleaned = {};
92
+ for (const [k, v] of Object.entries(next)) {
93
+ if (v !== void 0) cleaned[k] = v;
94
+ }
95
+ block.value = {
96
+ ...block.value,
97
+ badge: Object.keys(cleaned).length > 0 ? cleaned : void 0
98
+ };
99
+ }
100
+ function setBadgeRequest(v) {
101
+ patchBadge({ request: v.trim().length > 0 ? v : void 0 });
102
+ }
103
+ function setBadgeContent(v) {
104
+ patchBadge({ content: isLocaleBlank(v) ? void 0 : v });
105
+ }
106
+ function setBadgeInterval(v) {
107
+ patchBadge({ interval: typeof v === "number" && v > 0 ? Math.round(v) : void 0 });
108
+ }
109
+ function setBadgeDot(v) {
110
+ patchBadge({ dot: v ? true : void 0 });
111
+ }
112
+ function setBadgeVariant(v) {
113
+ const s = typeof v === "string" ? v : "default";
114
+ patchBadge({ variant: s === "default" ? void 0 : s });
115
+ }
116
+ function selectLayout(index) {
117
+ editor.activeLayoutIndex.value = index;
118
+ viewMode.value = "content";
119
+ drilledBlockId.value = null;
120
+ }
121
+ function addLayout() {
122
+ const cur = editor.layouts.value;
123
+ editor.layouts.value = [
124
+ ...cur,
125
+ { name: "\u65B0\u5E03\u5C40", layout: { columns: 1, placements: {} } }
126
+ ];
127
+ editor.activeLayoutIndex.value = cur.length;
128
+ viewMode.value = "content";
129
+ }
130
+ function addBlock(entry, options) {
131
+ editor.addBlock(entry, options);
132
+ }
133
+ const drilledBlockId = ref(null);
134
+ const drilledBlock = computed(() => {
135
+ const id = drilledBlockId.value;
136
+ if (!id) return null;
137
+ return editor.blocks.value.find((b) => b.id === id) ?? null;
138
+ });
139
+ const drilledEntry = computed(() => {
140
+ const b = drilledBlock.value;
141
+ return b ? findBlock(b.type, b.compatibilityDate) ?? null : null;
142
+ });
143
+ function onDrillDown(id) {
144
+ drilledBlockId.value = id;
145
+ }
146
+ function popDrill() {
147
+ drilledBlockId.value = null;
148
+ }
149
+ watch(
150
+ () => editor.blocks.value.map((b) => b.id),
151
+ (ids) => {
152
+ const id = drilledBlockId.value;
153
+ if (id && !ids.includes(id)) drilledBlockId.value = null;
154
+ }
155
+ );
156
+ function updateDrilledBlock(next) {
157
+ const id = drilledBlockId.value;
158
+ if (!id) return;
159
+ editor.updateBlock(id, next);
160
+ }
161
+ const breadcrumbExt = inject(BREADCRUMB_EXTENSION_KEY, null);
162
+ if (breadcrumbExt) {
163
+ const blockCrumb = breadcrumbExt.add();
164
+ watch(
165
+ drilledBlock,
166
+ (drilled) => {
167
+ if (drilled) {
168
+ blockCrumb.label.value = editor.getBlockLabel(drilled);
169
+ blockCrumb.back.value = popDrill;
170
+ } else {
171
+ blockCrumb.label.value = null;
172
+ blockCrumb.back.value = null;
173
+ }
174
+ },
175
+ { immediate: true }
176
+ );
177
+ onBeforeUnmount(() => {
178
+ blockCrumb.dispose();
179
+ });
180
+ }
181
+ </script>
182
+
183
+ <template>
184
+ <div class="flex min-w-0 gap-2 min-h-128">
185
+ <!-- Left rail: setting rows (top) + the slot's layouts (bottom). Hidden
186
+ while drilled into a child block so the drilled view owns the width. -->
187
+ <div
188
+ v-if="!drilledBlockId"
189
+ class="flex w-56 shrink-0 flex-col"
190
+ >
191
+ <div
192
+ class="row pl-2"
193
+ :class="viewMode === 'content' ? 'bg-[color-mix(in_srgb,var(--primary)_10%,white)] text-(--primary)' : 'text-zinc-700 hover:bg-zinc-50'"
194
+ @click="selectContent()"
195
+ >
196
+ <Icon
197
+ icon="fluent:apps-list-20-regular"
198
+ class="size-4 shrink-0"
199
+ />
200
+ <span class="flex-1 truncate">内容</span>
201
+ </div>
202
+
203
+ <div
204
+ class="row pl-2"
205
+ :class="viewMode === 'badge' ? 'bg-[color-mix(in_srgb,var(--primary)_10%,white)] text-(--primary)' : 'text-zinc-700 hover:bg-zinc-50'"
206
+ @click="selectBadge()"
207
+ >
208
+ <Icon
209
+ icon="fluent:badge-20-regular"
210
+ class="size-4 shrink-0"
211
+ />
212
+ <span class="flex-1 truncate">徽章</span>
213
+ </div>
214
+
215
+ <div
216
+ class="row pl-2"
217
+ :class="viewMode === 'general' ? 'bg-[color-mix(in_srgb,var(--primary)_10%,white)] text-(--primary)' : 'text-zinc-700 hover:bg-zinc-50'"
218
+ @click="selectGeneral()"
219
+ >
220
+ <Icon
221
+ icon="fluent:settings-20-regular"
222
+ class="size-4 shrink-0"
223
+ />
224
+ <span class="flex-1 truncate">通用配置</span>
225
+ </div>
226
+
227
+ <Separator class="my-2" />
228
+
229
+ <!-- Layouts of the slot -->
230
+ <div class="flex flex-1 min-h-0 flex-col">
231
+ <ScrollArea class="flex-1">
232
+ <LayoutsSidebar
233
+ :model-value="editor.layouts.value"
234
+ :active-index="editor.activeLayoutIndex.value"
235
+ @update:model-value="(v) => {
236
+ editor.layouts.value = v;
237
+ }"
238
+ @update:active-index="selectLayout"
239
+ />
240
+ </ScrollArea>
241
+ <Button
242
+ variant="ghost"
243
+ size="sm"
244
+ class="w-full justify-start"
245
+ @click="addLayout()"
246
+ >
247
+ <Icon
248
+ icon="fluent:add-20-regular"
249
+ class="size-4"
250
+ />
251
+ <span>新增布局</span>
252
+ </Button>
253
+ </div>
254
+ </div>
255
+
256
+ <!-- Right pane -->
257
+ <div class="flex min-w-0 flex-1 flex-col gap-3">
258
+ <!-- Drilled into a child block -->
259
+ <template v-if="drilledBlockId">
260
+ <div
261
+ v-if="!drilledBlock"
262
+ class="flex min-h-96 items-center justify-center p-8 text-sm text-zinc-400"
263
+ >
264
+ 块已不存在
265
+ </div>
266
+ <div v-else-if="drilledEntry">
267
+ <component
268
+ :is="drilledEntry.config"
269
+ :model-value="drilledBlock"
270
+ :configure="configure"
271
+ @update:model-value="(next) => updateDrilledBlock(next)"
272
+ />
273
+ </div>
274
+ <div
275
+ v-else
276
+ class="p-6 text-sm text-red-500"
277
+ >
278
+ 未注册的块类型:{{ drilledBlock.type }}@{{ drilledBlock.compatibilityDate }}
279
+ </div>
280
+ </template>
281
+
282
+ <!-- General block-level settings. -->
283
+ <template v-else-if="viewMode === 'general'">
284
+ <Field orientation="vertical">
285
+ <FieldLabel class="text-xs text-zinc-500">
286
+ <template
287
+ v-if="fieldDescription('displayName')"
288
+ #tooltip
289
+ >
290
+ <Markdown
291
+ :source="fieldDescription('displayName')"
292
+ block
293
+ class="prose prose-sm prose-zinc"
294
+ />
295
+ </template>
296
+ {{ fieldTitle("displayName") }}
297
+ </FieldLabel>
298
+ <InputGroup>
299
+ <InputGroupInput
300
+ :model-value="block.displayName ?? ''"
301
+ placeholder="例:概览卡片"
302
+ @update:model-value="setDisplayName"
303
+ />
304
+ </InputGroup>
305
+ </Field>
306
+
307
+ <Field orientation="vertical">
308
+ <FieldLabel class="text-xs text-zinc-500">
309
+ <template
310
+ v-if="fieldDescription('style')"
311
+ #tooltip
312
+ >
313
+ <Markdown
314
+ :source="fieldDescription('style')"
315
+ block
316
+ class="prose prose-sm prose-zinc"
317
+ />
318
+ </template>
319
+ {{ fieldTitle("style") }}
320
+ </FieldLabel>
321
+ <ExpressionEditor
322
+ :model-value="block.style ?? ''"
323
+ placeholder="返回 CSS 字符串或样式对象的表达式,如 'padding: 2rem'"
324
+ multiline
325
+ class="min-h-16"
326
+ @update:model-value="(v) => setStyle(v)"
327
+ />
328
+ </Field>
329
+
330
+ <Field orientation="vertical">
331
+ <FieldLabel class="text-xs text-zinc-500">
332
+ <template
333
+ v-if="fieldDescription('url')"
334
+ #tooltip
335
+ >
336
+ <Markdown
337
+ :source="fieldDescription('url')"
338
+ block
339
+ class="prose prose-sm prose-zinc"
340
+ />
341
+ </template>
342
+ {{ fieldTitle("url") }}
343
+ </FieldLabel>
344
+ <ExpressionEditor
345
+ :model-value="block.url ?? ''"
346
+ placeholder="可选;返回链接的表达式,如 '/detail/' + string(row.id)"
347
+ result-type="string"
348
+ @update:model-value="(v) => setUrl(v)"
349
+ />
350
+ </Field>
351
+ </template>
352
+
353
+ <!-- Badge settings. -->
354
+ <template v-else-if="viewMode === 'badge'">
355
+ <Field orientation="vertical">
356
+ <FieldLabel class="text-xs text-zinc-500">
357
+ <template
358
+ v-if="badgeDescription('content')"
359
+ #tooltip
360
+ >
361
+ <Markdown
362
+ :source="badgeDescription('content')"
363
+ block
364
+ class="prose prose-sm prose-zinc"
365
+ />
366
+ </template>
367
+ {{ badgeTitle("content") }}
368
+ </FieldLabel>
369
+ <LocaleField
370
+ markdown
371
+ translate-hint="card badge content"
372
+ :model-value="badge.content"
373
+ @update:model-value="setBadgeContent"
374
+ />
375
+ </Field>
376
+
377
+ <Field orientation="vertical">
378
+ <FieldLabel class="text-xs text-zinc-500">
379
+ <template
380
+ v-if="badgeDescription('request')"
381
+ #tooltip
382
+ >
383
+ <Markdown
384
+ :source="badgeDescription('request')"
385
+ block
386
+ class="prose prose-sm prose-zinc"
387
+ />
388
+ </template>
389
+ {{ badgeTitle("request") }}
390
+ </FieldLabel>
391
+ <ExpressionEditor
392
+ :model-value="badge.request ?? ''"
393
+ placeholder="可选;如 http.get('/api/notifications')"
394
+ result-type="HttpRequest"
395
+ multiline
396
+ class="min-h-20"
397
+ @update:model-value="(v) => setBadgeRequest(v)"
398
+ />
399
+ </Field>
400
+
401
+ <div class="grid grid-cols-2 gap-3">
402
+ <Field orientation="vertical">
403
+ <FieldLabel class="text-xs text-zinc-500">
404
+ <template
405
+ v-if="badgeDescription('interval')"
406
+ #tooltip
407
+ >
408
+ <Markdown
409
+ :source="badgeDescription('interval')"
410
+ block
411
+ class="prose prose-sm prose-zinc"
412
+ />
413
+ </template>
414
+ {{ badgeTitle("interval") }}
415
+ </FieldLabel>
416
+ <InputGroup>
417
+ <InputGroupNumberField
418
+ :model-value="badge.interval"
419
+ :min="1"
420
+ @update:model-value="(v) => setBadgeInterval(v)"
421
+ />
422
+ </InputGroup>
423
+ </Field>
424
+
425
+ <Field orientation="vertical">
426
+ <FieldLabel class="text-xs text-zinc-500">
427
+ <template
428
+ v-if="badgeDescription('variant')"
429
+ #tooltip
430
+ >
431
+ <Markdown
432
+ :source="badgeDescription('variant')"
433
+ block
434
+ class="prose prose-sm prose-zinc"
435
+ />
436
+ </template>
437
+ {{ badgeTitle("variant") }}
438
+ </FieldLabel>
439
+ <Select
440
+ :model-value="badge.variant ?? 'default'"
441
+ @update:model-value="setBadgeVariant"
442
+ >
443
+ <SelectTrigger class="w-full">
444
+ <SelectValue />
445
+ </SelectTrigger>
446
+ <SelectContent>
447
+ <SelectItem
448
+ v-for="opt in BADGE_VARIANTS"
449
+ :key="opt"
450
+ :value="opt"
451
+ >
452
+ {{ BADGE_VARIANT_LABELS[opt] }}
453
+ </SelectItem>
454
+ </SelectContent>
455
+ </Select>
456
+ </Field>
457
+ </div>
458
+
459
+ <Field orientation="horizontal">
460
+ <FieldLabel class="text-xs text-zinc-500">
461
+ <template
462
+ v-if="badgeDescription('dot')"
463
+ #tooltip
464
+ >
465
+ <Markdown
466
+ :source="badgeDescription('dot')"
467
+ block
468
+ class="prose prose-sm prose-zinc"
469
+ />
470
+ </template>
471
+ {{ badgeTitle("dot") }}
472
+ </FieldLabel>
473
+ <Switch
474
+ :model-value="badge.dot ?? false"
475
+ @update:model-value="setBadgeDot"
476
+ />
477
+ </Field>
478
+ </template>
479
+
480
+ <!-- Content: slot layout editor. -->
481
+ <template v-else>
482
+ <LayoutMetaStrip
483
+ :model-value="editor.layouts.value"
484
+ :index="editor.activeLayoutIndex.value"
485
+ @update:model-value="(v) => {
486
+ editor.layouts.value = v;
487
+ }"
488
+ />
489
+ <div class="flex-1">
490
+ <BlockLayoutEditor
491
+ :model-value="editor.layouts.value"
492
+ :active-index="editor.activeLayoutIndex.value"
493
+ :selected-item-ids="editor.selectedBlockIds.value"
494
+ :items="editor.blocks.value"
495
+ :find-entry="editor.findBlockMeta"
496
+ :get-item-label="editor.getBlockLabel"
497
+ :picker-entries="editor.pickerEntries.value"
498
+ :can-delete="true"
499
+ item-noun="块"
500
+ @update:model-value="(v) => {
501
+ editor.layouts.value = v;
502
+ }"
503
+ @update:active-index="(v) => {
504
+ editor.activeLayoutIndex.value = v;
505
+ }"
506
+ @update:selected-item-ids="(v) => {
507
+ editor.selectedBlockIds.value = v;
508
+ }"
509
+ @add-new="addBlock"
510
+ @drill-down="onDrillDown"
511
+ @delete-item="(id) => editor.removeBlock(id)"
512
+ @delete-items="(ids) => editor.removeBlocks(ids)"
513
+ />
514
+ </div>
515
+ </template>
516
+ </div>
517
+ </div>
518
+ </template>
519
+
520
+ <style scoped>
521
+ .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}
522
+ </style>
@@ -0,0 +1,96 @@
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.card";
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 url?: string | undefined;
37
+ readonly compatibilityDate: "2026-06-02";
38
+ readonly badge?: {
39
+ readonly content?: readonly [{
40
+ readonly locale: "zh";
41
+ readonly message: string;
42
+ }, ...{
43
+ readonly locale: "en" | "ja" | "ko";
44
+ readonly message: string;
45
+ }[]] | undefined;
46
+ readonly dot?: boolean | undefined;
47
+ readonly variant?: "default" | "destructive" | "outline" | "secondary" | undefined;
48
+ readonly request?: string | undefined;
49
+ readonly interval?: number | undefined;
50
+ } | undefined;
51
+ }) => any;
52
+ }, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
53
+ "onUpdate:modelValue"?: ((value: {
54
+ readonly type: "com.shwfed.block.card";
55
+ readonly style?: string | undefined;
56
+ readonly id: string;
57
+ readonly slot: {
58
+ readonly blocks: readonly any[];
59
+ readonly layouts: readonly {
60
+ readonly name: string;
61
+ readonly layout: {
62
+ readonly style?: string | undefined;
63
+ readonly columns: number;
64
+ readonly gap?: number | undefined;
65
+ readonly rows?: number | undefined;
66
+ readonly placements: {
67
+ readonly [x: string]: {
68
+ readonly area: readonly [readonly [number, number], readonly [number, number]];
69
+ readonly v?: "stretch" | "center" | "end" | "start" | undefined;
70
+ readonly h?: "stretch" | "center" | "end" | "start" | undefined;
71
+ };
72
+ };
73
+ };
74
+ readonly media?: string | undefined;
75
+ }[];
76
+ };
77
+ readonly displayName?: string | undefined;
78
+ readonly url?: string | undefined;
79
+ readonly compatibilityDate: "2026-06-02";
80
+ readonly badge?: {
81
+ readonly content?: readonly [{
82
+ readonly locale: "zh";
83
+ readonly message: string;
84
+ }, ...{
85
+ readonly locale: "en" | "ja" | "ko";
86
+ readonly message: string;
87
+ }[]] | undefined;
88
+ readonly dot?: boolean | undefined;
89
+ readonly variant?: "default" | "destructive" | "outline" | "secondary" | undefined;
90
+ readonly request?: string | undefined;
91
+ readonly interval?: number | undefined;
92
+ } | undefined;
93
+ }) => any) | undefined;
94
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
95
+ declare const _default: typeof __VLS_export;
96
+ export default _default;