@shwfed/config 2.3.26 → 2.3.28

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 (84) hide show
  1. package/dist/mcp.mjs +1211 -701
  2. package/dist/module.json +1 -1
  3. package/dist/preview/assets/{config-BkimX91E.js → config--PcXQV_r.js} +1 -1
  4. package/dist/preview/assets/{config-CO2iovZD.js → config-5KVDXgUF.js} +1 -1
  5. package/dist/preview/assets/{config-u1rl9w2L.js → config-B5avpKJE.js} +1 -1
  6. package/dist/preview/assets/{config-DgZ4NYoA.js → config-CJHPt8Gx.js} +1 -1
  7. package/dist/preview/assets/{config-ypYLVfRE.js → config-CNo3isHa.js} +1 -1
  8. package/dist/preview/assets/{config-Cm9t0CvW.js → config-CQHS6cZe.js} +1 -1
  9. package/dist/preview/assets/{config-DPFHMkHc.js → config-D0_1yZdF.js} +1 -1
  10. package/dist/preview/assets/{config-Dzqe6v-x.js → config-DDfTl9Cs.js} +1 -1
  11. package/dist/preview/assets/{config-BATy87wV.js → config-fvkC2rB8.js} +1 -1
  12. package/dist/preview/assets/{definition.vue_vue_type_script_setup_true_lang-CliXxe84.js → definition.vue_vue_type_script_setup_true_lang-RM-qDh0R.js} +1 -1
  13. package/dist/preview/assets/index-DNd8J9Zv.js +643 -0
  14. package/dist/preview/assets/index-DrIMqXAa.js +1 -0
  15. package/dist/preview/assets/index-a2QwAots.css +1 -0
  16. package/dist/preview/assets/{runtime-Dtc1ETUF.js → runtime-BGTWf-O7.js} +1 -1
  17. package/dist/preview/assets/{runtime-B_FMZ5eD.js → runtime-BPjZQmcY.js} +1 -1
  18. package/dist/preview/assets/{runtime-BTROwcw4.js → runtime-Bq3fmxeF.js} +1 -1
  19. package/dist/preview/assets/{runtime-Dsx8Y56q.js → runtime-CCbyrqQT.js} +1 -1
  20. package/dist/preview/assets/{runtime-T_tUqLxO.js → runtime-C_XX6a0C.js} +1 -1
  21. package/dist/preview/assets/{runtime-BR6-W3u_.js → runtime-CtqwtTE_.js} +1 -1
  22. package/dist/preview/assets/{runtime-D1xLbTQ9.js → runtime-DcrzodsN.js} +1 -1
  23. package/dist/preview/assets/{runtime-CTpsTb-X.js → runtime-Dr_10emf.js} +1 -1
  24. package/dist/preview/assets/{runtime-Cj0kLSqP.js → runtime-Dy4ZmQ-n.js} +1 -1
  25. package/dist/preview/index.html +2 -2
  26. package/dist/runtime/components/config/blocks/2026-05-06/com.shwfed.block.tabs/config.d.vue.ts +2 -0
  27. package/dist/runtime/components/config/blocks/2026-05-06/com.shwfed.block.tabs/config.vue +57 -3
  28. package/dist/runtime/components/config/blocks/2026-05-06/com.shwfed.block.tabs/config.vue.d.ts +2 -0
  29. package/dist/runtime/components/config/blocks/2026-05-06/com.shwfed.block.tabs/runtime.d.vue.ts +2 -0
  30. package/dist/runtime/components/config/blocks/2026-05-06/com.shwfed.block.tabs/runtime.vue +1 -0
  31. package/dist/runtime/components/config/blocks/2026-05-06/com.shwfed.block.tabs/runtime.vue.d.ts +2 -0
  32. package/dist/runtime/components/config/blocks/2026-05-06/com.shwfed.block.tabs/schema.d.ts +2 -0
  33. package/dist/runtime/components/config/blocks/2026-05-06/com.shwfed.block.tabs/schema.js +4 -0
  34. package/dist/runtime/components/form/fields/2026-05-23/com.shwfed.form.field.tree.multi/config.d.vue.ts +4 -4
  35. package/dist/runtime/components/form/fields/2026-05-23/com.shwfed.form.field.tree.multi/config.vue.d.ts +4 -4
  36. package/dist/runtime/components/form/fields/2026-05-26/com.shwfed.form.field.tree.combobox.multi/config.d.vue.ts +127 -0
  37. package/dist/runtime/components/form/fields/2026-05-26/com.shwfed.form.field.tree.combobox.multi/config.vue +593 -0
  38. package/dist/runtime/components/form/fields/2026-05-26/com.shwfed.form.field.tree.combobox.multi/config.vue.d.ts +127 -0
  39. package/dist/runtime/components/form/fields/2026-05-26/com.shwfed.form.field.tree.combobox.multi/runtime.d.vue.ts +8 -0
  40. package/dist/runtime/components/form/fields/2026-05-26/com.shwfed.form.field.tree.combobox.multi/runtime.vue +465 -0
  41. package/dist/runtime/components/form/fields/2026-05-26/com.shwfed.form.field.tree.combobox.multi/runtime.vue.d.ts +8 -0
  42. package/dist/runtime/components/form/fields/2026-05-26/com.shwfed.form.field.tree.combobox.multi/schema.d.ts +95 -0
  43. package/dist/runtime/components/form/fields/2026-05-26/com.shwfed.form.field.tree.combobox.multi/schema.js +112 -0
  44. package/dist/runtime/components/form/fields/2026-05-26/com.shwfed.form.field.tree.combobox.single/config.d.vue.ts +125 -0
  45. package/dist/runtime/components/form/fields/2026-05-26/com.shwfed.form.field.tree.combobox.single/config.vue +525 -0
  46. package/dist/runtime/components/form/fields/2026-05-26/com.shwfed.form.field.tree.combobox.single/config.vue.d.ts +125 -0
  47. package/dist/runtime/components/form/fields/2026-05-26/com.shwfed.form.field.tree.combobox.single/runtime.d.vue.ts +8 -0
  48. package/dist/runtime/components/form/fields/2026-05-26/com.shwfed.form.field.tree.combobox.single/runtime.vue +460 -0
  49. package/dist/runtime/components/form/fields/2026-05-26/com.shwfed.form.field.tree.combobox.single/runtime.vue.d.ts +8 -0
  50. package/dist/runtime/components/form/fields/2026-05-26/com.shwfed.form.field.tree.combobox.single/schema.d.ts +92 -0
  51. package/dist/runtime/components/form/fields/2026-05-26/com.shwfed.form.field.tree.combobox.single/schema.js +104 -0
  52. package/dist/runtime/components/form/fields/2026-05-26/tree-combobox-shared.d.ts +35 -0
  53. package/dist/runtime/components/form/fields/2026-05-26/tree-combobox-shared.js +31 -0
  54. package/dist/runtime/components/table/columns/2026-05-25/com.shwfed.table.column.combobox-multi/runtime.vue +36 -13
  55. package/dist/runtime/components/table/columns/2026-05-26/com.shwfed.table.column.combobox-multi/runtime.vue +36 -12
  56. package/dist/runtime/components/table/columns/2026-05-26/com.shwfed.table.column.combobox-multi.remote/runtime.vue +0 -1
  57. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-multi/config.d.vue.ts +131 -0
  58. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-multi/config.vue +607 -0
  59. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-multi/config.vue.d.ts +131 -0
  60. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-multi/runtime.d.vue.ts +9 -0
  61. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-multi/runtime.vue +447 -0
  62. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-multi/runtime.vue.d.ts +9 -0
  63. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-multi/schema.d.ts +90 -0
  64. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-multi/schema.js +143 -0
  65. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-single/config.d.vue.ts +129 -0
  66. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-single/config.vue +538 -0
  67. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-single/config.vue.d.ts +129 -0
  68. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-single/runtime.d.vue.ts +9 -0
  69. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-single/runtime.vue +429 -0
  70. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-single/runtime.vue.d.ts +9 -0
  71. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-single/schema.d.ts +87 -0
  72. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-single/schema.js +135 -0
  73. package/dist/runtime/components/table/columns/2026-05-27/tree-combobox-shared.d.ts +35 -0
  74. package/dist/runtime/components/table/columns/2026-05-27/tree-combobox-shared.js +31 -0
  75. package/dist/runtime/components/table/config.vue +29 -0
  76. package/dist/runtime/components/ui/command/CommandItem.vue +12 -4
  77. package/dist/runtime/components/ui/tree/Tree.d.vue.ts +2 -0
  78. package/dist/runtime/components/ui/tree/Tree.vue +7 -2
  79. package/dist/runtime/components/ui/tree/Tree.vue.d.ts +2 -0
  80. package/dist/runtime/components/ui/tree/TreeNode.vue +16 -26
  81. package/package.json +1 -1
  82. package/dist/preview/assets/index-6rM4rqXR.js +0 -1
  83. package/dist/preview/assets/index-BCE-G4Ha.css +0 -1
  84. package/dist/preview/assets/index-wBVA0mNO.js +0 -643
