@shwfed/config 2.3.28 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (146) hide show
  1. package/dist/mcp.mjs +3128 -1272
  2. package/dist/module.json +1 -1
  3. package/dist/preview/assets/{config-CQHS6cZe.js → config-BcQQl4v6.js} +1 -1
  4. package/dist/preview/assets/{config-fvkC2rB8.js → config-BdFIFUa_.js} +1 -1
  5. package/dist/preview/assets/{config-DDfTl9Cs.js → config-Bi9F-Jdh.js} +1 -1
  6. package/dist/preview/assets/{config-CJHPt8Gx.js → config-Bxkq2ZRm.js} +1 -1
  7. package/dist/preview/assets/{config-D0_1yZdF.js → config-C32yfrlg.js} +1 -1
  8. package/dist/preview/assets/{config--PcXQV_r.js → config-CHHX7vhb.js} +1 -1
  9. package/dist/preview/assets/{config-5KVDXgUF.js → config-CZ0f5xdI.js} +1 -1
  10. package/dist/preview/assets/{config-B5avpKJE.js → config-D9xGgFnF.js} +1 -1
  11. package/dist/preview/assets/{config-CNo3isHa.js → config-Ddh8pxIi.js} +1 -1
  12. package/dist/preview/assets/{definition.vue_vue_type_script_setup_true_lang-RM-qDh0R.js → definition.vue_vue_type_script_setup_true_lang-C_cjxvm1.js} +1 -1
  13. package/dist/preview/assets/{index-a2QwAots.css → index-BqOX70Hd.css} +1 -1
  14. package/dist/preview/assets/index-D-VR1i8D.js +659 -0
  15. package/dist/preview/assets/index-ihZGlPdX.js +1 -0
  16. package/dist/preview/assets/{runtime-BPjZQmcY.js → runtime-Bn8mqeDH.js} +1 -1
  17. package/dist/preview/assets/{runtime-DcrzodsN.js → runtime-Cc_Wk3o-.js} +1 -1
  18. package/dist/preview/assets/{runtime-BGTWf-O7.js → runtime-CttAjIgg.js} +1 -1
  19. package/dist/preview/assets/{runtime-Dy4ZmQ-n.js → runtime-Cx4f2UTl.js} +1 -1
  20. package/dist/preview/assets/{runtime-CCbyrqQT.js → runtime-D1dESjXR.js} +1 -1
  21. package/dist/preview/assets/{runtime-C_XX6a0C.js → runtime-DIEP1Xbh.js} +1 -1
  22. package/dist/preview/assets/{runtime-CtqwtTE_.js → runtime-DKceWuBx.js} +1 -1
  23. package/dist/preview/assets/{runtime-Dr_10emf.js → runtime-Dhid9O5c.js} +1 -1
  24. package/dist/preview/assets/{runtime-Bq3fmxeF.js → runtime-YMiqi6WY.js} +1 -1
  25. package/dist/preview/index.html +2 -2
  26. package/dist/runtime/components/block-layout-editor/index.d.vue.ts +10 -2
  27. package/dist/runtime/components/block-layout-editor/index.vue +44 -8
  28. package/dist/runtime/components/block-layout-editor/index.vue.d.ts +10 -2
  29. package/dist/runtime/components/config/blocks/2026-05-06/com.shwfed.block.form/config.d.vue.ts +2 -0
  30. package/dist/runtime/components/config/blocks/2026-05-06/com.shwfed.block.form/config.vue.d.ts +2 -0
  31. package/dist/runtime/components/config/blocks/2026-05-06/com.shwfed.block.form/runtime.d.vue.ts +2 -0
  32. package/dist/runtime/components/config/blocks/2026-05-06/com.shwfed.block.form/runtime.vue.d.ts +2 -0
  33. package/dist/runtime/components/config/blocks/2026-05-06/com.shwfed.block.form/schema.d.ts +2 -0
  34. package/dist/runtime/components/config/blocks/2026-05-06/com.shwfed.block.table/config.d.vue.ts +2 -0
  35. package/dist/runtime/components/config/blocks/2026-05-06/com.shwfed.block.table/config.vue.d.ts +2 -0
  36. package/dist/runtime/components/config/blocks/2026-05-06/com.shwfed.block.table/runtime.d.vue.ts +2 -0
  37. package/dist/runtime/components/config/blocks/2026-05-06/com.shwfed.block.table/runtime.vue.d.ts +2 -0
  38. package/dist/runtime/components/config/blocks/2026-05-06/com.shwfed.block.table/schema.d.ts +3 -0
  39. package/dist/runtime/components/config/config.vue +35 -0
  40. package/dist/runtime/components/config/use-editor.d.ts +11 -1
  41. package/dist/runtime/components/config/use-editor.js +27 -1
  42. package/dist/runtime/components/form/config.vue +32 -0
  43. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.combobox.multi/config.d.vue.ts +163 -0
  44. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.combobox.multi/config.vue +745 -0
  45. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.combobox.multi/config.vue.d.ts +163 -0
  46. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.combobox.multi/runtime.d.vue.ts +8 -0
  47. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.combobox.multi/runtime.vue +383 -0
  48. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.combobox.multi/runtime.vue.d.ts +8 -0
  49. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.combobox.multi/schema.d.ts +264 -0
  50. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.combobox.multi/schema.js +183 -0
  51. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.combobox.single/config.d.vue.ts +163 -0
  52. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.combobox.single/config.vue +745 -0
  53. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.combobox.single/config.vue.d.ts +163 -0
  54. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.combobox.single/runtime.d.vue.ts +8 -0
  55. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.combobox.single/runtime.vue +402 -0
  56. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.combobox.single/runtime.vue.d.ts +8 -0
  57. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.combobox.single/schema.d.ts +264 -0
  58. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.combobox.single/schema.js +209 -0
  59. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.multi/config.d.vue.ts +129 -0
  60. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.multi/config.vue +618 -0
  61. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.multi/config.vue.d.ts +129 -0
  62. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.multi/runtime.d.vue.ts +8 -0
  63. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.multi/runtime.vue +501 -0
  64. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.multi/runtime.vue.d.ts +8 -0
  65. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.multi/schema.d.ts +99 -0
  66. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.multi/schema.js +133 -0
  67. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.single/config.d.vue.ts +127 -0
  68. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.single/config.vue +550 -0
  69. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.single/config.vue.d.ts +127 -0
  70. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.single/runtime.d.vue.ts +8 -0
  71. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.single/runtime.vue +496 -0
  72. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.single/runtime.vue.d.ts +8 -0
  73. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.single/schema.d.ts +96 -0
  74. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.single/schema.js +125 -0
  75. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.multi/config.d.vue.ts +133 -0
  76. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.multi/config.vue +605 -0
  77. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.multi/config.vue.d.ts +133 -0
  78. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.multi/runtime.d.vue.ts +8 -0
  79. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.multi/runtime.vue +401 -0
  80. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.multi/runtime.vue.d.ts +8 -0
  81. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.multi/schema.d.ts +102 -0
  82. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.multi/schema.js +142 -0
  83. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.single/config.d.vue.ts +131 -0
  84. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.single/config.vue +560 -0
  85. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.single/config.vue.d.ts +131 -0
  86. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.single/runtime.d.vue.ts +8 -0
  87. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.single/runtime.vue +395 -0
  88. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.single/runtime.vue.d.ts +8 -0
  89. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.single/schema.d.ts +96 -0
  90. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.single/schema.js +118 -0
  91. package/dist/runtime/components/form/fields/2026-05-28/tree-combobox-shared.d.ts +35 -0
  92. package/dist/runtime/components/form/fields/2026-05-28/tree-combobox-shared.js +31 -0
  93. package/dist/runtime/components/form/index.vue +7 -5
  94. package/dist/runtime/components/form/schema.d.ts +4 -0
  95. package/dist/runtime/components/form/schema.js +4 -0
  96. package/dist/runtime/components/form/unit-config.vue +45 -1
  97. package/dist/runtime/components/table/columns/2026-04-14/com.shwfed.table.column.select/config.vue +0 -22
  98. package/dist/runtime/components/table/columns/2026-04-14/com.shwfed.table.column.select/header.vue +3 -15
  99. package/dist/runtime/components/table/columns/2026-04-14/com.shwfed.table.column.select/schema.d.ts +0 -1
  100. package/dist/runtime/components/table/columns/2026-04-14/com.shwfed.table.column.select/schema.js +0 -4
  101. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-multi/config.d.vue.ts +183 -0
  102. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-multi/config.vue +931 -0
  103. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-multi/config.vue.d.ts +183 -0
  104. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-multi/runtime.d.vue.ts +9 -0
  105. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-multi/runtime.vue +463 -0
  106. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-multi/runtime.vue.d.ts +9 -0
  107. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-multi/schema.d.ts +283 -0
  108. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-multi/schema.js +275 -0
  109. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-single/config.d.vue.ts +183 -0
  110. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-single/config.vue +931 -0
  111. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-single/config.vue.d.ts +183 -0
  112. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-single/runtime.d.vue.ts +9 -0
  113. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-single/runtime.vue +414 -0
  114. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-single/runtime.vue.d.ts +9 -0
  115. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-single/schema.d.ts +283 -0
  116. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-single/schema.js +275 -0
  117. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-multi/config.d.vue.ts +133 -0
  118. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-multi/config.vue +632 -0
  119. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-multi/config.vue.d.ts +133 -0
  120. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-multi/runtime.d.vue.ts +9 -0
  121. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-multi/runtime.vue +461 -0
  122. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-multi/runtime.vue.d.ts +9 -0
  123. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-multi/schema.d.ts +93 -0
  124. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-multi/schema.js +161 -0
  125. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-single/config.d.vue.ts +131 -0
  126. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-single/config.vue +563 -0
  127. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-single/config.vue.d.ts +131 -0
  128. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-single/runtime.d.vue.ts +9 -0
  129. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-single/runtime.vue +443 -0
  130. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-single/runtime.vue.d.ts +9 -0
  131. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-single/schema.d.ts +90 -0
  132. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-single/schema.js +153 -0
  133. package/dist/runtime/components/table/columns/2026-05-28/tree-combobox-shared.d.ts +35 -0
  134. package/dist/runtime/components/table/columns/2026-05-28/tree-combobox-shared.js +31 -0
  135. package/dist/runtime/components/table/config.vue +55 -82
  136. package/dist/runtime/components/table/schema.d.ts +4 -0
  137. package/dist/runtime/components/ui/command/CommandItem.d.vue.ts +7 -0
  138. package/dist/runtime/components/ui/command/CommandItem.vue +13 -4
  139. package/dist/runtime/components/ui/command/CommandItem.vue.d.ts +7 -0
  140. package/dist/runtime/share/clipboard.d.ts +26 -0
  141. package/dist/runtime/share/clipboard.js +82 -0
  142. package/dist/runtime/share/layout.d.ts +4 -0
  143. package/dist/runtime/share/layout.js +35 -0
  144. package/package.json +1 -1
  145. package/dist/preview/assets/index-DNd8J9Zv.js +0 -643
  146. package/dist/preview/assets/index-DrIMqXAa.js +0 -1
