@shwfed/config 2.12.0 → 2.12.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (186) hide show
  1. package/dist/module.json +1 -1
  2. package/dist/module.mjs +10 -0
  3. package/dist/runtime/components/form/config.vue +17 -6
  4. package/dist/runtime/components/form/fields/2026-04-24/com.shwfed.form.field.combobox.single/config.d.vue.ts +2 -2
  5. package/dist/runtime/components/form/fields/2026-04-24/com.shwfed.form.field.combobox.single/config.vue.d.ts +2 -2
  6. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.date/config.d.vue.ts +2 -0
  7. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.date/config.vue +22 -0
  8. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.date/config.vue.d.ts +2 -0
  9. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.date/runtime.vue +5 -0
  10. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.date/schema.d.ts +1 -0
  11. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.date/schema.js +12 -0
  12. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.daterange/config.d.vue.ts +2 -0
  13. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.daterange/config.vue +22 -0
  14. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.daterange/config.vue.d.ts +2 -0
  15. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.daterange/runtime.vue +5 -0
  16. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.daterange/schema.d.ts +1 -0
  17. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.daterange/schema.js +12 -0
  18. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.datetime/config.d.vue.ts +2 -0
  19. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.datetime/config.vue +22 -0
  20. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.datetime/config.vue.d.ts +2 -0
  21. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.datetime/runtime.vue +5 -0
  22. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.datetime/schema.d.ts +1 -0
  23. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.datetime/schema.js +12 -0
  24. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.datetimerange/config.d.vue.ts +2 -0
  25. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.datetimerange/config.vue +22 -0
  26. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.datetimerange/config.vue.d.ts +2 -0
  27. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.datetimerange/runtime.vue +5 -0
  28. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.datetimerange/schema.d.ts +1 -0
  29. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.datetimerange/schema.js +12 -0
  30. package/dist/runtime/components/form/fields/2026-05-13/com.shwfed.form.field.combobox.single.remote/config.d.vue.ts +2 -2
  31. package/dist/runtime/components/form/fields/2026-05-13/com.shwfed.form.field.combobox.single.remote/config.vue.d.ts +2 -2
  32. package/dist/runtime/components/form/fields/2026-05-13/com.shwfed.form.field.list/row.vue +8 -1
  33. package/dist/runtime/components/form/fields/2026-05-23/com.shwfed.form.field.tree.multi/config.d.vue.ts +24 -24
  34. package/dist/runtime/components/form/fields/2026-05-23/com.shwfed.form.field.tree.multi/config.vue.d.ts +24 -24
  35. package/dist/runtime/components/form/fields/2026-05-24/com.shwfed.form.field.month/config.d.vue.ts +2 -0
  36. package/dist/runtime/components/form/fields/2026-05-24/com.shwfed.form.field.month/config.vue +22 -0
  37. package/dist/runtime/components/form/fields/2026-05-24/com.shwfed.form.field.month/config.vue.d.ts +2 -0
  38. package/dist/runtime/components/form/fields/2026-05-24/com.shwfed.form.field.month/runtime.vue +5 -0
  39. package/dist/runtime/components/form/fields/2026-05-24/com.shwfed.form.field.month/schema.d.ts +1 -0
  40. package/dist/runtime/components/form/fields/2026-05-24/com.shwfed.form.field.month/schema.js +12 -0
  41. package/dist/runtime/components/form/fields/2026-05-24/com.shwfed.form.field.monthrange/config.d.vue.ts +2 -0
  42. package/dist/runtime/components/form/fields/2026-05-24/com.shwfed.form.field.monthrange/config.vue +22 -0
  43. package/dist/runtime/components/form/fields/2026-05-24/com.shwfed.form.field.monthrange/config.vue.d.ts +2 -0
  44. package/dist/runtime/components/form/fields/2026-05-24/com.shwfed.form.field.monthrange/runtime.vue +5 -0
  45. package/dist/runtime/components/form/fields/2026-05-24/com.shwfed.form.field.monthrange/schema.d.ts +1 -0
  46. package/dist/runtime/components/form/fields/2026-05-24/com.shwfed.form.field.monthrange/schema.js +12 -0
  47. package/dist/runtime/components/form/fields/2026-05-25/com.shwfed.form.field.combobox.multi/config.d.vue.ts +2 -2
  48. package/dist/runtime/components/form/fields/2026-05-25/com.shwfed.form.field.combobox.multi/config.vue.d.ts +2 -2
  49. package/dist/runtime/components/form/fields/2026-05-26/com.shwfed.form.field.tree.combobox.multi/config.d.vue.ts +24 -24
  50. package/dist/runtime/components/form/fields/2026-05-26/com.shwfed.form.field.tree.combobox.multi/config.vue.d.ts +24 -24
  51. package/dist/runtime/components/form/fields/2026-05-26/com.shwfed.form.field.tree.combobox.single/config.d.vue.ts +22 -22
  52. package/dist/runtime/components/form/fields/2026-05-26/com.shwfed.form.field.tree.combobox.single/config.vue.d.ts +22 -22
  53. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.combobox.multi/config.d.vue.ts +32 -32
  54. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.combobox.multi/config.vue.d.ts +32 -32
  55. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.combobox.multi/runtime.vue +9 -1
  56. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.combobox.single/config.d.vue.ts +32 -32
  57. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.combobox.single/config.vue.d.ts +32 -32
  58. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.combobox.single/runtime.vue +9 -1
  59. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.multi/config.d.vue.ts +24 -24
  60. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.multi/config.vue.d.ts +24 -24
  61. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.multi/runtime.vue +19 -1
  62. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.single/config.d.vue.ts +22 -22
  63. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.single/config.vue.d.ts +22 -22
  64. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.single/runtime.vue +19 -1
  65. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.multi/config.d.vue.ts +24 -24
  66. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.multi/config.vue.d.ts +24 -24
  67. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.multi/runtime.vue +20 -1
  68. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.single/config.d.vue.ts +22 -22
  69. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.single/config.vue.d.ts +22 -22
  70. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.single/runtime.vue +20 -1
  71. package/dist/runtime/components/form/fields/2026-06-14/com.shwfed.form.field.combobox.multi/config.d.vue.ts +32 -32
  72. package/dist/runtime/components/form/fields/2026-06-14/com.shwfed.form.field.combobox.multi/config.vue.d.ts +32 -32
  73. package/dist/runtime/components/form/fields/2026-06-14/com.shwfed.form.field.combobox.multi/runtime.vue +9 -1
  74. package/dist/runtime/components/form/fields/2026-06-14/com.shwfed.form.field.combobox.single/config.d.vue.ts +32 -32
  75. package/dist/runtime/components/form/fields/2026-06-14/com.shwfed.form.field.combobox.single/config.vue.d.ts +32 -32
  76. package/dist/runtime/components/form/fields/2026-06-14/com.shwfed.form.field.combobox.single/runtime.vue +9 -1
  77. package/dist/runtime/components/form/index.vue +6 -3
  78. package/dist/runtime/components/form/utils/ai-field-tools.d.ts +11 -0
  79. package/dist/runtime/components/form/utils/ai-field-tools.js +282 -0
  80. package/dist/runtime/components/form/utils/form-vars.js +2 -1
  81. package/dist/runtime/components/form/utils/resolve.d.ts +15 -0
  82. package/dist/runtime/components/form/utils/resolve.js +13 -0
  83. package/dist/runtime/components/head.d.vue.ts +13 -0
  84. package/dist/runtime/components/head.vue +69 -0
  85. package/dist/runtime/components/head.vue.d.ts +13 -0
  86. package/dist/runtime/components/sidebar/config.d.vue.ts +7 -0
  87. package/dist/runtime/components/sidebar/config.vue +302 -0
  88. package/dist/runtime/components/sidebar/config.vue.d.ts +7 -0
  89. package/dist/runtime/components/sidebar/favorites.d.ts +18 -0
  90. package/dist/runtime/components/sidebar/favorites.js +20 -0
  91. package/dist/runtime/components/sidebar/footer.d.vue.ts +11 -0
  92. package/dist/runtime/components/sidebar/footer.vue +49 -0
  93. package/dist/runtime/components/sidebar/footer.vue.d.ts +11 -0
  94. package/dist/runtime/components/sidebar/index.d.vue.ts +50 -0
  95. package/dist/runtime/components/sidebar/index.vue +100 -0
  96. package/dist/runtime/components/sidebar/index.vue.d.ts +50 -0
  97. package/dist/runtime/components/sidebar/node.d.vue.ts +9 -0
  98. package/dist/runtime/components/sidebar/node.vue +102 -0
  99. package/dist/runtime/components/sidebar/node.vue.d.ts +9 -0
  100. package/dist/runtime/components/sidebar/schema.d.ts +72 -0
  101. package/dist/runtime/components/sidebar/schema.js +84 -0
  102. package/dist/runtime/components/sidebar/tree.d.vue.ts +10 -0
  103. package/dist/runtime/components/sidebar/tree.vue +260 -0
  104. package/dist/runtime/components/sidebar/tree.vue.d.ts +10 -0
  105. package/dist/runtime/components/sidebar/types.d.ts +19 -0
  106. package/dist/runtime/components/sidebar/types.js +0 -0
  107. package/dist/runtime/components/sidebar/use-editor.d.ts +18 -0
  108. package/dist/runtime/components/sidebar/use-editor.js +43 -0
  109. package/dist/runtime/components/table/ai-generate.system.md +6 -0
  110. package/dist/runtime/components/table/ai-generate.vue +18 -17
  111. package/dist/runtime/components/table/columns/2026-05-24/com.shwfed.table.column.combobox-single.remote.options-remote/config.d.vue.ts +4 -4
  112. package/dist/runtime/components/table/columns/2026-05-24/com.shwfed.table.column.combobox-single.remote.options-remote/config.vue.d.ts +4 -4
  113. package/dist/runtime/components/table/columns/2026-05-24/com.shwfed.table.column.combobox-single.remote.options-static/config.d.vue.ts +2 -2
  114. package/dist/runtime/components/table/columns/2026-05-24/com.shwfed.table.column.combobox-single.remote.options-static/config.vue.d.ts +2 -2
  115. package/dist/runtime/components/table/columns/2026-05-25/com.shwfed.table.column.combobox-multi.remote.options-remote/config.d.vue.ts +4 -4
  116. package/dist/runtime/components/table/columns/2026-05-25/com.shwfed.table.column.combobox-multi.remote.options-remote/config.vue.d.ts +4 -4
  117. package/dist/runtime/components/table/columns/2026-05-25/com.shwfed.table.column.combobox-multi.remote.options-static/config.d.vue.ts +2 -2
  118. package/dist/runtime/components/table/columns/2026-05-25/com.shwfed.table.column.combobox-multi.remote.options-static/config.vue.d.ts +2 -2
  119. package/dist/runtime/components/table/columns/2026-05-26/com.shwfed.table.column.combobox-multi/config.d.vue.ts +36 -36
  120. package/dist/runtime/components/table/columns/2026-05-26/com.shwfed.table.column.combobox-multi/config.vue.d.ts +36 -36
  121. package/dist/runtime/components/table/columns/2026-05-26/com.shwfed.table.column.combobox-multi.remote/config.d.vue.ts +42 -42
  122. package/dist/runtime/components/table/columns/2026-05-26/com.shwfed.table.column.combobox-multi.remote/config.vue.d.ts +42 -42
  123. package/dist/runtime/components/table/columns/2026-05-26/com.shwfed.table.column.combobox-single/config.d.vue.ts +36 -36
  124. package/dist/runtime/components/table/columns/2026-05-26/com.shwfed.table.column.combobox-single/config.vue.d.ts +36 -36
  125. package/dist/runtime/components/table/columns/2026-05-26/com.shwfed.table.column.combobox-single.remote/config.d.vue.ts +42 -42
  126. package/dist/runtime/components/table/columns/2026-05-26/com.shwfed.table.column.combobox-single.remote/config.vue.d.ts +42 -42
  127. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-multi/config.d.vue.ts +4 -4
  128. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-multi/config.vue.d.ts +4 -4
  129. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-single/config.d.vue.ts +2 -2
  130. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-single/config.vue.d.ts +2 -2
  131. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-multi/config.d.vue.ts +28 -28
  132. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-multi/config.vue.d.ts +28 -28
  133. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-single/config.d.vue.ts +28 -28
  134. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-single/config.vue.d.ts +28 -28
  135. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-multi/config.d.vue.ts +4 -4
  136. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-multi/config.vue.d.ts +4 -4
  137. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-single/config.d.vue.ts +2 -2
  138. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-single/config.vue.d.ts +2 -2
  139. package/dist/runtime/components/table/columns/2026-06-14/com.shwfed.table.column.combobox-multi/config.d.vue.ts +28 -28
  140. package/dist/runtime/components/table/columns/2026-06-14/com.shwfed.table.column.combobox-multi/config.vue.d.ts +28 -28
  141. package/dist/runtime/components/table/columns/2026-06-14/com.shwfed.table.column.combobox-single/config.d.vue.ts +28 -28
  142. package/dist/runtime/components/table/columns/2026-06-14/com.shwfed.table.column.combobox-single/config.vue.d.ts +28 -28
  143. package/dist/runtime/components/table/columns/2026-06-14/com.shwfed.table.column.tree-combobox-multi/config.d.vue.ts +4 -4
  144. package/dist/runtime/components/table/columns/2026-06-14/com.shwfed.table.column.tree-combobox-multi/config.vue.d.ts +4 -4
  145. package/dist/runtime/components/table/columns/2026-06-14/com.shwfed.table.column.tree-combobox-single/config.d.vue.ts +2 -2
  146. package/dist/runtime/components/table/columns/2026-06-14/com.shwfed.table.column.tree-combobox-single/config.vue.d.ts +2 -2
  147. package/dist/runtime/components/table/columns/2026-06-17/com.shwfed.table.column.date-input/config.vue +33 -0
  148. package/dist/runtime/components/table/columns/2026-06-17/com.shwfed.table.column.date-input/runtime.vue +5 -0
  149. package/dist/runtime/components/table/columns/2026-06-17/com.shwfed.table.column.date-input/schema.d.ts +1 -0
  150. package/dist/runtime/components/table/columns/2026-06-17/com.shwfed.table.column.date-input/schema.js +6 -1
  151. package/dist/runtime/components/table/columns/2026-06-22/com.shwfed.table.column.date-range-input/config.vue +33 -0
  152. package/dist/runtime/components/table/columns/2026-06-22/com.shwfed.table.column.date-range-input/runtime.vue +5 -0
  153. package/dist/runtime/components/table/columns/2026-06-22/com.shwfed.table.column.date-range-input/schema.d.ts +1 -0
  154. package/dist/runtime/components/table/columns/2026-06-22/com.shwfed.table.column.date-range-input/schema.js +6 -1
  155. package/dist/runtime/components/table/utils/ai-tools.js +50 -1
  156. package/dist/runtime/components/table/utils/shared.d.ts +1 -0
  157. package/dist/runtime/components/table/utils/shared.js +10 -0
  158. package/dist/runtime/components/ui/alert-dialog/AlertDialogCancel.vue +1 -1
  159. package/dist/runtime/components/ui/chat/ChatPrompt.d.vue.ts +11 -1
  160. package/dist/runtime/components/ui/chat/ChatPrompt.vue +10 -0
  161. package/dist/runtime/components/ui/chat/ChatPrompt.vue.d.ts +11 -1
  162. package/dist/runtime/components/ui/expression-editor/CodeMirrorInput.d.vue.ts +1 -0
  163. package/dist/runtime/components/ui/expression-editor/CodeMirrorInput.vue +8 -0
  164. package/dist/runtime/components/ui/expression-editor/CodeMirrorInput.vue.d.ts +1 -0
  165. package/dist/runtime/components/ui/expression-editor/ExpressionEditor.d.vue.ts +3 -2
  166. package/dist/runtime/components/ui/expression-editor/ExpressionEditor.vue +51 -9
  167. package/dist/runtime/components/ui/expression-editor/ExpressionEditor.vue.d.ts +3 -2
  168. package/dist/runtime/components/ui/expression-editor/option-chip-extension.d.ts +4 -0
  169. package/dist/runtime/components/ui/expression-editor/option-chip-extension.js +119 -0
  170. package/dist/runtime/components/ui/expression-editor/option-refs.d.ts +6 -0
  171. package/dist/runtime/components/ui/expression-editor/option-refs.js +24 -0
  172. package/dist/runtime/components/ui/expression-editor/picker-entries.d.ts +2 -1
  173. package/dist/runtime/components/ui/expression-editor/picker-entries.js +12 -2
  174. package/dist/runtime/share/disabled-date.d.ts +34 -0
  175. package/dist/runtime/share/disabled-date.js +13 -0
  176. package/dist/runtime/utils/ai/index.js +24 -1
  177. package/dist/runtime/utils/cel-context.d.ts +1 -0
  178. package/dist/runtime/utils/cel-context.js +1 -0
  179. package/dist/runtime/utils/disabled-date.d.ts +26 -0
  180. package/dist/runtime/utils/disabled-date.js +21 -0
  181. package/dist/runtime/utils/selections-registry.d.ts +40 -6
  182. package/dist/runtime/utils/selections-registry.js +19 -4
  183. package/dist/runtime/vendor/cel-js/CLAUDE.md +2 -0
  184. package/dist/runtime/vendor/cel-js/PROMPT.md +2 -0
  185. package/dist/runtime/vendor/cel-js/lib/functions.js +33 -0
  186. package/package.json +1 -1