@@ -0,0 +1,429 @@
1
+ <script setup>
2
+ import { Icon } from "@iconify/vue";
3
+ import { Effect, Fiber, Option } from "effect";
4
+ import { computed, ref, shallowRef, watch } from "vue";
5
+ import { useI18n } from "vue-i18n";
6
+ import { cel as _rawCel } from "../../../../../utils/cel";
7
+ import { celBindings, injectCELContext } from "../../../../../utils/cel-context";
8
+ import { getLocalizedText } from "../../../../../share/locale";
9
+ import { InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput } from "../../../../ui/input-group";
10
+ import { Markdown } from "../../../../ui/markdown";
11
+ import { Popover, PopoverAnchor, PopoverContent, PopoverTrigger } from "../../../../ui/popover";
12
+ import { Skeleton } from "../../../../ui/skeleton";
13
+ import { Tree as UiTree } from "../../../../ui/tree";
14
+ import { useFormState } from "../../../../form/utils/state";
15
+ import { interpolateMarkdown } from "../../../utils/runtime";
16
+ import { useSharedFetchLayer } from "../../../utils/shared-fetch";
17
+ import {
18
+ findWrappedPath,
19
+ getWrappedChildren,
20
+ wrapStructuralAll
21
+ } from "../tree-combobox-shared";
22
+ defineOptions({ name: "ShwfedTableTreeComboboxSingleRendererRuntime" });
23
+ const props = defineProps({
24
+ column: { type: null, required: true },
25
+ ctx: { type: Object, required: true }
26
+ });
27
+ const { locale, t } = useI18n({
28
+ inheritLocale: true,
29
+ messages: {
30
+ zh: {
31
+ "tree-combobox-single-placeholder": "\u8BF7\u9009\u62E9",
32
+ "tree-combobox-single-search-placeholder": "\u641C\u7D22\u2026",
33
+ "tree-combobox-single-empty": "\u65E0\u53EF\u9009\u9879",
34
+ "tree-combobox-single-load-error": "\u52A0\u8F7D\u5931\u8D25",
35
+ "tree-combobox-single-retry": "\u91CD\u8BD5"
36
+ },
37
+ en: {
38
+ "tree-combobox-single-placeholder": "Select\u2026",
39
+ "tree-combobox-single-search-placeholder": "Search\u2026",
40
+ "tree-combobox-single-empty": "No options",
41
+ "tree-combobox-single-load-error": "Failed to load",
42
+ "tree-combobox-single-retry": "Retry"
43
+ },
44
+ ja: {
45
+ "tree-combobox-single-placeholder": "\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044",
46
+ "tree-combobox-single-search-placeholder": "\u691C\u7D22\u2026",
47
+ "tree-combobox-single-empty": "\u9078\u629E\u80A2\u306A\u3057",
48
+ "tree-combobox-single-load-error": "\u8AAD\u307F\u8FBC\u307F\u306B\u5931\u6557\u3057\u307E\u3057\u305F",
49
+ "tree-combobox-single-retry": "\u518D\u8A66\u884C"
50
+ }
51
+ }
52
+ });
53
+ const formState = useFormState();
54
+ const inherited = injectCELContext();
55
+ const $cel = (expression, context) => _rawCel(expression, { ...celBindings(inherited), ...context });
56
+ const sharedFetchLayer = useSharedFetchLayer();
57
+ const row = computed(() => props.ctx.row.original);
58
+ const rowIndex = computed(() => props.ctx.row.index);
59
+ const placeholderText = computed(
60
+ () => props.column.placeholder ? getLocalizedText(props.column.placeholder, locale.value) : t("tree-combobox-single-placeholder")
61
+ );
62
+ function evalBool(expression, label) {
63
+ if (!expression) return false;
64
+ try {
65
+ return Effect.runSync($cel(expression, { row: row.value, index: rowIndex.value })) === true;
66
+ } catch (e) {
67
+ console.error(`[shwfed-table] tree-combobox-single ${label} failed`, e);
68
+ return false;
69
+ }
70
+ }
71
+ const isHidden = computed(() => evalBool(props.column.hidden, "hidden"));
72
+ const isDisabled = computed(() => evalBool(props.column.disabled, "disabled"));
73
+ const isReadonly = computed(() => evalBool(props.column.readonly, "readonly"));
74
+ const effectiveReadonly = computed(
75
+ () => isReadonly.value || props.column.derived?.mode === "formula"
76
+ );
77
+ const model = computed({
78
+ get: () => {
79
+ const raw = formState.getAt(props.column.binding);
80
+ if (raw == null) return void 0;
81
+ return String(raw);
82
+ },
83
+ set: (next) => {
84
+ formState.setAt(props.column.binding, next == null ? void 0 : String(next));
85
+ }
86
+ });
87
+ function nodeCtx(raw) {
88
+ return { row: row.value, index: rowIndex.value, node: raw };
89
+ }
90
+ function nodeKey(raw) {
91
+ try {
92
+ return String(Effect.runSync($cel(props.column.nodeKey, nodeCtx(raw))));
93
+ } catch (e) {
94
+ console.error("[shwfed-table] tree-combobox-single nodeKey failed", e);
95
+ return "";
96
+ }
97
+ }
98
+ function nodeChildrenList(raw) {
99
+ let v;
100
+ try {
101
+ v = Effect.runSync($cel(props.column.nodeChildren, nodeCtx(raw)));
102
+ } catch (e) {
103
+ console.error("[shwfed-table] tree-combobox-single nodeChildren failed", e);
104
+ return void 0;
105
+ }
106
+ if (v == null) return void 0;
107
+ if (!Array.isArray(v)) return void 0;
108
+ return v;
109
+ }
110
+ function safeInterpolate(tpl, raw) {
111
+ try {
112
+ return interpolateMarkdown(tpl, $cel, nodeCtx(raw));
113
+ } catch (e) {
114
+ console.error("[shwfed-table] tree-combobox-single node interpolation failed", e);
115
+ return tpl;
116
+ }
117
+ }
118
+ function wrappedLabelText(w) {
119
+ const tpl = getLocalizedText(props.column.nodeLabel, locale.value) ?? "";
120
+ return tpl ? safeInterpolate(tpl, w.raw) : "";
121
+ }
122
+ function wrappedTooltipText(w) {
123
+ if (!props.column.nodeTooltip) return void 0;
124
+ const tpl = getLocalizedText(props.column.nodeTooltip, locale.value);
125
+ return tpl ? safeInterpolate(tpl, w.raw) : void 0;
126
+ }
127
+ function wrappedSelectable(w, _depth) {
128
+ if (isDisabled.value) return false;
129
+ const expr = props.column.nodeSelectable;
130
+ if (!expr) return true;
131
+ try {
132
+ return Effect.runSync($cel(expr, nodeCtx(w.raw)));
133
+ } catch {
134
+ return false;
135
+ }
136
+ }
137
+ const rawRoots = shallowRef([]);
138
+ const loading = ref(false);
139
+ const fetchError = ref(null);
140
+ async function fetchTree() {
141
+ const dataSource = props.column.dataSource;
142
+ if (!dataSource) {
143
+ rawRoots.value = [];
144
+ return;
145
+ }
146
+ const effect = Effect.gen(function* () {
147
+ let jsonOpt = Option.none();
148
+ if (dataSource.request) {
149
+ const builder = yield* $cel(dataSource.request, {
150
+ row: row.value,
151
+ index: rowIndex.value
152
+ });
153
+ const response = yield* builder.json();
154
+ jsonOpt = Option.some(response);
155
+ }
156
+ const dataRaw = yield* $cel(dataSource.data, {
157
+ row: row.value,
158
+ index: rowIndex.value,
159
+ json: jsonOpt
160
+ });
161
+ return Array.isArray(dataRaw) ? dataRaw : [];
162
+ });
163
+ const program = Effect.gen(function* () {
164
+ const showMaskFiber = yield* Effect.fork(
165
+ Effect.sync(() => {
166
+ loading.value = true;
167
+ }).pipe(Effect.delay("30 millis"))
168
+ );
169
+ return yield* Effect.ensuring(effect, Fiber.interrupt(showMaskFiber));
170
+ }).pipe(
171
+ Effect.ensuring(Effect.sync(() => {
172
+ loading.value = false;
173
+ }))
174
+ );
175
+ try {
176
+ const result = await Effect.runPromise(Effect.provide(program, sharedFetchLayer));
177
+ rawRoots.value = result;
178
+ fetchError.value = null;
179
+ } catch (e) {
180
+ console.warn("[shwfed-table] tree-combobox-single dataSource fetch failed", e);
181
+ fetchError.value = e;
182
+ }
183
+ }
184
+ watch(
185
+ () => [props.column.dataSource?.request, props.column.dataSource?.data],
186
+ () => {
187
+ void fetchTree();
188
+ },
189
+ { immediate: true }
190
+ );
191
+ const roots = computed(
192
+ () => wrapStructuralAll(rawRoots.value, {
193
+ nodeKey,
194
+ nodeChildren: nodeChildrenList
195
+ })
196
+ );
197
+ const triggerLabel = computed(() => {
198
+ const k = model.value;
199
+ if (!k) return "";
200
+ const path = findWrappedPath(roots.value, k);
201
+ if (!path || path.length === 0) return "";
202
+ const leaf = path[path.length - 1];
203
+ return wrappedLabelText(leaf);
204
+ });
205
+ const initialExpanded = computed(() => {
206
+ if (!props.column.expandAll) return [];
207
+ const out = [];
208
+ const stack = [...roots.value];
209
+ while (stack.length) {
210
+ const n = stack.pop();
211
+ if (n.kind === "branch") {
212
+ out.push(n.key);
213
+ stack.push(...n.children);
214
+ }
215
+ }
216
+ return out;
217
+ });
218
+ const filterQuery = ref("");
219
+ function filterPredicate(w, query) {
220
+ const q = query.trim().toLowerCase();
221
+ if (!q) return true;
222
+ return wrappedLabelText(w).trim().toLowerCase().includes(q);
223
+ }
224
+ const open = ref(false);
225
+ function handleUpdate(next) {
226
+ const k = typeof next === "string" ? next : void 0;
227
+ model.value = k;
228
+ if (k) open.value = false;
229
+ }
230
+ const showClear = computed(
231
+ () => !isDisabled.value && !loading.value && !!model.value
232
+ );
233
+ function handleClear() {
234
+ model.value = void 0;
235
+ open.value = false;
236
+ }
237
+ const hoveredKey = ref(null);
238
+ watch(open, (isOpen) => {
239
+ if (!isOpen) hoveredKey.value = null;
240
+ });
241
+ function collectTooltipNodes(out, siblings) {
242
+ for (const n of siblings) {
243
+ if (wrappedTooltipText(n)) out.push(n.key);
244
+ if (n.kind === "branch") collectTooltipNodes(out, n.children);
245
+ }
246
+ }
247
+ const anyHasTooltip = computed(() => {
248
+ if (!props.column.nodeTooltip) return false;
249
+ const out = [];
250
+ collectTooltipNodes(out, roots.value);
251
+ return out.length > 0;
252
+ });
253
+ const hoveredTooltip = computed(() => {
254
+ const k = hoveredKey.value;
255
+ if (!k) return void 0;
256
+ const path = findWrappedPath(roots.value, k);
257
+ if (!path || path.length === 0) return void 0;
258
+ return wrappedTooltipText(path[path.length - 1]);
259
+ });
260
+ </script>
261
+
262
+ <template>
263
+ <div class="p-[0.125rem] w-full">
264
+ <span
265
+ v-if="isHidden"
266
+ class="block h-7 w-full"
267
+ />
268
+ <span
269
+ v-else-if="effectiveReadonly"
270
+ class="flex items-center h-7 w-full px-2 text-[0.75rem] text-zinc-700 truncate"
271
+ >
272
+ {{ triggerLabel || "\u2014" }}
273
+ </span>
274
+ <Popover
275
+ v-else
276
+ v-model:open="open"
277
+ >
278
+ <PopoverAnchor as-child>
279
+ <InputGroup
280
+ class="group/tree-combobox-single h-7 rounded border-zinc-200/30 hover:border-zinc-200 focus-within:border-zinc-200 transition-colors ease-out duration-180"
281
+ :data-disabled="isDisabled ? 'true' : void 0"
282
+ >
283
+ <PopoverTrigger as-child>
284
+ <InputGroupInput
285
+ :model-value="triggerLabel"
286
+ :disabled="isDisabled"
287
+ :placeholder="placeholderText"
288
+ class="h-7 text-[0.75rem] md:text-[0.75rem] px-2 cursor-pointer text-left"
289
+ readonly
290
+ />
291
+ </PopoverTrigger>
292
+ <InputGroupAddon
293
+ v-if="loading"
294
+ align="inline-end"
295
+ data-slot="tree-combobox-single-loading"
296
+ class="text-zinc-400"
297
+ >
298
+ <Icon
299
+ icon="fluent:spinner-ios-20-regular"
300
+ class="size-3 animate-spin"
301
+ />
302
+ </InputGroupAddon>
303
+ <InputGroupAddon
304
+ v-else-if="showClear"
305
+ align="inline-end"
306
+ class="[@media(hover:hover)]:opacity-0 transition-opacity group-hover/tree-combobox-single:opacity-100 focus-within:opacity-100"
307
+ >
308
+ <InputGroupButton
309
+ size="icon-xs"
310
+ data-slot="tree-combobox-single-clear"
311
+ class="size-4 text-zinc-500 hover:text-zinc-700"
312
+ tabindex="-1"
313
+ @mousedown.prevent
314
+ @click.stop="handleClear"
315
+ >
316
+ <Icon
317
+ icon="fluent:dismiss-20-regular"
318
+ class="size-3"
319
+ />
320
+ </InputGroupButton>
321
+ </InputGroupAddon>
322
+ </InputGroup>
323
+ </PopoverAnchor>
324
+ <PopoverContent
325
+ class="p-0"
326
+ :style="{ width: 'var(--reka-popover-trigger-width)' }"
327
+ >
328
+ <div
329
+ data-slot="tree-combobox-single-search"
330
+ class="flex h-7 items-center gap-2 border-b border-zinc-200 px-2"
331
+ >
332
+ <Icon
333
+ icon="fluent:search-20-filled"
334
+ class="size-3 shrink-0 opacity-50"
335
+ />
336
+ <input
337
+ v-model="filterQuery"
338
+ :disabled="isDisabled"
339
+ :placeholder="t('tree-combobox-single-search-placeholder')"
340
+ class="flex h-7 w-full bg-transparent text-[0.75rem] outline-hidden placeholder:text-zinc-500 disabled:cursor-not-allowed disabled:opacity-50"
341
+ >
342
+ </div>
343
+ <div class="flex flex-col p-1">
344
+ <div
345
+ v-if="fetchError && roots.length === 0"
346
+ class="min-h-7 px-2 py-1 text-[0.75rem] text-red-500"
347
+ >
348
+ {{ t("tree-combobox-single-load-error") }}
349
+ </div>
350
+ <div
351
+ v-else-if="loading && roots.length === 0"
352
+ class="flex flex-col gap-1 px-2 py-1"
353
+ aria-busy="true"
354
+ >
355
+ <Skeleton class="h-4 w-2/3" />
356
+ <Skeleton class="h-4 w-1/2" />
357
+ <Skeleton class="h-4 w-3/5" />
358
+ </div>
359
+
360
+ <UiTree
361
+ v-else
362
+ :roots="roots"
363
+ :get-key="(w) => w.key"
364
+ :get-children="getWrappedChildren"
365
+ selection-mode="single"
366
+ :model-value="model"
367
+ :selectable="wrappedSelectable"
368
+ :filter-predicate="filterPredicate"
369
+ :filter-query="filterQuery"
370
+ :initial-expanded="initialExpanded"
371
+ :show-focused-row="false"
372
+ :class="isDisabled ? 'pointer-events-none opacity-60' : void 0"
373
+ class="max-h-72 overflow-y-auto"
374
+ @update:model-value="handleUpdate"
375
+ >
376
+ <template #node="{ node, selected }">
377
+ <span
378
+ class="flex flex-1 min-w-0 items-center justify-between gap-2"
379
+ @mouseenter="hoveredKey = node.key"
380
+ @focusin="hoveredKey = node.key"
381
+ >
382
+ <Markdown
383
+ :source="wrappedLabelText(node)"
384
+ class="prose prose-xs prose-zinc text-zinc-700 min-w-0"
385
+ />
386
+ <Icon
387
+ v-if="selected"
388
+ icon="fluent:checkmark-20-regular"
389
+ class="size-3 shrink-0 text-zinc-700"
390
+ />
391
+ </span>
392
+ </template>
393
+
394
+ <template #empty>
395
+ <div class="min-h-7 px-2 py-1 text-[0.75rem] text-zinc-400">
396
+ {{ t("tree-combobox-single-empty") }}
397
+ </div>
398
+ </template>
399
+
400
+ <template #error="{ error, retry }">
401
+ <span class="inline-flex items-center gap-1 text-xs text-red-500">
402
+ {{ t("tree-combobox-single-load-error") }}
403
+ <button
404
+ type="button"
405
+ class="underline hover:text-red-600"
406
+ @click.stop="retry"
407
+ >
408
+ {{ t("tree-combobox-single-retry") }}
409
+ </button>
410
+ <span class="sr-only">{{ String(error) }}</span>
411
+ </span>
412
+ </template>
413
+ </UiTree>
414
+ </div>
415
+ <div
416
+ v-if="anyHasTooltip && hoveredTooltip"
417
+ data-slot="tree-combobox-single-tooltip"
418
+ class="border-t border-zinc-200 px-2 py-1.5"
419
+ >
420
+ <Markdown
421
+ :source="hoveredTooltip"
422
+ block
423
+ class="prose prose-xs prose-zinc"
424
+ />
425
+ </div>
426
+ </PopoverContent>
427
+ </Popover>
428
+ </div>
429
+ </template>
@@ -0,0 +1,9 @@
1
+ import type { CellContext } from '@tanstack/vue-table';
2
+ import type { Value } from './schema.js';
3
+ type __VLS_Props = {
4
+ column: Value;
5
+ ctx: CellContext<unknown, unknown>;
6
+ };
7
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
8
+ declare const _default: typeof __VLS_export;
9
+ export default _default;
@@ -0,0 +1,87 @@
1
+ import { Schema } from 'effect';
2
+ import type { ColumnDef } from '@tanstack/vue-table';
3
+ import type { Environment } from '../../../../../vendor/cel-js/lib/index.js';
4
+ import type { ColumnDefDeps } from '../../../utils/resolve.js';
5
+ export declare const type: "com.shwfed.table.column.tree-combobox-single";
6
+ export declare const compatibilityDate: "2026-05-27";
7
+ export declare const metadata: {
8
+ readonly name: "下拉树(单选)";
9
+ readonly icon: "fluent:tree-evergreen-20-regular";
10
+ };
11
+ export declare function schema(configure: (env: Environment) => void): Schema.Struct<{
12
+ placeholder: Schema.optional<Schema.TupleType<readonly [Schema.Struct<{
13
+ locale: Schema.Literal<["zh"]>;
14
+ message: Schema.SchemaClass<string, string, never>;
15
+ }>], [Schema.Struct<{
16
+ locale: Schema.Literal<["ja", "en", "ko"]>;
17
+ message: Schema.SchemaClass<string, string, never>;
18
+ }>]>>;
19
+ hidden: Schema.optional<Schema.Schema<string, string, never>>;
20
+ disabled: Schema.optional<Schema.Schema<string, string, never>>;
21
+ readonly: Schema.optional<Schema.Schema<string, string, never>>;
22
+ derived: Schema.optional<Schema.Struct<{
23
+ mode: Schema.Literal<["formula", "prefill"]>;
24
+ expression: Schema.Schema<string, string, never>;
25
+ }>>;
26
+ dataSource: Schema.Struct<{
27
+ request: Schema.optional<Schema.Schema<string, string, never>>;
28
+ data: Schema.Schema<string, string, never>;
29
+ }>;
30
+ nodeKey: Schema.Schema<string, string, never>;
31
+ nodeChildren: Schema.Schema<string, string, never>;
32
+ nodeLabel: Schema.refine<readonly [{
33
+ readonly locale: "zh";
34
+ readonly message: string;
35
+ }, ...{
36
+ readonly locale: "en" | "ja" | "ko";
37
+ readonly message: string;
38
+ }[]], Schema.TupleType<readonly [Schema.Struct<{
39
+ locale: Schema.Literal<["zh"]>;
40
+ message: Schema.SchemaClass<string, string, never>;
41
+ }>], [Schema.Struct<{
42
+ locale: Schema.Literal<["ja", "en", "ko"]>;
43
+ message: Schema.SchemaClass<string, string, never>;
44
+ }>]>>;
45
+ nodeTooltip: Schema.optional<Schema.refine<readonly [{
46
+ readonly locale: "zh";
47
+ readonly message: string;
48
+ }, ...{
49
+ readonly locale: "en" | "ja" | "ko";
50
+ readonly message: string;
51
+ }[]], Schema.TupleType<readonly [Schema.Struct<{
52
+ locale: Schema.Literal<["zh"]>;
53
+ message: Schema.SchemaClass<string, string, never>;
54
+ }>], [Schema.Struct<{
55
+ locale: Schema.Literal<["ja", "en", "ko"]>;
56
+ message: Schema.SchemaClass<string, string, never>;
57
+ }>]>>>;
58
+ nodeSelectable: Schema.optional<Schema.Schema<string, string, never>>;
59
+ expandAll: Schema.optionalWith<typeof Schema.Boolean, {
60
+ default: () => false;
61
+ }>;
62
+ title: Schema.TupleType<readonly [Schema.Struct<{
63
+ locale: Schema.Literal<["zh"]>;
64
+ message: Schema.SchemaClass<string, string, never>;
65
+ }>], [Schema.Struct<{
66
+ locale: Schema.Literal<["ja", "en", "ko"]>;
67
+ message: Schema.SchemaClass<string, string, never>;
68
+ }>]>;
69
+ binding: Schema.refine<string, typeof Schema.String>;
70
+ enableSorting: Schema.optional<Schema.SchemaClass<boolean, boolean, never>>;
71
+ size: Schema.optional<Schema.refine<number, Schema.filter<typeof Schema.Number>>>;
72
+ grow: Schema.optional<Schema.SchemaClass<boolean, boolean, never>>;
73
+ tooltip: Schema.optional<Schema.TupleType<readonly [Schema.Struct<{
74
+ locale: Schema.Literal<["zh"]>;
75
+ message: Schema.SchemaClass<string, string, never>;
76
+ }>], [Schema.Struct<{
77
+ locale: Schema.Literal<["ja", "en", "ko"]>;
78
+ message: Schema.SchemaClass<string, string, never>;
79
+ }>]>>;
80
+ id: Schema.refine<string, typeof Schema.String>;
81
+ groupId: Schema.optional<typeof Schema.UUID>;
82
+ type: Schema.Literal<["com.shwfed.table.column.tree-combobox-single"]>;
83
+ compatibilityDate: Schema.Literal<["2026-05-27"]>;
84
+ }>;
85
+ export type Value = Schema.Schema.Type<ReturnType<typeof schema>>;
86
+ export declare function defaults(): Partial<Value>;
87
+ export declare function toColumnDef(value: Value, { getLocaleText }: ColumnDefDeps): Partial<ColumnDef<unknown, unknown>>;
@@ -0,0 +1,135 @@
1
+ import { Schema } from "effect";
2
+ import { getProperty } from "dot-prop";
3
+ import { Locale } from "../../../../../share/locale.js";
4
+ import { Expression, LocaleMarkdown } from "../../../../../share/expression.js";
5
+ import {
6
+ CelRowAccess,
7
+ derivedRowField,
8
+ editableColumnFields,
9
+ editableHeader,
10
+ registerRowVariablesIfAbsent
11
+ } from "../../../utils/shared.js";
12
+ export const type = "com.shwfed.table.column.tree-combobox-single";
13
+ export const compatibilityDate = "2026-05-27";
14
+ export const metadata = {
15
+ name: "\u4E0B\u62C9\u6811\uFF08\u5355\u9009\uFF09",
16
+ icon: "fluent:tree-evergreen-20-regular"
17
+ };
18
+ const isListLike = (t) => t === "dyn" || t.startsWith("list") || t.startsWith("optional");
19
+ const isKeyType = (t) => t === "string" || t === "number" || t === "dyn";
20
+ function withRowAndNode(configure) {
21
+ return (env) => {
22
+ configure(env);
23
+ registerRowVariablesIfAbsent(env);
24
+ env.registerVariable("node", "dyn", { description: "`\u6570\u636E\u6E90` \u8FD4\u56DE\u7684\u8282\u70B9\uFF1B\u7531\u6811\u9010\u5C42\u5411\u4E0B\u8BFB\u53D6" });
25
+ };
26
+ }
27
+ export function schema(configure) {
28
+ const CelBool = CelRowAccess(configure, { resultType: "bool" });
29
+ const CelNodeKey = Expression({ configure: withRowAndNode(configure), resultType: isKeyType });
30
+ const CelNodeChildren = Expression({ configure: withRowAndNode(configure), resultType: isListLike });
31
+ const CelNodeBool = Expression({ configure: withRowAndNode(configure), resultType: "bool" });
32
+ const NodeLocaleMd = LocaleMarkdown({ configure: withRowAndNode(configure) });
33
+ const dataSourceConfigure = (env) => {
34
+ configure(env);
35
+ registerRowVariablesIfAbsent(env);
36
+ };
37
+ const CelDataSourceRequest = Expression({
38
+ configure: dataSourceConfigure,
39
+ resultType: "HttpRequest"
40
+ });
41
+ const CelDataSourceData = Expression({
42
+ configure: (env) => {
43
+ dataSourceConfigure(env);
44
+ env.registerVariable("json", "optional<dyn>", {
45
+ description: "HTTP \u54CD\u5E94\u4F53\uFF08\u5DF2\u89E3\u6790 JSON\uFF09\uFF1B\u672A\u914D\u7F6E `request` \u65F6\u4E3A `none`"
46
+ });
47
+ },
48
+ resultType: (t) => t.startsWith("list") || t === "dyn" || t.startsWith("optional")
49
+ });
50
+ const TreeDataSource = Schema.Struct({
51
+ request: Schema.optional(CelDataSourceRequest).annotations({
52
+ title: "\u8BF7\u6C42",
53
+ description: "\u53EF\u9009\u7684 HTTP \u8BF7\u6C42\u8868\u8FBE\u5F0F\uFF1B\u672A\u914D\u7F6E\u65F6\u6570\u636E\u4ECE `data` \u8868\u8FBE\u5F0F\u4E2D\u8BFB\u53D6"
54
+ }),
55
+ data: CelDataSourceData.annotations({
56
+ title: "\u6570\u636E",
57
+ description: "\u8FD4\u56DE\u884C\u6570\u636E\u5217\u8868\u7684 CEL \u8868\u8FBE\u5F0F\uFF1B\u914D\u7F6E\u4E86 `request` \u65F6\u53EF\u901A\u8FC7 `json` \u5F15\u7528\u54CD\u5E94\u4F53"
58
+ })
59
+ }).annotations({ title: "DataSource", description: "\u6570\u636E\u6E90\u914D\u7F6E" });
60
+ return Schema.Struct({
61
+ type: Schema.Literal(type),
62
+ compatibilityDate: Schema.Literal(compatibilityDate),
63
+ ...editableColumnFields(),
64
+ placeholder: Schema.optional(Locale.annotations({
65
+ title: "\u5360\u4F4D\u7B26",
66
+ description: "\u672A\u9009\u4E2D\u4EFB\u4F55\u9009\u9879\u65F6\u8F93\u5165\u6846\u4E2D\u7684\u5360\u4F4D\u6587\u672C"
67
+ })),
68
+ hidden: Schema.optional(CelBool.annotations({
69
+ title: "\u9690\u85CF\u6761\u4EF6",
70
+ description: "\u8FD4\u56DE `true` \u65F6\u8BE5\u884C\u7684\u4E0B\u62C9\u6811\u4E0D\u6E32\u67D3\uFF08\u5176\u4F59\u884C\u4E0D\u53D7\u5F71\u54CD\uFF09"
71
+ })),
72
+ disabled: Schema.optional(CelBool.annotations({
73
+ title: "\u7981\u7528\u6761\u4EF6",
74
+ description: "\u8FD4\u56DE `true` \u65F6\u4E0B\u62C9\u6811\u4ECD\u7136\u6E32\u67D3\u4F46\u4E0D\u53EF\u9009\u62E9"
75
+ })),
76
+ readonly: Schema.optional(CelBool.annotations({
77
+ title: "\u53EA\u8BFB\u6761\u4EF6",
78
+ description: "\u8FD4\u56DE `true` \u65F6\u4EC5\u4EE5\u7EAF\u6587\u672C\u5C55\u793A\u5F53\u524D\u9009\u9879\u7684\u6807\u7B7E"
79
+ })),
80
+ derived: derivedRowField(configure, "dyn"),
81
+ dataSource: TreeDataSource.annotations({
82
+ title: "\u6570\u636E\u6E90",
83
+ description: "\u8FD4\u56DE\u5B8C\u6574\u6811\uFF08\u6839\u8282\u70B9\u5217\u8868\uFF09\u7684\u6570\u636E\u6E90\uFF1B\u901A\u8FC7 `\u8282\u70B9\u5B50\u7EA7` \u8868\u8FBE\u5F0F\u9010\u5C42\u5411\u4E0B\u8BFB\u53D6\uFF1B\u53EF\u8BBF\u95EE `row`\u3001`index`"
84
+ }),
85
+ nodeKey: CelNodeKey.annotations({
86
+ title: "\u8282\u70B9 ID",
87
+ description: "\u4E3A\u6BCF\u4E2A\u8282\u70B9\u8BA1\u7B97\u7A33\u5B9A\u552F\u4E00 ID \u7684 CEL \u8868\u8FBE\u5F0F\uFF0C\u53EF\u8BBF\u95EE `node`\u3001`row`\u3001`index`\uFF1B\u8FD0\u884C\u65F6\u4EE5\u5B57\u7B26\u4E32\u5F62\u5F0F\u5B58\u50A8"
88
+ }),
89
+ nodeChildren: CelNodeChildren.annotations({
90
+ title: "\u8282\u70B9\u5B50\u7EA7",
91
+ description: "\u8FD4\u56DE\u5F53\u524D\u8282\u70B9\u5B50\u7EA7\u5217\u8868\u7684 CEL \u8868\u8FBE\u5F0F\uFF1B\u8FD4\u56DE `none`/`null` \u6216\u7A7A\u6570\u7EC4\u65F6\u8BE5\u8282\u70B9\u89C6\u4E3A\u53F6\u5B50\uFF08\u7EC8\u7AEF\u8282\u70B9\uFF09"
92
+ }),
93
+ nodeLabel: NodeLocaleMd.annotations({
94
+ title: "\u8282\u70B9\u6807\u7B7E",
95
+ description: "\u8282\u70B9\u5C55\u793A\u7684\u672C\u5730\u5316\u6587\u672C\uFF0C\u652F\u6301 Markdown \u4E0E `{{ node.foo }}` / `{{ row.foo }}` \u63D2\u503C"
96
+ }),
97
+ nodeTooltip: Schema.optional(NodeLocaleMd.annotations({
98
+ title: "\u8282\u70B9\u63D0\u793A",
99
+ description: "\u9F20\u6807\u60AC\u505C\u5728\u8282\u70B9\u4E0A\u65F6\u5C55\u793A\u7684\u672C\u5730\u5316\u63D0\u793A"
100
+ })),
101
+ nodeSelectable: Schema.optional(CelNodeBool.annotations({
102
+ title: "\u8282\u70B9\u53EF\u9009\u6761\u4EF6",
103
+ description: "\u8FD4\u56DE `true` \u8868\u793A\u8BE5\u8282\u70B9\u53EF\u88AB\u9009\u4E2D\uFF1B\u9ED8\u8BA4\u5168\u90E8\u53EF\u9009"
104
+ })),
105
+ expandAll: Schema.optionalWith(Schema.Boolean, { default: () => false }).annotations({
106
+ title: "\u9ED8\u8BA4\u5168\u90E8\u5C55\u5F00",
107
+ description: "\u5F00\u542F\u540E\u6302\u8F7D\u65F6\u5C55\u5F00\u6240\u6709\u975E\u53F6\u5B50\u8282\u70B9"
108
+ })
109
+ }).annotations({ title: "TreeComboboxSingleRenderer", description: "\u4E0B\u62C9\u6811\u5355\u9009\u6E32\u67D3\u5668\uFF08\u53EF\u7F16\u8F91\uFF09" });
110
+ }
111
+ export function defaults() {
112
+ return {
113
+ dataSource: { data: "[]" },
114
+ nodeKey: "string(node.id)",
115
+ nodeChildren: "has(node.children) ? node.children : null",
116
+ nodeLabel: [{ locale: "zh", message: "{{ node.label }}" }],
117
+ expandAll: false
118
+ };
119
+ }
120
+ export function toColumnDef(value, { getLocaleText }) {
121
+ return {
122
+ header: editableHeader(getLocaleText(value.title)),
123
+ accessorFn: (row) => {
124
+ if (!row || typeof row !== "object") return void 0;
125
+ return getProperty(row, value.binding);
126
+ },
127
+ enableSorting: value.enableSorting ?? false,
128
+ sortingFn: "basic",
129
+ size: value.size,
130
+ meta: {
131
+ grow: value.grow ?? false,
132
+ tooltip: getLocaleText(value.tooltip)
133
+ }
134
+ };
135
+ }