@@ -0,0 +1,153 @@
1
+ import { Effect, 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-28";
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 CelKeywords = Expression({ configure: withRowAndNode(configure), resultType: isListLike });
33
+ const NodeLocaleMd = LocaleMarkdown({ configure: withRowAndNode(configure) });
34
+ const dataSourceConfigure = (env) => {
35
+ configure(env);
36
+ registerRowVariablesIfAbsent(env);
37
+ };
38
+ const CelDataSourceRequest = Expression({
39
+ configure: dataSourceConfigure,
40
+ resultType: "HttpRequest"
41
+ });
42
+ const CelDataSourceData = Expression({
43
+ configure: (env) => {
44
+ dataSourceConfigure(env);
45
+ env.registerVariable("json", "optional<dyn>", {
46
+ description: "HTTP \u54CD\u5E94\u4F53\uFF08\u5DF2\u89E3\u6790 JSON\uFF09\uFF1B\u672A\u914D\u7F6E `request` \u65F6\u4E3A `none`"
47
+ });
48
+ },
49
+ resultType: (t) => t.startsWith("list") || t === "dyn" || t.startsWith("optional")
50
+ });
51
+ const TreeDataSource = Schema.Struct({
52
+ request: Schema.optional(CelDataSourceRequest).annotations({
53
+ title: "\u8BF7\u6C42",
54
+ 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"
55
+ }),
56
+ data: CelDataSourceData.annotations({
57
+ title: "\u6570\u636E",
58
+ 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"
59
+ })
60
+ }).annotations({ title: "DataSource", description: "\u6570\u636E\u6E90\u914D\u7F6E" });
61
+ return Schema.Struct({
62
+ type: Schema.Literal(type),
63
+ compatibilityDate: Schema.Literal(compatibilityDate),
64
+ ...editableColumnFields(),
65
+ placeholder: Schema.optional(Locale.annotations({
66
+ title: "\u5360\u4F4D\u7B26",
67
+ description: "\u672A\u9009\u4E2D\u4EFB\u4F55\u9009\u9879\u65F6\u8F93\u5165\u6846\u4E2D\u7684\u5360\u4F4D\u6587\u672C"
68
+ })),
69
+ hidden: Schema.optional(CelBool.annotations({
70
+ title: "\u9690\u85CF\u6761\u4EF6",
71
+ description: "\u8FD4\u56DE `true` \u65F6\u8BE5\u884C\u7684\u4E0B\u62C9\u6811\u4E0D\u6E32\u67D3\uFF08\u5176\u4F59\u884C\u4E0D\u53D7\u5F71\u54CD\uFF09"
72
+ })),
73
+ disabled: Schema.optional(CelBool.annotations({
74
+ title: "\u7981\u7528\u6761\u4EF6",
75
+ description: "\u8FD4\u56DE `true` \u65F6\u4E0B\u62C9\u6811\u4ECD\u7136\u6E32\u67D3\u4F46\u4E0D\u53EF\u9009\u62E9"
76
+ })),
77
+ readonly: Schema.optional(CelBool.annotations({
78
+ title: "\u53EA\u8BFB\u6761\u4EF6",
79
+ description: "\u8FD4\u56DE `true` \u65F6\u4EC5\u4EE5\u7EAF\u6587\u672C\u5C55\u793A\u5F53\u524D\u9009\u9879\u7684\u6807\u7B7E"
80
+ })),
81
+ derived: derivedRowField(configure, "dyn"),
82
+ dataSource: TreeDataSource.annotations({
83
+ title: "\u6570\u636E\u6E90",
84
+ 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`"
85
+ }),
86
+ nodeKey: CelNodeKey.annotations({
87
+ title: "\u8282\u70B9 ID",
88
+ 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"
89
+ }),
90
+ nodeChildren: CelNodeChildren.annotations({
91
+ title: "\u8282\u70B9\u5B50\u7EA7",
92
+ 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"
93
+ }),
94
+ nodeLabel: NodeLocaleMd.annotations({
95
+ title: "\u8282\u70B9\u6807\u7B7E",
96
+ description: "\u8282\u70B9\u5C55\u793A\u7684\u672C\u5730\u5316\u6587\u672C\uFF0C\u652F\u6301 Markdown \u4E0E `{{ node.foo }}` / `{{ row.foo }}` \u63D2\u503C"
97
+ }),
98
+ nodeTooltip: Schema.optional(NodeLocaleMd.annotations({
99
+ title: "\u8282\u70B9\u63D0\u793A",
100
+ description: "\u9F20\u6807\u60AC\u505C\u5728\u8282\u70B9\u4E0A\u65F6\u5C55\u793A\u7684\u672C\u5730\u5316\u63D0\u793A"
101
+ })),
102
+ keywords: Schema.optional(CelKeywords.annotations({
103
+ title: "\u989D\u5916\u5173\u952E\u8BCD",
104
+ description: "\u8FD4\u56DE\u5B57\u7B26\u4E32\u5217\u8868\u7684 CEL \u8868\u8FBE\u5F0F\uFF0C\u53EF\u8BBF\u95EE `node`\u3001`row`\u3001`index`\uFF1B\u641C\u7D22\u65F6\u53EA\u8981 `\u8282\u70B9\u6807\u7B7E` \u6216 \u4EFB\u4E00\u5173\u952E\u8BCD \u5305\u542B\u67E5\u8BE2\u8BCD\uFF08\u4E0D\u533A\u5206\u5927\u5C0F\u5199\uFF09\u5373\u547D\u4E2D"
105
+ })),
106
+ nodeSelectable: Schema.optional(CelNodeBool.annotations({
107
+ title: "\u8282\u70B9\u53EF\u9009\u6761\u4EF6",
108
+ description: "\u8FD4\u56DE `true` \u8868\u793A\u8BE5\u8282\u70B9\u53EF\u88AB\u9009\u4E2D\uFF1B\u9ED8\u8BA4\u5168\u90E8\u53EF\u9009"
109
+ })),
110
+ expandAll: Schema.optionalWith(Schema.Boolean, { default: () => false }).annotations({
111
+ title: "\u9ED8\u8BA4\u5168\u90E8\u5C55\u5F00",
112
+ description: "\u5F00\u542F\u540E\u6302\u8F7D\u65F6\u5C55\u5F00\u6240\u6709\u975E\u53F6\u5B50\u8282\u70B9"
113
+ })
114
+ }).annotations({ title: "TreeComboboxSingleRenderer", description: "\u4E0B\u62C9\u6811\u5355\u9009\u6E32\u67D3\u5668\uFF08\u53EF\u7F16\u8F91\uFF09" });
115
+ }
116
+ export function defaults() {
117
+ return {
118
+ dataSource: { data: "[]" },
119
+ nodeKey: "string(node.id)",
120
+ nodeChildren: "has(node.children) ? node.children : null",
121
+ nodeLabel: [{ locale: "zh", message: "{{ node.label }}" }],
122
+ expandAll: false
123
+ };
124
+ }
125
+ export const migrateFrom = [
126
+ { type: "com.shwfed.table.column.tree-combobox-single", compatibilityDate: "2026-05-27" }
127
+ ];
128
+ export const migrate = (prev) => Effect.try({
129
+ try: () => {
130
+ if (!prev || typeof prev !== "object") {
131
+ throw new Error("\u4E0B\u62C9\u6811\uFF08\u5355\u9009\uFF09\u8FC1\u79FB\u5931\u8D25\uFF1A\u539F\u503C\u4E0D\u662F\u5BF9\u8C61");
132
+ }
133
+ const { compatibilityDate: _omit, ...rest } = prev;
134
+ return { ...rest, type, compatibilityDate };
135
+ },
136
+ catch: (e) => e instanceof Error ? e : new Error(String(e))
137
+ });
138
+ export function toColumnDef(value, { getLocaleText }) {
139
+ return {
140
+ header: editableHeader(getLocaleText(value.title)),
141
+ accessorFn: (row) => {
142
+ if (!row || typeof row !== "object") return void 0;
143
+ return getProperty(row, value.binding);
144
+ },
145
+ enableSorting: value.enableSorting ?? false,
146
+ sortingFn: "basic",
147
+ size: value.size,
148
+ meta: {
149
+ grow: value.grow ?? false,
150
+ tooltip: getLocaleText(value.tooltip)
151
+ }
152
+ };
153
+ }
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Wrapping + adapter helpers shared by `tree-combobox-single` and
3
+ * `tree-combobox-multi`. The whole tree comes from `dataSource` in one
4
+ * shot, so wrapping is a pure walk over CEL-derived children: each raw
5
+ * node either has children (`branch`) or it doesn't (`terminal`).
6
+ */
7
+ export type WrappedNode = {
8
+ readonly kind: 'branch';
9
+ readonly raw: unknown;
10
+ readonly key: string;
11
+ readonly children: WrappedNode[];
12
+ } | {
13
+ readonly kind: 'terminal';
14
+ readonly raw: unknown;
15
+ readonly key: string;
16
+ };
17
+ export interface WrapStructureContext {
18
+ /** Stringified node id; one per raw node. Reuses `nodeKey` CEL. */
19
+ nodeKey: (raw: unknown) => string;
20
+ /**
21
+ * Normalised children array. `undefined`/`null`/empty all collapse to
22
+ * `undefined` here — the wrapping logic interprets that as
23
+ * "this node has no children" → `terminal`.
24
+ */
25
+ nodeChildren: (raw: unknown) => unknown[] | undefined;
26
+ }
27
+ export declare function wrapStructural(raw: unknown, ctx: WrapStructureContext): WrappedNode;
28
+ export declare function wrapStructuralAll(raws: unknown[], ctx: WrapStructureContext): WrappedNode[];
29
+ /** Synchronous `getChildren` adapter for ui/tree. */
30
+ export declare function getWrappedChildren(w: WrappedNode): WrappedNode[] | undefined;
31
+ /**
32
+ * Find the path from root to a node whose `key` matches. Returns `null`
33
+ * if the key isn't present in `roots`.
34
+ */
35
+ export declare function findWrappedPath(roots: WrappedNode[], key: string): WrappedNode[] | null;
@@ -0,0 +1,31 @@
1
+ export function wrapStructural(raw, ctx) {
2
+ const kids = ctx.nodeChildren(raw);
3
+ if (!kids || kids.length === 0) {
4
+ return { kind: "terminal", raw, key: ctx.nodeKey(raw) };
5
+ }
6
+ return {
7
+ kind: "branch",
8
+ raw,
9
+ key: ctx.nodeKey(raw),
10
+ children: kids.map((c) => wrapStructural(c, ctx))
11
+ };
12
+ }
13
+ export function wrapStructuralAll(raws, ctx) {
14
+ return raws.map((r) => wrapStructural(r, ctx));
15
+ }
16
+ export function getWrappedChildren(w) {
17
+ return w.kind === "branch" ? w.children : void 0;
18
+ }
19
+ export function findWrappedPath(roots, key) {
20
+ const trail = [];
21
+ function walk(siblings) {
22
+ for (const n of siblings) {
23
+ trail.push(n);
24
+ if (n.key === key) return true;
25
+ if (n.kind === "branch" && n.children.length > 0 && walk(n.children)) return true;
26
+ trail.pop();
27
+ }
28
+ return false;
29
+ }
30
+ return walk(roots) ? trail.slice() : null;
31
+ }
@@ -485,43 +485,14 @@ function getColumnDefaults(id, type, compatibilityDate) {
485
485
  case "com.shwfed.table.column.actions":
486
486
  return { id, type, compatibilityDate, title: [{ locale: "zh", message: "" }], size: 200, groups: [], items: [] };
487
487
  case "com.shwfed.table.column.combobox-multi":
488
- return {
489
- id,
490
- type,
491
- compatibilityDate,
492
- title: [{ locale: "zh", message: "" }],
493
- binding: "",
494
- size: 200,
495
- options: { kind: "static", items: [] }
496
- };
497
- case "com.shwfed.table.column.combobox-multi.remote":
498
- return {
499
- id,
500
- type,
501
- compatibilityDate,
502
- title: [{ locale: "zh", message: "" }],
503
- accessor: "",
504
- size: 200,
505
- options: { kind: "static", items: [] }
506
- };
507
488
  case "com.shwfed.table.column.combobox-single":
508
489
  return {
509
490
  id,
510
491
  type,
511
492
  compatibilityDate,
512
493
  title: [{ locale: "zh", message: "" }],
513
- binding: "",
514
- size: 200,
515
- options: { kind: "static", items: [] }
516
- };
517
- case "com.shwfed.table.column.combobox-single.remote":
518
- return {
519
- id,
520
- type,
521
- compatibilityDate,
522
- title: [{ locale: "zh", message: "" }],
523
- accessor: "",
524
494
  size: 200,
495
+ write: { kind: "binding", binding: "" },
525
496
  options: { kind: "static", items: [] }
526
497
  };
527
498
  case "com.shwfed.table.column.tree-combobox-single":
@@ -1292,61 +1263,63 @@ const tableQueryValue = computed({
1292
1263
  v-if="selectedGeneral"
1293
1264
  class="space-y-5"
1294
1265
  >
1295
- <Field
1296
- v-if="!hideDisplayName"
1297
- orientation="vertical"
1298
- >
1299
- <FieldLabel class="text-xs text-zinc-500">
1300
- <template
1301
- v-if="generalFieldDescription('displayName')"
1302
- #tooltip
1303
- >
1304
- <Markdown
1305
- :source="generalFieldDescription('displayName')"
1306
- block
1307
- class="prose prose-sm prose-zinc"
1266
+ <div class="grid grid-cols-2 gap-x-6 gap-y-4">
1267
+ <Field
1268
+ v-if="!hideDisplayName"
1269
+ orientation="vertical"
1270
+ >
1271
+ <FieldLabel class="text-xs text-zinc-500">
1272
+ <template
1273
+ v-if="generalFieldDescription('displayName')"
1274
+ #tooltip
1275
+ >
1276
+ <Markdown
1277
+ :source="generalFieldDescription('displayName')"
1278
+ block
1279
+ class="prose prose-sm prose-zinc"
1280
+ />
1281
+ </template>
1282
+ {{ generalFieldTitle("displayName") }}
1283
+ </FieldLabel>
1284
+ <InputGroup>
1285
+ <InputGroupInput
1286
+ :model-value="editingGeneralConfig.displayName ?? ''"
1287
+ placeholder="例:订单列表"
1288
+ @update:model-value="setGeneralDisplayName"
1308
1289
  />
1309
- </template>
1310
- {{ generalFieldTitle("displayName") }}
1311
- </FieldLabel>
1312
- <InputGroup>
1313
- <InputGroupInput
1314
- :model-value="editingGeneralConfig.displayName ?? ''"
1315
- placeholder="例:订单列表"
1316
- @update:model-value="setGeneralDisplayName"
1317
- />
1318
- </InputGroup>
1319
- </Field>
1290
+ </InputGroup>
1291
+ </Field>
1320
1292
 
1321
- <Field orientation="vertical">
1322
- <FieldLabel class="text-xs text-zinc-500">
1323
- <template
1324
- v-if="generalFieldDescription('rowKey')"
1325
- #tooltip
1326
- >
1327
- <Markdown
1328
- :source="generalFieldDescription('rowKey')"
1329
- block
1330
- class="prose prose-sm prose-zinc"
1293
+ <Field orientation="vertical">
1294
+ <FieldLabel class="text-xs text-zinc-500">
1295
+ <template
1296
+ v-if="generalFieldDescription('rowKey')"
1297
+ #tooltip
1298
+ >
1299
+ <Markdown
1300
+ :source="generalFieldDescription('rowKey')"
1301
+ block
1302
+ class="prose prose-sm prose-zinc"
1303
+ />
1304
+ </template>
1305
+ {{ generalFieldTitle("rowKey") }}
1306
+ </FieldLabel>
1307
+ <RowKeyCELContext>
1308
+ <ExpressionEditor
1309
+ :model-value="editingGeneralConfig.rowKey ?? ''"
1310
+ placeholder="如 row.id"
1311
+ result-type="string"
1312
+ @update:model-value="(v) => updateGeneralOptionalString('rowKey', v)"
1331
1313
  />
1332
- </template>
1333
- {{ generalFieldTitle("rowKey") }}
1334
- </FieldLabel>
1335
- <RowKeyCELContext>
1336
- <ExpressionEditor
1337
- :model-value="editingGeneralConfig.rowKey ?? ''"
1338
- placeholder="如 row.id"
1339
- result-type="string"
1340
- @update:model-value="(v) => updateGeneralOptionalString('rowKey', v)"
1341
- />
1342
- </RowKeyCELContext>
1343
- <p
1344
- v-if="getError('rowKey')"
1345
- class="text-xs text-red-500"
1346
- >
1347
- {{ getError("rowKey") }}
1348
- </p>
1349
- </Field>
1314
+ </RowKeyCELContext>
1315
+ <p
1316
+ v-if="getError('rowKey')"
1317
+ class="text-xs text-red-500"
1318
+ >
1319
+ {{ getError("rowKey") }}
1320
+ </p>
1321
+ </Field>
1322
+ </div>
1350
1323
 
1351
1324
  <!-- Host extension slot: a wrapping editor (e.g. the `table` form
1352
1325
  field config) injects its own fields into the general pane. -->
@@ -132,6 +132,7 @@ export declare function TableConfig(configure: (env: Environment) => void): Sche
132
132
  }[]] | undefined;
133
133
  }[];
134
134
  readonly query?: {
135
+ readonly style?: string | undefined;
135
136
  readonly initial?: {
136
137
  readonly data: string;
137
138
  readonly request?: string | undefined;
@@ -436,6 +437,7 @@ export declare function TableConfig(configure: (env: Environment) => void): Sche
436
437
  }, never>>;
437
438
  }>>;
438
439
  query: Schema.optional<Schema.refine<{
440
+ readonly style?: string | undefined;
439
441
  readonly initial?: {
440
442
  readonly data: string;
441
443
  readonly request?: string | undefined;
@@ -502,6 +504,7 @@ export declare function TableConfig(configure: (env: Environment) => void): Sche
502
504
  data: Schema.Schema<string, string, never>;
503
505
  }>>>;
504
506
  readonly: Schema.optional<Schema.Schema<string, string, never>>;
507
+ style: Schema.optional<typeof Schema.String>;
505
508
  }>>>;
506
509
  rowKey: Schema.optional<Schema.Schema<string, string, never>>;
507
510
  cellStyle: Schema.optional<Schema.Schema<string, string, never>>;
@@ -571,6 +574,7 @@ export declare function createTableConfig(body: Omit<Schema.Schema.Type<ReturnTy
571
574
  }[]] | undefined;
572
575
  }[];
573
576
  query?: {
577
+ readonly style?: string | undefined;
574
578
  readonly initial?: {
575
579
  readonly data: string;
576
580
  readonly request?: string | undefined;
@@ -2,6 +2,13 @@ import type { ListboxItemProps } from 'reka-ui';
2
2
  import type { HTMLAttributes } from 'vue';
3
3
  type __VLS_Props = ListboxItemProps & {
4
4
  class?: HTMLAttributes['class'];
5
+ /**
6
+ * Extra text folded into the value `Command` filters against, on top of the
7
+ * item's rendered label (its DOM `textContent`). Lets callers make an item
8
+ * match search terms — keywords / aliases / codes — that the label never
9
+ * shows. Pass a single pre-joined string; whitespace separates terms.
10
+ */
11
+ keywords?: string;
5
12
  };
6
13
  declare var __VLS_11: {};
7
14
  type __VLS_Slots = {} & {
@@ -1,7 +1,7 @@
1
1
  <script setup>
2
2
  import { reactiveOmit, useCurrentElement } from "@vueuse/core";
3
3
  import { injectListboxRootContext, ListboxItem, useForwardPropsEmits, useId } from "reka-ui";
4
- import { computed, onMounted, onUnmounted, ref } from "vue";
4
+ import { computed, onMounted, onUnmounted, ref, watch } from "vue";
5
5
  import { cn } from "../../../utils/cn";
6
6
  import { useCommand, useCommandGroup } from ".";
7
7
  const props = defineProps({
@@ -9,10 +9,11 @@ const props = defineProps({
9
9
  disabled: { type: Boolean, required: false },
10
10
  asChild: { type: Boolean, required: false },
11
11
  as: { type: null, required: false },
12
- class: { type: [Boolean, null, String, Object, Array], required: false, skipCheck: true }
12
+ class: { type: [Boolean, null, String, Object, Array], required: false, skipCheck: true },
13
+ keywords: { type: String, required: false }
13
14
  });
14
15
  const emits = defineEmits(["select"]);
15
- const delegatedProps = reactiveOmit(props, "class");
16
+ const delegatedProps = reactiveOmit(props, "class", "keywords");
16
17
  const forwarded = useForwardPropsEmits(delegatedProps, emits);
17
18
  const id = useId();
18
19
  const { filterState, allItems, allGroups } = useCommand();
@@ -40,10 +41,15 @@ const isRender = computed(() => {
40
41
  });
41
42
  const itemRef = ref();
42
43
  const currentElement = useCurrentElement(itemRef);
44
+ function indexedValue() {
45
+ const label = currentElement.value instanceof HTMLElement ? currentElement.value.textContent ?? "" : props.value?.toString() ?? "";
46
+ const kw = props.keywords?.trim();
47
+ return kw ? `${label} ${kw}` : label;
48
+ }
43
49
  onMounted(() => {
44
50
  if (!(currentElement.value instanceof HTMLElement))
45
51
  return;
46
- allItems.value.set(id, currentElement.value.textContent ?? (props.value?.toString() ?? ""));
52
+ allItems.value.set(id, indexedValue());
47
53
  const groupId = groupContext?.id;
48
54
  if (groupId) {
49
55
  if (!allGroups.value.has(groupId)) {
@@ -53,6 +59,9 @@ onMounted(() => {
53
59
  }
54
60
  }
55
61
  });
62
+ watch(() => props.keywords, () => {
63
+ if (allItems.value.has(id)) allItems.value.set(id, indexedValue());
64
+ });
56
65
  onUnmounted(() => {
57
66
  allItems.value.delete(id);
58
67
  });
@@ -2,6 +2,13 @@ import type { ListboxItemProps } from 'reka-ui';
2
2
  import type { HTMLAttributes } from 'vue';
3
3
  type __VLS_Props = ListboxItemProps & {
4
4
  class?: HTMLAttributes['class'];
5
+ /**
6
+ * Extra text folded into the value `Command` filters against, on top of the
7
+ * item's rendered label (its DOM `textContent`). Lets callers make an item
8
+ * match search terms — keywords / aliases / codes — that the label never
9
+ * shows. Pass a single pre-joined string; whitespace separates terms.
10
+ */
11
+ keywords?: string;
5
12
  };
6
13
  declare var __VLS_11: {};
7
14
  type __VLS_Slots = {} & {
@@ -0,0 +1,26 @@
1
+ export type ClipSurface = 'form' | 'block';
2
+ export type ClipPayload = Readonly<{
3
+ surface: ClipSurface;
4
+ items: ReadonlyArray<unknown>;
5
+ placements?: Readonly<Record<string, unknown>>;
6
+ }>;
7
+ /**
8
+ * Deep-clone the fragment with every id (and every reference to a copied id)
9
+ * replaced by a fresh UUID. Deterministic within one call: equal old ids map
10
+ * to equal new ids, so cross-references between copied items stay intact.
11
+ */
12
+ export declare function reidItems<T>(items: ReadonlyArray<T>): T[];
13
+ /**
14
+ * Reid items and their placements through one shared map, so the placement keys
15
+ * (which are item ids) and the items' own `id`s land on the same fresh UUIDs.
16
+ */
17
+ export declare function reidFragment<T>(items: ReadonlyArray<T>, placements?: Readonly<Record<string, unknown>>): {
18
+ items: T[];
19
+ placements?: Record<string, unknown>;
20
+ };
21
+ export declare function serializeClip(surface: ClipSurface, items: ReadonlyArray<unknown>, placements?: Readonly<Record<string, unknown>>): string;
22
+ export declare function parseClip(text: string): ClipPayload | null;
23
+ /** Write a fragment to the system clipboard. Resolves `false` on any failure. */
24
+ export declare function writeClip(surface: ClipSurface, items: ReadonlyArray<unknown>, placements?: Readonly<Record<string, unknown>>): Promise<boolean>;
25
+ /** Read a fragment from the system clipboard, or `null` if absent/unreadable. */
26
+ export declare function readClip(): Promise<ClipPayload | null>;
@@ -0,0 +1,82 @@
1
+ const CLIP_KEY = "__shwfed_clip";
2
+ const CLIP_VERSION = "v1";
3
+ const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
4
+ function freshId() {
5
+ if (typeof crypto !== "undefined" && "randomUUID" in crypto) return crypto.randomUUID();
6
+ return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
7
+ const r = Math.random() * 16 | 0;
8
+ return (c === "x" ? r : r & 3 | 8).toString(16);
9
+ });
10
+ }
11
+ function collectIds(node, into) {
12
+ if (Array.isArray(node)) {
13
+ for (const v of node) collectIds(v, into);
14
+ return;
15
+ }
16
+ if (node === null || typeof node !== "object") return;
17
+ for (const [k, v] of Object.entries(node)) {
18
+ if (k === "id" && typeof v === "string" && UUID_RE.test(v)) into.add(v);
19
+ collectIds(v, into);
20
+ }
21
+ }
22
+ function remap(node, map) {
23
+ if (Array.isArray(node)) return node.map((v) => remap(v, map));
24
+ if (node === null || typeof node !== "object") {
25
+ return typeof node === "string" ? map.get(node) ?? node : node;
26
+ }
27
+ const out = {};
28
+ for (const [k, v] of Object.entries(node)) {
29
+ out[map.get(k) ?? k] = remap(v, map);
30
+ }
31
+ return out;
32
+ }
33
+ function buildIdMap(items) {
34
+ const ids = /* @__PURE__ */ new Set();
35
+ collectIds(items, ids);
36
+ const map = /* @__PURE__ */ new Map();
37
+ for (const id of ids) map.set(id, freshId());
38
+ return map;
39
+ }
40
+ export function reidItems(items) {
41
+ return remap(items, buildIdMap(items));
42
+ }
43
+ export function reidFragment(items, placements) {
44
+ const map = buildIdMap(items);
45
+ return {
46
+ items: remap(items, map),
47
+ placements: placements ? remap(placements, map) : void 0
48
+ };
49
+ }
50
+ export function serializeClip(surface, items, placements) {
51
+ return JSON.stringify({ [CLIP_KEY]: CLIP_VERSION, surface, items, placements });
52
+ }
53
+ function isPlainObject(v) {
54
+ return v !== null && typeof v === "object" && !Array.isArray(v);
55
+ }
56
+ export function parseClip(text) {
57
+ try {
58
+ const o = JSON.parse(text);
59
+ if (!o || o[CLIP_KEY] !== CLIP_VERSION) return null;
60
+ if (o.surface !== "form" && o.surface !== "block") return null;
61
+ if (!Array.isArray(o.items)) return null;
62
+ const placements = isPlainObject(o.placements) ? o.placements : void 0;
63
+ return { surface: o.surface, items: o.items, placements };
64
+ } catch {
65
+ return null;
66
+ }
67
+ }
68
+ export async function writeClip(surface, items, placements) {
69
+ try {
70
+ await navigator.clipboard.writeText(serializeClip(surface, items, placements));
71
+ return true;
72
+ } catch {
73
+ return false;
74
+ }
75
+ }
76
+ export async function readClip() {
77
+ try {
78
+ return parseClip(await navigator.clipboard.readText());
79
+ } catch {
80
+ return null;
81
+ }
82
+ }
@@ -50,6 +50,10 @@ export type IdentifiableItem = Readonly<{
50
50
  export declare function validatePlacements(items: ReadonlyArray<IdentifiableItem>, layouts: ReadonlyArray<LayoutSetValue>, label: string): string | true;
51
51
  export declare function normalizeLayoutSet(ls: LayoutSetValue): LayoutSetValue;
52
52
  export declare function findFreePlacement(placements: Readonly<Record<string, PlacementValue>>, w: number, h: number): PlacementValue;
53
+ export declare function placeGroupAt(existing: Readonly<Record<string, PlacementValue>>, group: Readonly<Record<string, PlacementValue>>, target: {
54
+ x: number;
55
+ y: number;
56
+ }): Record<string, PlacementValue>;
53
57
  type AnySchema = Schema.Schema<any, any, never>;
54
58
  export declare function Slot(BlockSchemaUnion: AnySchema, configure: (env: Environment) => void): Schema.refine<{
55
59
  readonly blocks: readonly any[];
@@ -152,6 +152,41 @@ export function findFreePlacement(placements, w, h) {
152
152
  }
153
153
  return { area: [[1, 1], [1 + ww, 1 + hh]] };
154
154
  }
155
+ export function placeGroupAt(existing, group, target) {
156
+ const entries = Object.entries(group);
157
+ if (entries.length === 0) return {};
158
+ let gx1 = Infinity;
159
+ let gy1 = Infinity;
160
+ let gx2 = -Infinity;
161
+ let gy2 = -Infinity;
162
+ for (const [, p] of entries) {
163
+ const [[ax, ay], [bx, by]] = p.area;
164
+ if (ax < gx1) gx1 = ax;
165
+ if (ay < gy1) gy1 = ay;
166
+ if (bx > gx2) gx2 = bx;
167
+ if (by > gy2) gy2 = by;
168
+ }
169
+ const gw = gx2 - gx1;
170
+ const gh = gy2 - gy1;
171
+ const tx = Math.round(target.x);
172
+ const ty0 = Math.round(target.y);
173
+ const others = Object.values(existing).map((p) => p.area);
174
+ const overlaps = (a, b) => a[0][0] < b[1][0] && a[1][0] > b[0][0] && a[0][1] < b[1][1] && a[1][1] > b[0][1];
175
+ let ty = ty0;
176
+ for (let y = ty0; y < ty0 + 1e3; y++) {
177
+ const box = [[tx, y], [tx + gw, y + gh]];
178
+ if (!others.some((o) => overlaps(box, o))) {
179
+ ty = y;
180
+ break;
181
+ }
182
+ }
183
+ const sx = tx - gx1;
184
+ const sy = ty - gy1;
185
+ return Object.fromEntries(entries.map(([id, p]) => {
186
+ const [[ax, ay], [bx, by]] = p.area;
187
+ return [id, { ...p, area: [[ax + sx, ay + sy], [bx + sx, by + sy]] }];
188
+ }));
189
+ }
155
190
  export function Slot(BlockSchemaUnion, configure) {
156
191
  return Schema.Struct({
157
192
  blocks: Schema.Array(BlockSchemaUnion).annotations({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shwfed/config",
3
- "version": "2.3.28",
3
+ "version": "2.4.0",
4
4
  "description": "Configurable UI for SHWFED",
5
5
  "type": "module",
6
6
  "publishConfig": {