@@ -0,0 +1,119 @@
1
+ import { Facet, RangeSetBuilder } from "@codemirror/state";
2
+ import {
3
+ Decoration,
4
+ EditorView,
5
+ ViewPlugin,
6
+ WidgetType
7
+ } from "@codemirror/view";
8
+ import { scanOptionRefs } from "./option-refs.js";
9
+ export const optionLookupFacet = Facet.define({
10
+ combine: (values) => values.length > 0 ? values[values.length - 1] : /* @__PURE__ */ new Map()
11
+ });
12
+ class OptionChipWidget extends WidgetType {
13
+ constructor(id, name) {
14
+ super();
15
+ this.id = id;
16
+ this.name = name;
17
+ }
18
+ eq(other) {
19
+ return other.id === this.id && other.name === this.name;
20
+ }
21
+ toDOM() {
22
+ const chip = document.createElement("span");
23
+ chip.className = "cm-option-chip";
24
+ chip.setAttribute("data-option-id", this.id);
25
+ const tag = document.createElement("span");
26
+ tag.className = "cm-option-chip-tag";
27
+ tag.textContent = "\u5168\u90E8\u9009\u9879";
28
+ chip.appendChild(tag);
29
+ const text = document.createElement("span");
30
+ text.className = "cm-option-chip-label";
31
+ if (this.name !== null) {
32
+ text.textContent = this.name;
33
+ chip.title = `\u5168\u90E8\u9009\u9879 \xB7 ${this.name}`;
34
+ } else {
35
+ chip.classList.add("cm-option-chip-dangling");
36
+ const short = this.id.length > 8 ? `${this.id.slice(0, 8)}\u2026` : this.id;
37
+ text.textContent = short;
38
+ chip.title = `\u672A\u77E5\u5B57\u6BB5 ${this.id}`;
39
+ }
40
+ chip.appendChild(text);
41
+ return chip;
42
+ }
43
+ ignoreEvent() {
44
+ return false;
45
+ }
46
+ }
47
+ function buildChips(view) {
48
+ const lookup = view.state.facet(optionLookupFacet);
49
+ const builder = new RangeSetBuilder();
50
+ for (const ref of scanOptionRefs(view.state.doc.toString())) {
51
+ const name = lookup.get(ref.id) ?? null;
52
+ builder.add(
53
+ ref.from,
54
+ ref.to,
55
+ Decoration.replace({ widget: new OptionChipWidget(ref.id, name) })
56
+ );
57
+ }
58
+ return builder.finish();
59
+ }
60
+ const chipPlugin = ViewPlugin.fromClass(
61
+ class {
62
+ decorations;
63
+ constructor(view) {
64
+ this.decorations = buildChips(view);
65
+ }
66
+ update(update) {
67
+ if (update.docChanged || update.viewportChanged || update.startState.facet(optionLookupFacet) !== update.state.facet(optionLookupFacet)) {
68
+ this.decorations = buildChips(update.view);
69
+ }
70
+ }
71
+ },
72
+ {
73
+ decorations: (plugin) => plugin.decorations,
74
+ // Atomic so the caret steps over a chip and Backspace removes the whole
75
+ // `options["id"]` at once — matching the selection chip's delete-as-unit feel.
76
+ provide: (plugin) => EditorView.atomicRanges.of((view) => view.plugin(plugin)?.decorations ?? Decoration.none)
77
+ }
78
+ );
79
+ const chipTheme = EditorView.theme({
80
+ ".cm-option-chip": {
81
+ display: "inline-flex",
82
+ alignItems: "center",
83
+ gap: "0.25rem",
84
+ margin: "0 1px",
85
+ padding: "0.125rem 0.25rem",
86
+ borderRadius: "0.25rem",
87
+ background: "#fffbeb",
88
+ border: "1px solid #fde68a",
89
+ color: "#b45309",
90
+ fontFamily: "ui-sans-serif, system-ui, sans-serif",
91
+ verticalAlign: "baseline",
92
+ cursor: "default",
93
+ whiteSpace: "nowrap"
94
+ },
95
+ ".cm-option-chip-dangling": {
96
+ background: "#fef2f2",
97
+ borderColor: "#fecaca",
98
+ color: "#b91c1c"
99
+ },
100
+ ".cm-option-chip-tag": {
101
+ borderRadius: "0.125rem",
102
+ background: "#fef3c7",
103
+ padding: "0.05rem 0.2rem",
104
+ fontSize: "9px",
105
+ lineHeight: "1",
106
+ color: "#d97706"
107
+ },
108
+ ".cm-option-chip-dangling .cm-option-chip-tag": {
109
+ background: "#fee2e2",
110
+ color: "#b91c1c"
111
+ },
112
+ ".cm-option-chip-label": {
113
+ fontSize: "0.75rem",
114
+ lineHeight: "1.1"
115
+ }
116
+ });
117
+ export function optionChips() {
118
+ return [chipPlugin, chipTheme];
119
+ }
@@ -0,0 +1,6 @@
1
+ export type OptionRef = {
2
+ from: number;
3
+ to: number;
4
+ id: string;
5
+ };
6
+ export declare function scanOptionRefs(text: string): OptionRef[];
@@ -0,0 +1,24 @@
1
+ import { OPTIONS_VAR } from "../../../utils/cel-context.js";
2
+ const OPTION_REF_RE = new RegExp(
3
+ `(?<![\\w$.])${OPTIONS_VAR}\\[\\??("(?:[^"\\\\]|\\\\.)*")\\]`,
4
+ "g"
5
+ );
6
+ export function scanOptionRefs(text) {
7
+ const out = [];
8
+ OPTION_REF_RE.lastIndex = 0;
9
+ let match;
10
+ while ((match = OPTION_REF_RE.exec(text)) !== null) {
11
+ let id;
12
+ try {
13
+ id = JSON.parse(match[1]);
14
+ } catch {
15
+ continue;
16
+ }
17
+ out.push({
18
+ from: match.index,
19
+ to: match.index + match[0].length,
20
+ id
21
+ });
22
+ }
23
+ return out;
24
+ }
@@ -1,7 +1,7 @@
1
1
  import { type ScopeAncestor, type SelectionFieldRef, type StepRef } from '../../../utils/cel-context.js';
