@shwfed/config 2.3.27 → 2.3.29

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 (178) hide show
  1. package/dist/mcp.mjs +3963 -1597
  2. package/dist/module.json +1 -1
  3. package/dist/preview/assets/{config-CRqRJ0oF.js → config-6IiXCmyu.js} +1 -1
  4. package/dist/preview/assets/{config-C45AT0tt.js → config-BJzUh1_G.js} +1 -1
  5. package/dist/preview/assets/{config-CIcy6Jwg.js → config-Bl80ye-i.js} +1 -1
  6. package/dist/preview/assets/{config-D0YS2Bpj.js → config-CZOeZ8ty.js} +1 -1
  7. package/dist/preview/assets/{config-l3KurfL5.js → config-DaZD4ZSa.js} +1 -1
  8. package/dist/preview/assets/{config-D-i-AFgH.js → config-DhsbcNzx.js} +1 -1
  9. package/dist/preview/assets/{config-CXaH7a2G.js → config-Diuyh0Ex.js} +1 -1
  10. package/dist/preview/assets/{config-Bv_hUugV.js → config-aK67Rsw5.js} +1 -1
  11. package/dist/preview/assets/{config-DrpESRR5.js → config-rpX_Mc6I.js} +1 -1
  12. package/dist/preview/assets/{definition.vue_vue_type_script_setup_true_lang-Ck8Pbwem.js → definition.vue_vue_type_script_setup_true_lang-C_jU8d47.js} +1 -1
  13. package/dist/preview/assets/index-2eQR4s3q.css +1 -0
  14. package/dist/preview/assets/index-DEF3_MKr.js +659 -0
  15. package/dist/preview/assets/index-Df-thth9.js +1 -0
  16. package/dist/preview/assets/{runtime-Df715bRA.js → runtime-3p1K6te5.js} +1 -1
  17. package/dist/preview/assets/{runtime-D42ecZyC.js → runtime-BcLnafic.js} +1 -1
  18. package/dist/preview/assets/{runtime-D6twt5H_.js → runtime-CSaV-359.js} +1 -1
  19. package/dist/preview/assets/{runtime-z_QPMN-R.js → runtime-CjR8Vi5N.js} +1 -1
  20. package/dist/preview/assets/{runtime-CvuGnDIa.js → runtime-D_fJCKX_.js} +1 -1
  21. package/dist/preview/assets/{runtime-tobnPKdV.js → runtime-DpeCgGEG.js} +1 -1
  22. package/dist/preview/assets/{runtime-CmCvUWLV.js → runtime-K2a1x0TJ.js} +1 -1
  23. package/dist/preview/assets/{runtime-BSASeqgI.js → runtime-g9Zu3VNQ.js} +1 -1
  24. package/dist/preview/assets/{runtime-DUyUjFqF.js → runtime-jTnh_6Dm.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.tabs/config.d.vue.ts +2 -0
  30. package/dist/runtime/components/config/blocks/2026-05-06/com.shwfed.block.tabs/config.vue +57 -3
  31. package/dist/runtime/components/config/blocks/2026-05-06/com.shwfed.block.tabs/config.vue.d.ts +2 -0
  32. package/dist/runtime/components/config/blocks/2026-05-06/com.shwfed.block.tabs/runtime.d.vue.ts +2 -0
  33. package/dist/runtime/components/config/blocks/2026-05-06/com.shwfed.block.tabs/runtime.vue +1 -0
  34. package/dist/runtime/components/config/blocks/2026-05-06/com.shwfed.block.tabs/runtime.vue.d.ts +2 -0
  35. package/dist/runtime/components/config/blocks/2026-05-06/com.shwfed.block.tabs/schema.d.ts +2 -0
  36. package/dist/runtime/components/config/blocks/2026-05-06/com.shwfed.block.tabs/schema.js +4 -0
  37. package/dist/runtime/components/config/config.vue +35 -0
  38. package/dist/runtime/components/config/use-editor.d.ts +11 -1
  39. package/dist/runtime/components/config/use-editor.js +27 -1
  40. package/dist/runtime/components/form/fields/2026-05-23/com.shwfed.form.field.tree.multi/config.d.vue.ts +4 -4
  41. package/dist/runtime/components/form/fields/2026-05-23/com.shwfed.form.field.tree.multi/config.vue.d.ts +4 -4
  42. package/dist/runtime/components/form/fields/2026-05-26/com.shwfed.form.field.tree.combobox.multi/config.d.vue.ts +127 -0
  43. package/dist/runtime/components/form/fields/2026-05-26/com.shwfed.form.field.tree.combobox.multi/config.vue +593 -0
  44. package/dist/runtime/components/form/fields/2026-05-26/com.shwfed.form.field.tree.combobox.multi/config.vue.d.ts +127 -0
  45. package/dist/runtime/components/form/fields/2026-05-26/com.shwfed.form.field.tree.combobox.multi/runtime.d.vue.ts +8 -0
  46. package/dist/runtime/components/form/fields/2026-05-26/com.shwfed.form.field.tree.combobox.multi/runtime.vue +465 -0
  47. package/dist/runtime/components/form/fields/2026-05-26/com.shwfed.form.field.tree.combobox.multi/runtime.vue.d.ts +8 -0
  48. package/dist/runtime/components/form/fields/2026-05-26/com.shwfed.form.field.tree.combobox.multi/schema.d.ts +95 -0
  49. package/dist/runtime/components/form/fields/2026-05-26/com.shwfed.form.field.tree.combobox.multi/schema.js +112 -0
  50. package/dist/runtime/components/form/fields/2026-05-26/com.shwfed.form.field.tree.combobox.single/config.d.vue.ts +125 -0
  51. package/dist/runtime/components/form/fields/2026-05-26/com.shwfed.form.field.tree.combobox.single/config.vue +525 -0
  52. package/dist/runtime/components/form/fields/2026-05-26/com.shwfed.form.field.tree.combobox.single/config.vue.d.ts +125 -0
  53. package/dist/runtime/components/form/fields/2026-05-26/com.shwfed.form.field.tree.combobox.single/runtime.d.vue.ts +8 -0
  54. package/dist/runtime/components/form/fields/2026-05-26/com.shwfed.form.field.tree.combobox.single/runtime.vue +460 -0
  55. package/dist/runtime/components/form/fields/2026-05-26/com.shwfed.form.field.tree.combobox.single/runtime.vue.d.ts +8 -0
  56. package/dist/runtime/components/form/fields/2026-05-26/com.shwfed.form.field.tree.combobox.single/schema.d.ts +92 -0
  57. package/dist/runtime/components/form/fields/2026-05-26/com.shwfed.form.field.tree.combobox.single/schema.js +104 -0
  58. package/dist/runtime/components/form/fields/2026-05-26/tree-combobox-shared.d.ts +35 -0
  59. package/dist/runtime/components/form/fields/2026-05-26/tree-combobox-shared.js +31 -0
  60. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.combobox.multi/config.d.vue.ts +163 -0
  61. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.combobox.multi/config.vue +745 -0
  62. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.combobox.multi/config.vue.d.ts +163 -0
  63. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.combobox.multi/runtime.d.vue.ts +8 -0
  64. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.combobox.multi/runtime.vue +383 -0
  65. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.combobox.multi/runtime.vue.d.ts +8 -0
  66. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.combobox.multi/schema.d.ts +264 -0
  67. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.combobox.multi/schema.js +183 -0
  68. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.combobox.single/config.d.vue.ts +163 -0
  69. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.combobox.single/config.vue +745 -0
  70. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.combobox.single/config.vue.d.ts +163 -0
  71. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.combobox.single/runtime.d.vue.ts +8 -0
  72. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.combobox.single/runtime.vue +402 -0
  73. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.combobox.single/runtime.vue.d.ts +8 -0
  74. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.combobox.single/schema.d.ts +264 -0
  75. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.combobox.single/schema.js +209 -0
  76. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.multi/config.d.vue.ts +129 -0
  77. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.multi/config.vue +618 -0
  78. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.multi/config.vue.d.ts +129 -0
  79. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.multi/runtime.d.vue.ts +8 -0
  80. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.multi/runtime.vue +501 -0
  81. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.multi/runtime.vue.d.ts +8 -0
  82. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.multi/schema.d.ts +99 -0
  83. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.multi/schema.js +133 -0
  84. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.single/config.d.vue.ts +127 -0
  85. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.single/config.vue +550 -0
  86. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.single/config.vue.d.ts +127 -0
  87. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.single/runtime.d.vue.ts +8 -0
  88. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.single/runtime.vue +496 -0
  89. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.single/runtime.vue.d.ts +8 -0
  90. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.single/schema.d.ts +96 -0
  91. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.single/schema.js +125 -0
  92. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.multi/config.d.vue.ts +133 -0
  93. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.multi/config.vue +605 -0
  94. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.multi/config.vue.d.ts +133 -0
  95. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.multi/runtime.d.vue.ts +8 -0
  96. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.multi/runtime.vue +401 -0
  97. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.multi/runtime.vue.d.ts +8 -0
  98. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.multi/schema.d.ts +102 -0
  99. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.multi/schema.js +142 -0
  100. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.single/config.d.vue.ts +131 -0
  101. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.single/config.vue +560 -0
  102. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.single/config.vue.d.ts +131 -0
  103. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.single/runtime.d.vue.ts +8 -0
  104. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.single/runtime.vue +395 -0
  105. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.single/runtime.vue.d.ts +8 -0
  106. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.single/schema.d.ts +96 -0
  107. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.single/schema.js +118 -0
  108. package/dist/runtime/components/form/fields/2026-05-28/tree-combobox-shared.d.ts +35 -0
  109. package/dist/runtime/components/form/fields/2026-05-28/tree-combobox-shared.js +31 -0
  110. package/dist/runtime/components/form/unit-config.vue +45 -1
  111. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-multi/config.d.vue.ts +131 -0
  112. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-multi/config.vue +607 -0
  113. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-multi/config.vue.d.ts +131 -0
  114. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-multi/runtime.d.vue.ts +9 -0
  115. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-multi/runtime.vue +447 -0
  116. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-multi/runtime.vue.d.ts +9 -0
  117. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-multi/schema.d.ts +90 -0
  118. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-multi/schema.js +143 -0
  119. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-single/config.d.vue.ts +129 -0
  120. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-single/config.vue +538 -0
  121. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-single/config.vue.d.ts +129 -0
  122. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-single/runtime.d.vue.ts +9 -0
  123. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-single/runtime.vue +429 -0
  124. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-single/runtime.vue.d.ts +9 -0
  125. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-single/schema.d.ts +87 -0
  126. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-single/schema.js +135 -0
  127. package/dist/runtime/components/table/columns/2026-05-27/tree-combobox-shared.d.ts +35 -0
  128. package/dist/runtime/components/table/columns/2026-05-27/tree-combobox-shared.js +31 -0
  129. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-multi/config.d.vue.ts +183 -0
  130. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-multi/config.vue +931 -0
  131. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-multi/config.vue.d.ts +183 -0
  132. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-multi/runtime.d.vue.ts +9 -0
  133. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-multi/runtime.vue +463 -0
  134. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-multi/runtime.vue.d.ts +9 -0
  135. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-multi/schema.d.ts +283 -0
  136. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-multi/schema.js +275 -0
  137. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-single/config.d.vue.ts +183 -0
  138. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-single/config.vue +931 -0
  139. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-single/config.vue.d.ts +183 -0
  140. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-single/runtime.d.vue.ts +9 -0
  141. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-single/runtime.vue +414 -0
  142. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-single/runtime.vue.d.ts +9 -0
  143. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-single/schema.d.ts +283 -0
  144. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-single/schema.js +275 -0
  145. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-multi/config.d.vue.ts +133 -0
  146. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-multi/config.vue +632 -0
  147. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-multi/config.vue.d.ts +133 -0
  148. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-multi/runtime.d.vue.ts +9 -0
  149. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-multi/runtime.vue +461 -0
  150. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-multi/runtime.vue.d.ts +9 -0
  151. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-multi/schema.d.ts +93 -0
  152. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-multi/schema.js +161 -0
  153. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-single/config.d.vue.ts +131 -0
  154. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-single/config.vue +563 -0
  155. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-single/config.vue.d.ts +131 -0
  156. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-single/runtime.d.vue.ts +9 -0
  157. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-single/runtime.vue +443 -0
  158. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-single/runtime.vue.d.ts +9 -0
  159. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-single/schema.d.ts +90 -0
  160. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-single/schema.js +153 -0
  161. package/dist/runtime/components/table/columns/2026-05-28/tree-combobox-shared.d.ts +35 -0
  162. package/dist/runtime/components/table/columns/2026-05-28/tree-combobox-shared.js +31 -0
  163. package/dist/runtime/components/table/config.vue +16 -16
  164. package/dist/runtime/components/ui/command/CommandItem.d.vue.ts +7 -0
  165. package/dist/runtime/components/ui/command/CommandItem.vue +13 -4
  166. package/dist/runtime/components/ui/command/CommandItem.vue.d.ts +7 -0
  167. package/dist/runtime/components/ui/tree/Tree.d.vue.ts +2 -0
  168. package/dist/runtime/components/ui/tree/Tree.vue +7 -2
  169. package/dist/runtime/components/ui/tree/Tree.vue.d.ts +2 -0
  170. package/dist/runtime/components/ui/tree/TreeNode.vue +16 -26
  171. package/dist/runtime/share/clipboard.d.ts +26 -0
  172. package/dist/runtime/share/clipboard.js +82 -0
  173. package/dist/runtime/share/layout.d.ts +4 -0
  174. package/dist/runtime/share/layout.js +35 -0
  175. package/package.json +1 -1
  176. package/dist/preview/assets/index-BCE-G4Ha.css +0 -1
  177. package/dist/preview/assets/index-C3Ycah5_.js +0 -643
  178. package/dist/preview/assets/index-hWT4_I5k.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,26 +485,17 @@ 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
+ case "com.shwfed.table.column.combobox-single":
488
489
  return {
489
490
  id,
490
491
  type,
491
492
  compatibilityDate,
492
493
  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
494
  size: 200,
495
+ write: { kind: "binding", binding: "" },
505
496
  options: { kind: "static", items: [] }
506
497
  };
507
- case "com.shwfed.table.column.combobox-single":
498
+ case "com.shwfed.table.column.tree-combobox-single":
508
499
  return {
509
500
  id,
510
501
  type,
@@ -512,17 +503,26 @@ function getColumnDefaults(id, type, compatibilityDate) {
512
503
  title: [{ locale: "zh", message: "" }],
513
504
  binding: "",
514
505
  size: 200,
515
- options: { kind: "static", items: [] }
506
+ dataSource: { data: "[]" },
507
+ nodeKey: "string(node.id)",
508
+ nodeChildren: "has(node.children) ? node.children : null",
509
+ nodeLabel: [{ locale: "zh", message: "{{ node.label }}" }],
510
+ expandAll: false
516
511
  };
517
- case "com.shwfed.table.column.combobox-single.remote":
512
+ case "com.shwfed.table.column.tree-combobox-multi":
518
513
  return {
519
514
  id,
520
515
  type,
521
516
  compatibilityDate,
522
517
  title: [{ locale: "zh", message: "" }],
523
- accessor: "",
518
+ binding: "",
524
519
  size: 200,
525
- options: { kind: "static", items: [] }
520
+ dataSource: { data: "[]" },
521
+ nodeKey: "string(node.id)",
522
+ nodeChildren: "has(node.children) ? node.children : null",
523
+ nodeLabel: [{ locale: "zh", message: "{{ node.label }}" }],
524
+ cascade: "independent",
525
+ expandAll: false
526
526
  };
527
527
  default:
528
528
  return { id, type, compatibilityDate };
@@ -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 = {} & {
@@ -34,6 +34,7 @@ declare const __VLS_export: <Node>(__VLS_props: NonNullable<Awaited<typeof __VLS
34
34
  onMove?: ((payload: MoveEventPayload) => any) | undefined;
35
35
  "onUpdate:modelValue"?: ((value: string | string[] | undefined) => any) | undefined;
36
36
  "onUpdate:roots"?: ((value: Node[]) => any) | undefined;
37
+ "onUpdate:expanded"?: ((value: string[]) => any) | undefined;
37
38
  }> & (typeof globalThis extends {
38
39
  __VLS_PROPS_FALLBACK: infer P;
39
40
  } ? P : {});
@@ -50,6 +51,7 @@ declare const __VLS_export: <Node>(__VLS_props: NonNullable<Awaited<typeof __VLS
50
51
  emit: {
51
52
  (e: "update:modelValue", value: NodeKey | NodeKey[] | undefined): void;
52
53
  (e: "update:roots", value: Node[]): void;
54
+ (e: "update:expanded", value: NodeKey[]): void;
53
55
  (e: "move", payload: MoveEventPayload): void;
54
56
  };
55
57
  }>) => import("vue").VNode & {
@@ -1,5 +1,5 @@
1
1
  <script setup>
2
- import { computed, watch } from "vue";
2
+ import { computed, watch, watchEffect } from "vue";
3
3
  import { useTreeState } from "./useTreeState";
4
4
  import TreeNode from "./TreeNode.vue";
5
5
  defineOptions({ name: "UiTree" });
@@ -19,7 +19,7 @@ const props = defineProps({
19
19
  initialExpanded: { type: Array, required: false, default: () => [] },
20
20
  showFocusedRow: { type: Boolean, required: false, default: true }
21
21
  });
22
- const emit = defineEmits(["update:modelValue", "update:roots", "move"]);
22
+ const emit = defineEmits(["update:modelValue", "update:roots", "update:expanded", "move"]);
23
23
  defineSlots();
24
24
  function readInitialSelection() {
25
25
  if (props.selectionMode === "none") return [];
@@ -57,6 +57,11 @@ const state = useTreeState({
57
57
  onSelectionChange
58
58
  });
59
59
  watch(rootsRef, () => state.syncRoots());
60
+ watchEffect(() => {
61
+ const next = [];
62
+ for (const k of state.expanded) next.push(k);
63
+ emit("update:expanded", next);
64
+ });
60
65
  watch(
61
66
  () => props.modelValue,
62
67
  (v) => {
@@ -34,6 +34,7 @@ declare const __VLS_export: <Node>(__VLS_props: NonNullable<Awaited<typeof __VLS
34
34
  onMove?: ((payload: MoveEventPayload) => any) | undefined;
35
35
  "onUpdate:modelValue"?: ((value: string | string[] | undefined) => any) | undefined;
36
36
  "onUpdate:roots"?: ((value: Node[]) => any) | undefined;
37
+ "onUpdate:expanded"?: ((value: string[]) => any) | undefined;
37
38
  }> & (typeof globalThis extends {
38
39
  __VLS_PROPS_FALLBACK: infer P;
39
40
  } ? P : {});
@@ -50,6 +51,7 @@ declare const __VLS_export: <Node>(__VLS_props: NonNullable<Awaited<typeof __VLS
50
51
  emit: {
51
52
  (e: "update:modelValue", value: NodeKey | NodeKey[] | undefined): void;
52
53
  (e: "update:roots", value: Node[]): void;
54
+ (e: "update:expanded", value: NodeKey[]): void;
53
55
  (e: "move", payload: MoveEventPayload): void;
54
56
  };
55
57
  }>) => import("vue").VNode & {
@@ -2,7 +2,6 @@
2
2
  import { computed } from "vue";
3
3
  import { Icon } from "@iconify/vue";
4
4
  import { cn } from "../../../utils/cn";
5
- import { Checkbox } from "../checkbox";
6
5
  defineOptions({ name: "UiTreeNode", inheritAttrs: false });
7
6
  const props = defineProps({
8
7
  node: { type: null, required: true },
@@ -77,10 +76,16 @@ function onToggleArrow() {
77
76
  if (!expandable.value) return;
78
77
  emit("toggle-expand", key.value);
79
78
  }
80
- function onToggleSelect() {
81
- if (props.selectionMode === "none") return;
82
- if (!userSelectable.value) return;
83
- emit("toggle-select", key.value);
79
+ function onRowClick() {
80
+ if (expandable.value && !userSelectable.value) {
81
+ emit("toggle-expand", key.value);
82
+ return;
83
+ }
84
+ if (props.selectionMode !== "none" && userSelectable.value) {
85
+ emit("toggle-select", key.value);
86
+ return;
87
+ }
88
+ emit("focus-row", key.value);
84
89
  }
85
90
  const ariaSelected = computed(() => {
86
91
  if (props.selectionMode === "none") return void 0;
@@ -109,11 +114,13 @@ const showChildren = computed(
109
114
  <div
110
115
  v-if="subtreeMatches"
111
116
  :class="cn(
112
- 'group flex items-center justify-between gap-2 rounded px-1 py-1 outline-none',
117
+ 'group flex items-center justify-between gap-2 rounded px-1 py-1 outline-none transition-colors',
118
+ selectionMode !== 'none' && userSelectable && 'cursor-pointer hover:bg-zinc-100/70',
119
+ selectedFlag && !indeterminateFlag && 'bg-(--primary)/10 hover:bg-(--primary)/15',
113
120
  showFocusedRow && focusedKey === key && 'bg-(--primary)/10'
114
121
  )"
115
122
  tabindex="-1"
116
- @click.stop="emit('focus-row', key)"
123
+ @click.stop="onRowClick"
117
124
  >
118
125
  <!-- LEFT: indent + arrow + selector + #node slot -->
119
126
  <div class="flex items-center gap-1 min-w-0 flex-1">
@@ -140,25 +147,8 @@ const showChildren = computed(
140
147
  class="inline-block size-4 shrink-0"
141
148
  />
142
149
 
143
- <!-- selector: shadcn-styled Checkbox for multi; raw radio for single
144
- (no standalone shadcn radio RadioGroupItem requires a group). -->
145
- <template v-if="selectionMode !== 'none' && userSelectable">
146
- <Checkbox
147
- v-if="selectionMode === 'multi'"
148
- :model-value="indeterminateFlag ? 'indeterminate' : selectedFlag"
149
- data-tree-toggle="checkbox"
150
- @update:model-value="onToggleSelect"
151
- @click.stop
152
- />
153
- <input
154
- v-else
155
- type="radio"
156
- class="size-4 shrink-0 accent-(--primary) cursor-pointer"
157
- :checked="selectedFlag"
158
- data-tree-toggle="radio"
159
- @click.stop="onToggleSelect"
160
- >
161
- </template>
150
+ <!-- selection is driven entirely by row click; selection state is
151
+ conveyed via the row background highlight. -->
162
152
 
163
153
  <div class="min-w-0 flex-1">
164
154
  <slot
@@ -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({