@shwfed/config 2.12.1 → 2.12.3

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 (142) hide show
  1. package/dist/module.json +1 -1
  2. package/dist/module.mjs +10 -0
  3. package/dist/runtime/components/config/blocks/2026-05-06/com.shwfed.block.table/config.d.vue.ts +68 -68
  4. package/dist/runtime/components/config/blocks/2026-05-06/com.shwfed.block.table/config.vue.d.ts +68 -68
  5. package/dist/runtime/components/config/blocks/2026-05-06/com.shwfed.block.table/runtime.d.vue.ts +68 -68
  6. package/dist/runtime/components/config/blocks/2026-05-06/com.shwfed.block.table/runtime.vue.d.ts +68 -68
  7. package/dist/runtime/components/config/blocks/2026-05-06/com.shwfed.block.table/schema.d.ts +34 -34
  8. package/dist/runtime/components/form/config.vue +17 -6
  9. package/dist/runtime/components/form/fields/2026-04-24/com.shwfed.form.field.combobox.single/config.d.vue.ts +2 -2
  10. package/dist/runtime/components/form/fields/2026-04-24/com.shwfed.form.field.combobox.single/config.vue.d.ts +2 -2
  11. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.daterange/config.d.vue.ts +6 -6
  12. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.daterange/config.vue.d.ts +6 -6
  13. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.datetimerange/config.d.vue.ts +8 -8
  14. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.datetimerange/config.vue.d.ts +8 -8
  15. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.timerange/config.d.vue.ts +2 -2
  16. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.timerange/config.vue.d.ts +2 -2
  17. package/dist/runtime/components/form/fields/2026-05-13/com.shwfed.form.field.combobox.single.remote/config.d.vue.ts +2 -2
  18. package/dist/runtime/components/form/fields/2026-05-13/com.shwfed.form.field.combobox.single.remote/config.vue.d.ts +2 -2
  19. package/dist/runtime/components/form/fields/2026-05-13/com.shwfed.form.field.list/row.vue +8 -1
  20. package/dist/runtime/components/form/fields/2026-05-23/com.shwfed.form.field.tree.multi/config.d.vue.ts +24 -24
  21. package/dist/runtime/components/form/fields/2026-05-23/com.shwfed.form.field.tree.multi/config.vue.d.ts +24 -24
  22. package/dist/runtime/components/form/fields/2026-05-24/com.shwfed.form.field.monthrange/config.d.vue.ts +6 -6
  23. package/dist/runtime/components/form/fields/2026-05-24/com.shwfed.form.field.monthrange/config.vue.d.ts +6 -6
  24. package/dist/runtime/components/form/fields/2026-05-25/com.shwfed.form.field.combobox.multi/config.d.vue.ts +2 -2
  25. package/dist/runtime/components/form/fields/2026-05-25/com.shwfed.form.field.combobox.multi/config.vue.d.ts +2 -2
  26. package/dist/runtime/components/form/fields/2026-05-26/com.shwfed.form.field.tree.combobox.multi/config.d.vue.ts +24 -24
  27. package/dist/runtime/components/form/fields/2026-05-26/com.shwfed.form.field.tree.combobox.multi/config.vue.d.ts +24 -24
  28. package/dist/runtime/components/form/fields/2026-05-26/com.shwfed.form.field.tree.combobox.single/config.d.vue.ts +22 -22
  29. package/dist/runtime/components/form/fields/2026-05-26/com.shwfed.form.field.tree.combobox.single/config.vue.d.ts +22 -22
  30. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.combobox.multi/config.d.vue.ts +32 -32
  31. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.combobox.multi/config.vue.d.ts +32 -32
  32. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.combobox.multi/runtime.vue +10 -2
  33. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.combobox.single/config.d.vue.ts +32 -32
  34. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.combobox.single/config.vue.d.ts +32 -32
  35. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.combobox.single/runtime.vue +10 -2
  36. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.multi/config.d.vue.ts +24 -24
  37. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.multi/config.vue.d.ts +24 -24
  38. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.multi/runtime.vue +19 -1
  39. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.single/config.d.vue.ts +22 -22
  40. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.single/config.vue.d.ts +22 -22
  41. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.single/runtime.vue +19 -1
  42. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.multi/config.d.vue.ts +24 -24
  43. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.multi/config.vue.d.ts +24 -24
  44. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.multi/runtime.vue +20 -1
  45. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.single/config.d.vue.ts +22 -22
  46. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.single/config.vue.d.ts +22 -22
  47. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.single/runtime.vue +20 -1
  48. package/dist/runtime/components/form/fields/2026-06-14/com.shwfed.form.field.combobox.multi/config.d.vue.ts +32 -32
  49. package/dist/runtime/components/form/fields/2026-06-14/com.shwfed.form.field.combobox.multi/config.vue.d.ts +32 -32
  50. package/dist/runtime/components/form/fields/2026-06-14/com.shwfed.form.field.combobox.multi/runtime.vue +10 -2
  51. package/dist/runtime/components/form/fields/2026-06-14/com.shwfed.form.field.combobox.single/config.d.vue.ts +32 -32
  52. package/dist/runtime/components/form/fields/2026-06-14/com.shwfed.form.field.combobox.single/config.vue.d.ts +32 -32
  53. package/dist/runtime/components/form/fields/2026-06-14/com.shwfed.form.field.combobox.single/runtime.vue +10 -2
  54. package/dist/runtime/components/form/index.vue +6 -3
  55. package/dist/runtime/components/form/utils/form-vars.js +2 -1
  56. package/dist/runtime/components/head.d.vue.ts +13 -0
  57. package/dist/runtime/components/head.vue +69 -0
  58. package/dist/runtime/components/head.vue.d.ts +13 -0
  59. package/dist/runtime/components/sidebar/config.d.vue.ts +7 -0
  60. package/dist/runtime/components/sidebar/config.vue +302 -0
  61. package/dist/runtime/components/sidebar/config.vue.d.ts +7 -0
  62. package/dist/runtime/components/sidebar/favorites.d.ts +18 -0
  63. package/dist/runtime/components/sidebar/favorites.js +20 -0
  64. package/dist/runtime/components/sidebar/footer.d.vue.ts +11 -0
  65. package/dist/runtime/components/sidebar/footer.vue +49 -0
  66. package/dist/runtime/components/sidebar/footer.vue.d.ts +11 -0
  67. package/dist/runtime/components/sidebar/index.d.vue.ts +50 -0
  68. package/dist/runtime/components/sidebar/index.vue +100 -0
  69. package/dist/runtime/components/sidebar/index.vue.d.ts +50 -0
  70. package/dist/runtime/components/sidebar/node.d.vue.ts +9 -0
  71. package/dist/runtime/components/sidebar/node.vue +102 -0
  72. package/dist/runtime/components/sidebar/node.vue.d.ts +9 -0
  73. package/dist/runtime/components/sidebar/schema.d.ts +72 -0
  74. package/dist/runtime/components/sidebar/schema.js +84 -0
  75. package/dist/runtime/components/sidebar/tree.d.vue.ts +10 -0
  76. package/dist/runtime/components/sidebar/tree.vue +260 -0
  77. package/dist/runtime/components/sidebar/tree.vue.d.ts +10 -0
  78. package/dist/runtime/components/sidebar/types.d.ts +19 -0
  79. package/dist/runtime/components/sidebar/types.js +0 -0
  80. package/dist/runtime/components/sidebar/use-editor.d.ts +18 -0
  81. package/dist/runtime/components/sidebar/use-editor.js +43 -0
  82. package/dist/runtime/components/table/columns/2026-05-24/com.shwfed.table.column.combobox-single.remote.options-remote/config.d.vue.ts +2 -2
  83. package/dist/runtime/components/table/columns/2026-05-24/com.shwfed.table.column.combobox-single.remote.options-remote/config.vue.d.ts +2 -2
  84. package/dist/runtime/components/table/columns/2026-05-25/com.shwfed.table.column.combobox-multi.remote.options-remote/config.d.vue.ts +2 -2
  85. package/dist/runtime/components/table/columns/2026-05-25/com.shwfed.table.column.combobox-multi.remote.options-remote/config.vue.d.ts +2 -2
  86. package/dist/runtime/components/table/columns/2026-05-26/com.shwfed.table.column.combobox-multi/config.d.vue.ts +36 -36
  87. package/dist/runtime/components/table/columns/2026-05-26/com.shwfed.table.column.combobox-multi/config.vue.d.ts +36 -36
  88. package/dist/runtime/components/table/columns/2026-05-26/com.shwfed.table.column.combobox-multi.remote/config.d.vue.ts +40 -40
  89. package/dist/runtime/components/table/columns/2026-05-26/com.shwfed.table.column.combobox-multi.remote/config.vue.d.ts +40 -40
  90. package/dist/runtime/components/table/columns/2026-05-26/com.shwfed.table.column.combobox-single/config.d.vue.ts +36 -36
  91. package/dist/runtime/components/table/columns/2026-05-26/com.shwfed.table.column.combobox-single/config.vue.d.ts +36 -36
  92. package/dist/runtime/components/table/columns/2026-05-26/com.shwfed.table.column.combobox-single.remote/config.d.vue.ts +40 -40
  93. package/dist/runtime/components/table/columns/2026-05-26/com.shwfed.table.column.combobox-single.remote/config.vue.d.ts +40 -40
  94. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-multi/config.d.vue.ts +4 -4
  95. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-multi/config.vue.d.ts +4 -4
  96. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-single/config.d.vue.ts +2 -2
  97. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-single/config.vue.d.ts +2 -2
  98. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-multi/config.d.vue.ts +26 -26
  99. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-multi/config.vue.d.ts +26 -26
  100. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-single/config.d.vue.ts +26 -26
  101. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-single/config.vue.d.ts +26 -26
  102. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-multi/config.d.vue.ts +4 -4
  103. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-multi/config.vue.d.ts +4 -4
  104. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-single/config.d.vue.ts +2 -2
  105. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-single/config.vue.d.ts +2 -2
  106. package/dist/runtime/components/table/columns/2026-06-14/com.shwfed.table.column.combobox-multi/config.d.vue.ts +26 -26
  107. package/dist/runtime/components/table/columns/2026-06-14/com.shwfed.table.column.combobox-multi/config.vue.d.ts +26 -26
  108. package/dist/runtime/components/table/columns/2026-06-14/com.shwfed.table.column.combobox-single/config.d.vue.ts +26 -26
  109. package/dist/runtime/components/table/columns/2026-06-14/com.shwfed.table.column.combobox-single/config.vue.d.ts +26 -26
  110. package/dist/runtime/components/table/columns/2026-06-14/com.shwfed.table.column.tree-combobox-multi/config.d.vue.ts +4 -4
  111. package/dist/runtime/components/table/columns/2026-06-14/com.shwfed.table.column.tree-combobox-multi/config.vue.d.ts +4 -4
  112. package/dist/runtime/components/table/columns/2026-06-14/com.shwfed.table.column.tree-combobox-single/config.d.vue.ts +2 -2
  113. package/dist/runtime/components/table/columns/2026-06-14/com.shwfed.table.column.tree-combobox-single/config.vue.d.ts +2 -2
  114. package/dist/runtime/components/table/schema.d.ts +68 -68
  115. package/dist/runtime/components/ui/date-picker/DatePickerInput.d.vue.ts +1 -1
  116. package/dist/runtime/components/ui/date-picker/DatePickerInput.vue.d.ts +1 -1
  117. package/dist/runtime/components/ui/date-picker/DatePickerTimeInput.d.vue.ts +1 -1
  118. package/dist/runtime/components/ui/date-picker/DatePickerTimeInput.vue.d.ts +1 -1
  119. package/dist/runtime/components/ui/date-range-picker/DateRangePickerInput.d.vue.ts +1 -1
  120. package/dist/runtime/components/ui/date-range-picker/DateRangePickerInput.vue.d.ts +1 -1
  121. package/dist/runtime/components/ui/date-range-picker/DateRangePickerTimeInput.d.vue.ts +2 -2
  122. package/dist/runtime/components/ui/date-range-picker/DateRangePickerTimeInput.vue.d.ts +2 -2
  123. package/dist/runtime/components/ui/expression-editor/CodeMirrorInput.d.vue.ts +1 -0
  124. package/dist/runtime/components/ui/expression-editor/CodeMirrorInput.vue +8 -0
  125. package/dist/runtime/components/ui/expression-editor/CodeMirrorInput.vue.d.ts +1 -0
  126. package/dist/runtime/components/ui/expression-editor/ExpressionEditor.d.vue.ts +3 -2
  127. package/dist/runtime/components/ui/expression-editor/ExpressionEditor.vue +51 -9
  128. package/dist/runtime/components/ui/expression-editor/ExpressionEditor.vue.d.ts +3 -2
  129. package/dist/runtime/components/ui/expression-editor/option-chip-extension.d.ts +4 -0
  130. package/dist/runtime/components/ui/expression-editor/option-chip-extension.js +119 -0
  131. package/dist/runtime/components/ui/expression-editor/option-refs.d.ts +6 -0
  132. package/dist/runtime/components/ui/expression-editor/option-refs.js +24 -0
  133. package/dist/runtime/components/ui/expression-editor/picker-entries.d.ts +2 -1
  134. package/dist/runtime/components/ui/expression-editor/picker-entries.js +12 -2
  135. package/dist/runtime/utils/cel-context.d.ts +1 -0
  136. package/dist/runtime/utils/cel-context.js +1 -0
  137. package/dist/runtime/utils/selections-registry.d.ts +40 -6
  138. package/dist/runtime/utils/selections-registry.js +19 -4
  139. package/dist/runtime/vendor/cel-js/CLAUDE.md +2 -0
  140. package/dist/runtime/vendor/cel-js/PROMPT.md +2 -0
  141. package/dist/runtime/vendor/cel-js/lib/functions.js +33 -0
  142. 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}`,
@@ -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) {
@@ -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.1",
3
+ "version": "2.12.3",
4
4
  "description": "Configurable UI for SHWFED",
5
5
  "type": "module",
6
6
  "publishConfig": {