2
2
  export type PickEntry = {
3
3
  id: string;
4
- group: 'var' | 'scope' | 'selection' | 'step';
4
+ group: 'var' | 'scope' | 'selection' | 'option' | 'step';
5
5
  insert: string;
6
6
  display: string;
7
7
  label: string;
@@ -15,6 +15,7 @@ export type PickVarMeta = {
15
15
  };
16
16
  export declare function buildVarEntries(celContext: Record<string, PickVarMeta>, extraVars?: Record<string, PickVarMeta>): PickEntry[];
17
17
  export declare function buildSelectionEntries(roster: ReadonlyArray<SelectionFieldRef>): PickEntry[];
18
+ export declare function buildOptionEntries(roster: ReadonlyArray<SelectionFieldRef>): PickEntry[];
18
19
  export declare function buildStepEntries(roster: ReadonlyArray<StepRef>): PickEntry[];
19
20
  export declare function selectShadowedScopes(ancestry: ReadonlyArray<ScopeAncestor>): ScopeAncestor[];
20
21
  export declare function buildScopeEntries(ancestry: ReadonlyArray<ScopeAncestor>): PickEntry[];
@@ -1,6 +1,6 @@
1
- import { SCOPE_ADDRESS_VAR, SELECTIONS_VAR, STEPS_VAR } from "../../../utils/cel-context.js";
1
+ import { OPTIONS_VAR, SCOPE_ADDRESS_VAR, SELECTIONS_VAR, STEPS_VAR } from "../../../utils/cel-context.js";
2
2
  import { scopeOrigin } from "./scope-refs.js";
3
- const SUPPRESSED_VARS = /* @__PURE__ */ new Set([SCOPE_ADDRESS_VAR, SELECTIONS_VAR, STEPS_VAR]);
3
+ const SUPPRESSED_VARS = /* @__PURE__ */ new Set([SCOPE_ADDRESS_VAR, SELECTIONS_VAR, OPTIONS_VAR, STEPS_VAR]);
4
4
  export function buildVarEntries(celContext, extraVars) {
5
5
  const out = [];
6
6
  const seen = /* @__PURE__ */ new Set();
@@ -25,6 +25,16 @@ export function buildSelectionEntries(roster) {
25
25
  type: "dyn"
26
26
  }));
27
27
  }
28
+ export function buildOptionEntries(roster) {
29
+ return roster.map((field) => ({
30
+ id: `option:${field.id}`,
31
+ group: "option",
32
+ insert: `${OPTIONS_VAR}[?${JSON.stringify(field.id)}]`,
33
+ display: field.name,
34
+ label: "\u5168\u90E8\u9009\u9879",
35
+ type: "dyn"
36
+ }));
37
+ }
28
38
  export function buildStepEntries(roster) {
29
39
  return roster.filter((step) => step.valid).map((step) => ({
30
40
  id: `step:${step.id}`,
@@ -0,0 +1,34 @@
1
+ import type { Environment } from '../vendor/cel-js/lib/index.js';
2
+ import type { ResultType } from './expression.js';
3
+ /**
4
+ * Result-type matcher for a per-date "should this date be disabled" expression.
5
+ * The expression returns `true` to disable the candidate date; `false`/none/
6
+ * absent leave it enabled (matching reka-ui's native `isDateDisabled`). Accepts
7
+ * a bare `bool` (`input >= now`) as well as `optional<bool>`
8
+ * (`cond ? optional.of(true) : optional.none()`) — same leniency as
9
+ * `HttpRequestResult` in `share/expression.ts`. At runtime `cel()` unwraps
10
+ * `optional.none()` to `undefined`, which the predicate treats as "no opinion,
11
+ * keep the date enabled". `dyn`/`optional<dyn>` ride along for gradual typing.
12
+ */
13
+ export declare const DISABLE_DATE_RESULT: ResultType;
14
+ /**
15
+ * Register the `input` (Date) CEL variable — the candidate date the calendar is
16
+ * rendering — only when an enclosing `configure` hasn't already declared it. The
17
+ * CEL registry throws `'input' is already registered` on a duplicate, so the
18
+ * guard mirrors `registerRowVariablesIfAbsent` / `registerLoopVariablesIfAbsent`.
19
+ */
20
+ export declare function registerInputDateIfAbsent(env: Environment): void;
21
+ /**
22
+ * The `input` variable advertised to `ExpressionEditor` via its `extra-vars`
23
+ * prop, so completion offers it at design time. Pair with
24
+ * `DISABLE_DATE_EDITOR_RESULT` for the editor's `result-type` — the editor prop
25
+ * can't take a function matcher, so the array form mirrors `DISABLE_DATE_RESULT`.
26
+ */
27
+ export declare const INPUT_DATE_VARS: {
28
+ readonly input: {
29
+ readonly type: "Date";
30
+ readonly label: "候选日期";
31
+ readonly description: "日历中待判定是否可选的日期";
32
+ };
33
+ };
34
+ export declare const DISABLE_DATE_EDITOR_RESULT: readonly ["bool", "optional<bool>"];
@@ -0,0 +1,13 @@
1
+ export const DISABLE_DATE_RESULT = (t) => t === "bool" || t === "optional<bool>" || t === "optional<dyn>" || t === "dyn";
2
+ const INPUT_VAR_LABEL = "\u5019\u9009\u65E5\u671F";
3
+ const INPUT_VAR_DESCRIPTION = "\u65E5\u5386\u4E2D\u5F85\u5224\u5B9A\u662F\u5426\u53EF\u9009\u7684\u65E5\u671F";
4
+ export function registerInputDateIfAbsent(env) {
5
+ const declared = new Set(env.getDefinitions().variables.map((v) => v.name));
6
+ if (!declared.has("input")) {
7
+ env.registerVariable("input", "Date", { label: INPUT_VAR_LABEL, description: INPUT_VAR_DESCRIPTION });
8
+ }
9
+ }
10
+ export const INPUT_DATE_VARS = {
11
+ input: { type: "Date", label: INPUT_VAR_LABEL, description: INPUT_VAR_DESCRIPTION }
12
+ };
13
+ export const DISABLE_DATE_EDITOR_RESULT = ["bool", "optional<bool>"];
@@ -5,7 +5,7 @@ import { coerceFromString } from "../../share/coerce-from-string.js";
5
5
  const ENDPOINT = "http://192.168.168.10/anthropic/v1/messages";
6
6
  const MODEL = "MiniMax-M2.7";
7
7
  const ANTHROPIC_VERSION = "2023-06-01";
8
- const DEFAULT_MAX_TOKENS = 8192;
8
+ const DEFAULT_MAX_TOKENS = 32768;
9
9
  export class StructuredOutputDecodeError extends Error {
10
10
  rawOutput;
11
11
  constructor(rawOutput, cause) {
@@ -273,6 +273,8 @@ async function streamChat(input) {
273
273
  };
274
274
  const assistant = { id: createMessageId(), role: "assistant", parts: [] };
275
275
  const publish = () => input.onMessageUpdate?.(assistant);
276
+ const MAX_TRUNCATION_STREAK = 3;
277
+ let truncationStreak = 0;
276
278
  for (; ; ) {
277
279
  const partByIndex = /* @__PURE__ */ new Map();
278
280
  const response = await callStream(messages, input.system, opts, input.signal, () => {
@@ -313,8 +315,29 @@ async function streamChat(input) {
313
315
  (b) => b.type === "tool_use"
314
316
  );
315
317
  if (toolUses.length === 0) {
318
+ if (response.stop_reason === "max_tokens") {
319
+ if (truncationStreak >= MAX_TRUNCATION_STREAK) {
320
+ throw new Error("\u6A21\u578B\u8FDE\u7EED\u591A\u8F6E\u5728\u4EA7\u51FA\u524D\u7528\u5C3D token \u9884\u7B97\uFF08max_tokens\uFF09\uFF0C\u5DF2\u505C\u6B62\u3002\u8BF7\u7F29\u5C0F\u672C\u6B21\u914D\u7F6E\u8303\u56F4\u6216\u62C6\u5206\u6307\u4EE4\u540E\u91CD\u8BD5\u3002");
321
+ }
322
+ truncationStreak++;
323
+ const echoable = response.content.filter(
324
+ (b) => !(b.type === "text" && b.text.length === 0)
325
+ );
326
+ const assistantEcho = echoable.length > 0 ? echoable : [{ type: "text", text: "\u2026" }];
327
+ messages.push({ role: "assistant", content: assistantEcho });
328
+ messages.push({
329
+ role: "user",
330
+ content: "\u4E0A\u4E00\u8F6E\u5728 max_tokens \u5904\u88AB\u622A\u65AD\u3002\u8BF7\u7528\u66F4\u5C0F\u7684\u6B65\u5B50\u7EE7\u7EED\uFF1A\u672C\u8F6E\u53EA\u505A\u4E00\u6B65\uFF08\u4E00\u4E2A\u5DE5\u5177\u8C03\u7528\uFF0C\u6216\u4E00\u6BB5\u7B80\u77ED\u56DE\u590D\uFF09\u3002"
331
+ });
332
+ if (assistant.parts.length > 0) {
333
+ assistant.parts.push({ type: "step-start" });
334
+ publish();
335
+ }
336
+ continue;
337
+ }
316
338
  return assistant;
317
339
  }
340
+ truncationStreak = 0;
318
341
  await runToolResults(
319
342
  messages,
320
343
  response.content,
@@ -8,6 +8,7 @@ export type CELVar = {
8
8
  export type CELContext = Record<string, CELVar>;
9
9
  export declare const SCOPE_ADDRESS_VAR = "__scopes__";
10
10
  export declare const SELECTIONS_VAR = "selections";
11
+ export declare const OPTIONS_VAR = "options";
11
12
  export declare const STEPS_VAR = "steps";
12
13
  export type ScopeAccessor = Record<string, () => unknown>;
13
14
  export declare function provideCELContext(context: CELContext): void;
@@ -2,6 +2,7 @@ import { computed, inject, provide, shallowRef } from "vue";
2
2
  import { injectLocal, provideLocal } from "@vueuse/core";
3
3
  export const SCOPE_ADDRESS_VAR = "__scopes__";
4
4
  export const SELECTIONS_VAR = "selections";
5
+ export const OPTIONS_VAR = "options";
5
6
  export const STEPS_VAR = "steps";
6
7
  const CEL_CONTEXT_KEY = Symbol("cel-context");
7
8
  export function provideCELContext(context) {
@@ -0,0 +1,26 @@
1
+ import type { DateValue } from 'reka-ui';
2
+ /**
3
+ * Convert an `@internationalized/date` `DateValue` (what the picker's
4
+ * `disabledDate` callback receives) to a native JS `Date`, so user expressions
5
+ * see a plain `input: Date`. Mirrors `pickerValueToNative` in
6
+ * `ui/date-picker/DatePicker.vue` (minus the `Time` branch — the per-date
7
+ * predicate never receives a `Time`). For a `CalendarDate` (date/month/year
8
+ * panels) the time fields are absent and default to `0`; for `month` panels the
9
+ * candidate is the first of the month (`day` is `1`).
10
+ */
11
+ export declare function dateValueToNative(d: DateValue): Date;
12
+ /**
13
+ * Build the `(d: DateValue) => boolean` predicate the date pickers expect from a
14
+ * user-authored CEL expression. Centralizes three concerns shared by every date
15
+ * block: the `DateValue` → native `Date` conversion, the "expression returns
16
+ * `true` ⇒ date disabled" mapping (`false`/`undefined`/none ⇒ enabled — matching
17
+ * reka-ui's native `isDateDisabled`), and error containment (a throwing
18
+ * expression leaves the date enabled).
19
+ *
20
+ * Each runtime passes its own `evalWithInput` closure so its existing CEL scope
21
+ * is preserved verbatim — form fields evaluate against `{ form, input }`, table
22
+ * columns against `celScope(celContext, { input })`. Returns `undefined` when
23
+ * there's no expression, so the picker omits the prop and all dates stay
24
+ * selectable.
25
+ */
26
+ export declare function makeDisabledDatePredicate(expr: string | undefined, evalWithInput: (input: Date) => boolean | undefined): ((d: DateValue) => boolean) | undefined;
@@ -0,0 +1,21 @@
1
+ export function dateValueToNative(d) {
2
+ return new Date(
3
+ d.year,
4
+ d.month - 1,
5
+ "day" in d ? d.day : 1,
6
+ "hour" in d ? d.hour : 0,
7
+ "hour" in d ? d.minute : 0,
8
+ "hour" in d ? d.second : 0
9
+ );
10
+ }
11
+ export function makeDisabledDatePredicate(expr, evalWithInput) {
12
+ if (!expr) return void 0;
13
+ return (d) => {
14
+ try {
15
+ return evalWithInput(dateValueToNative(d)) === true;
16
+ } catch (e) {
17
+ console.error("[shwfed] disabledDate expression failed", e);
18
+ return false;
19
+ }
20
+ };
21
+ }
@@ -38,17 +38,38 @@ export type SelectionsRegistry = {
38
38
  clear: (uuid: string) => void;
39
39
  };
40
40
  /**
41
- * Create a registry and provide it to descendants. Called once per host (the
42
- * form root; later, a table row). The returned `entries` ref is what the host
43
- * overlays as the `selections` CEL thunk.
41
+ * The `options` channel is the exact same registry shape a `uuid → value` map
42
+ * with the identical shallowRef + map-replace + identity-dedup discipline but
43
+ * carries a field's WHOLE loaded option list (`options["<uuid>"]` `[opt, …]`)
44
+ * rather than its selected option. A field owns both channels: `selections`
45
+ * publishes the picked option(s), `options` publishes every option it loaded.
46
+ * Kept under a separate injection key so the two maps are independent providers
47
+ * on the one host (the form root provides both). `OptionsRegistry` is a plain
48
+ * alias of `SelectionsRegistry` — the recursion-safety invariant is identical,
49
+ * so they must share the one implementation, never a drifting copy.
50
+ */
51
+ export type OptionsRegistry = SelectionsRegistry;
52
+ /**
53
+ * Create the selections registry and provide it to descendants. The returned
54
+ * `entries` ref is what the host overlays as the `selections` CEL thunk.
44
55
  */
45
56
  export declare function provideSelectionsRegistry(): SelectionsRegistry;
46
57
  /**
47
- * Inject the nearest registry, or `undefined` when there's no providing host
48
- * (an uncontrolled field, a unit test). Callers must tolerate the absent case
49
- * publishing is best-effort.
58
+ * Create the options registry and provide it to descendants. The returned
59
+ * `entries` ref is what the host overlays as the `options` CEL thunk.
60
+ */
61
+ export declare function provideOptionsRegistry(): OptionsRegistry;
62
+ /**
63
+ * Inject the nearest selections registry, or `undefined` when there's no
64
+ * providing host (an uncontrolled field, a unit test). Callers must tolerate the
65
+ * absent case — publishing is best-effort.
50
66
  */
51
67
  export declare function useSelectionsRegistry(): SelectionsRegistry | undefined;
68
+ /**
69
+ * Inject the nearest options registry, or `undefined` when there's no providing
70
+ * host. Best-effort, same contract as `useSelectionsRegistry`.
71
+ */
72
+ export declare function useOptionsRegistry(): OptionsRegistry | undefined;
52
73
  /**
53
74
  * Wire a selection field's publish lifecycle to the nearest registry. Call once
54
75
  * in setup; it injects the host registry (tolerating absence), watches the
@@ -75,3 +96,16 @@ export declare function publishSelection<T>(key: string, resolved: () => T | und
75
96
  identity: (value: T) => string;
76
97
  raw: (value: T) => unknown;
77
98
  }): void;
99
+ /**
100
+ * Wire a selection field's OPTIONS-list publish lifecycle to the nearest options
101
+ * registry. Same contract and de-dup discipline as `publishSelection` — the
102
+ * recursion hazard is identical (`celBindings` reads the `options` map on every
103
+ * `$cel` pass, and remote records are re-copied each pass), so `resolved` must
104
+ * return the whole loaded list, `identity` must project it to the STABLE joined
105
+ * option keys (never the payload), and `raw` projects it to the array stored for
106
+ * siblings to read. An empty list resolves to `undefined` → the entry clears.
107
+ */
108
+ export declare function publishOptions<T>(key: string, resolved: () => T | undefined, project: {
109
+ identity: (value: T) => string;
110
+ raw: (value: T) => unknown;
111
+ }): void;
@@ -1,5 +1,6 @@
1
1
  import { inject, onUnmounted, provide, shallowRef, watch } from "vue";
2
2
  const SELECTIONS_KEY = Symbol("shwfed-selections");
3
+ const OPTIONS_KEY = Symbol("shwfed-options");
3
4
  function sameSelection(a, b) {
4
5
  if (Object.is(a, b)) return true;
5
6
  if (Array.isArray(a) && Array.isArray(b)) {
@@ -8,7 +9,7 @@ function sameSelection(a, b) {
8
9
  }
9
10
  return false;
10
11
  }
11
- export function provideSelectionsRegistry() {
12
+ function createRegistry(key) {
12
13
  const entries = shallowRef({});
13
14
  const registry = {
14
15
  entries,
@@ -19,18 +20,29 @@ export function provideSelectionsRegistry() {
19
20
  clear: (uuid) => {
20
21
  if (!(uuid in entries.value)) return;
21
22
  entries.value = Object.fromEntries(
22
- Object.entries(entries.value).filter(([key]) => key !== uuid)
23
+ Object.entries(entries.value).filter(([key2]) => key2 !== uuid)
23
24
  );
24
25
  }
25
26
  };
26
- provide(SELECTIONS_KEY, registry);
27
+ provide(key, registry);
27
28
  return registry;
28
29
  }
30
+ export function provideSelectionsRegistry() {
31
+ return createRegistry(SELECTIONS_KEY);
32
+ }
33
+ export function provideOptionsRegistry() {
34
+ return createRegistry(OPTIONS_KEY);
35
+ }
29
36
  export function useSelectionsRegistry() {
30
37
  return inject(SELECTIONS_KEY, void 0);
31
38
  }
39
+ export function useOptionsRegistry() {
40
+ return inject(OPTIONS_KEY, void 0);
41
+ }
32
42
  export function publishSelection(key, resolved, project) {
33
- const registry = useSelectionsRegistry();
43
+ publishTo(useSelectionsRegistry(), key, resolved, project);
44
+ }
45
+ function publishTo(registry, key, resolved, project) {
34
46
  const NONE = "\0:none";
35
47
  let last = "\0:init";
36
48
  watch(
@@ -47,3 +59,6 @@ export function publishSelection(key, resolved, project) {
47
59
  );
48
60
  onUnmounted(() => registry?.clear(key));
49
61
  }
62
+ export function publishOptions(key, resolved, project) {
63
+ publishTo(useOptionsRegistry(), key, resolved, project);
64
+ }
@@ -18,6 +18,8 @@ A `list.enumerate(): list<map<string, dyn>>` receiver method has been added (not
18
18
 
19
19
  A `list.slice(number)` / `list.slice(number, number)` receiver pair has been added (not from upstream, in `functions.ts` beside `list.enumerate()`) — delegates straight to JS `Array.prototype.slice`, so negative indices count from the end (`list.slice(0, -1)` drops the last element) and out-of-range bounds clamp rather than throw. End is exclusive. Fills the gap left by CEL's `list[i]`, which has no negative indexing. Both overloads return `list<dyn>`.
20
20
 
21
+ A `string.replace(string, string): string` / `string.replace(string, string, number): string` receiver pair has been added (in `functions.ts` beside `string.trim()`), matching the CEL strings-extension `replace`. The two-arg form delegates to JS `String.prototype.replaceAll` (so all non-overlapping occurrences are replaced; an empty `from` interleaves `to`). The three-arg form takes a limit and mirrors Go's `strings.Replace` via the `replaceLimited` helper: `limit < 0` replaces all, `0` replaces none, otherwise the first `limit` occurrences (`"foo".replace("", "_", 2) == "_f_oo"`).
22
+
21
23
  `evaluate` now returns `Effect<T, ParseError | EvaluationError | TypeError>` instead of a plain value. The entire evaluation pipeline is Effect-based — every AST node's `evaluate` function returns an Effect, and sub-expressions are composed via `Effect.gen` / `yield*`. Promise-based async handling has been removed. User-registered functions may return `Effect` values, which are automatically flatMapped into the evaluation pipeline. Import `Effect` from `effect` and use `Effect.runSync` or `Effect.runPromise` to execute the returned Effect.
22
24
 
23
25
  The `homogeneousAggregateLiterals` and `enableOptionalTypes` environment options have been removed. Aggregate data structures (lists, maps) are always heterogeneous — mixed-type literals are inferred as `list<dyn>` or `map<dyn, dyn>`. Optional types (`.?`, `[?]`, `optional.*` helpers) are always enabled.
@@ -161,6 +161,8 @@ Mirrors JS `Array.prototype.slice`. Negative indices count from the end (CEL's `
161
161
  "hello".indexOf("l") // 2
162
162
  "hello".lastIndexOf("l") // 3
163
163
  "hello".matches("[a-z]+") // true (regex)
164
+ "hello".replace("l", "L") // "heLLo" (all occurrences)
165
+ "hello".replace("l", "L", 1) // "heLlo" (first N; N<0 = all, 0 = none)
164
166
  "a,b,c".split(",") // ["a", "b", "c"]
165
167
  "a,b,c".split(",", 2) // ["a", "b,c"]
166
168
  ["a", "b"].join() // "ab"
@@ -139,6 +139,14 @@ export function registerFunctions(registry) {
139
139
  functionOverload("string.lowerAscii(): string", (a) => a.toLowerCase());
140
140
  functionOverload("string.upperAscii(): string", (a) => a.toUpperCase());
141
141
  functionOverload("string.trim(): string", (a) => a.trim());
142
+ functionOverload(
143
+ "string.replace(string, string): string",
144
+ (string, from, to) => string.replaceAll(from, to)
145
+ );
146
+ functionOverload(
147
+ "string.replace(string, string, number): string",
148
+ (string, from, to, limit) => replaceLimited(string, from, to, toNum(limit))
149
+ );
142
150
  functionOverload(
143
151
  "string.indexOf(string): number",
144
152
  (string, search) => Decimal.from(string.indexOf(search))
@@ -436,3 +444,28 @@ function stringSize(str) {
436
444
  for (const _ of str) count++;
437
445
  return count;
438
446
  }
447
+ function replaceLimited(str, from, to, limit) {
448
+ if (limit < 0) return str.replaceAll(from, to);
449
+ if (limit === 0 || from === to) return str;
450
+ let result = "";
451
+ let start = 0;
452
+ let count = 0;
453
+ while (count < limit) {
454
+ let j;
455
+ if (from === "") {
456
+ if (count > 0) {
457
+ if (start >= str.length) break;
458
+ j = start + 1;
459
+ } else {
460
+ j = start;
461
+ }
462
+ } else {
463
+ j = str.indexOf(from, start);
464
+ if (j < 0) break;
465
+ }
466
+ result += str.slice(start, j) + to;
467
+ start = j + from.length;
468
+ count++;
469
+ }
470
+ return result + str.slice(start);
471
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shwfed/config",
3
- "version": "2.12.0",
3
+ "version": "2.12.2",
4
4
  "description": "Configurable UI for SHWFED",
5
5
  "type": "module",
6
6
  "publishConfig": {