@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,302 @@
1
+ <script setup>
2
+ import { ExpressionEditor } from "../ui/expression-editor";
3
+ import { Field, FieldLabel } from "../ui/field";
4
+ import { Locale as LocaleField } from "../ui/locale";
5
+ import { Markdown } from "../ui/markdown";
6
+ import { DataSource } from "../table/schema";
7
+ import { getStructFieldDescription, getStructFieldTitle, SidebarConfig } from "./schema";
8
+ defineOptions({ name: "ShwfedSidebarConfig" });
9
+ const props = defineProps({
10
+ state: { type: Object, required: true }
11
+ });
12
+ const draft = props.state.draft;
13
+ const cfgSchema = SidebarConfig(() => {
14
+ });
15
+ const fieldTitle = (f) => getStructFieldTitle(cfgSchema, f) ?? f;
16
+ const fieldDescription = (f) => getStructFieldDescription(cfgSchema, f);
17
+ const dataSourceSchema = DataSource(() => {
18
+ });
19
+ const dsTitle = (f) => getStructFieldTitle(dataSourceSchema, f) ?? f;
20
+ const dsDescription = (f) => getStructFieldDescription(dataSourceSchema, f);
21
+ const nodeExtraVars = {
22
+ node: {
23
+ type: "dyn",
24
+ label: "\u5F53\u524D\u8282\u70B9",
25
+ description: "\u7531 `\u6570\u636E` \u8868\u8FBE\u5F0F\u8FD4\u56DE\u7684\u6BCF\u4E00\u9879\uFF1B\u7C7B\u578B\u5728\u914D\u7F6E\u65F6\u672A\u77E5\uFF08`dyn`\uFF09"
26
+ }
27
+ };
28
+ const jsonExtraVars = {
29
+ json: {
30
+ type: "optional<dyn>",
31
+ label: "HTTP \u54CD\u5E94\u4F53",
32
+ description: "\u5DF2\u89E3\u6790\u7684 JSON \u54CD\u5E94\uFF1B\u672A\u914D\u7F6E `request` \u65F6\u4E3A `none`"
33
+ }
34
+ };
35
+ function setDataSourceData(next) {
36
+ draft.value = { ...draft.value, dataSource: { ...draft.value.dataSource, data: next } };
37
+ }
38
+ function setDataSourceRequest(next) {
39
+ if (next.trim().length === 0) {
40
+ const { request: _omit, ...rest } = draft.value.dataSource;
41
+ draft.value = { ...draft.value, dataSource: rest };
42
+ } else {
43
+ draft.value = { ...draft.value, dataSource: { ...draft.value.dataSource, request: next } };
44
+ }
45
+ }
46
+ function setOptionalExpression(key, next) {
47
+ if (next.length === 0) {
48
+ const { [key]: _omit, ...rest } = draft.value;
49
+ draft.value = rest;
50
+ } else {
51
+ draft.value = { ...draft.value, [key]: next };
52
+ }
53
+ }
54
+ function setRequired(key, next) {
55
+ draft.value = { ...draft.value, [key]: next };
56
+ }
57
+ function setNodeLabel(next) {
58
+ draft.value = { ...draft.value, nodeLabel: next };
59
+ }
60
+ </script>
61
+
62
+ <template>
63
+ <!-- Plain block wrapper, NOT a scroll container: the modal itself scrolls
64
+ (ShwfedModal's DialogScrollContent), so no inner scroll here. It must not
65
+ be a reka ScrollArea either — that wraps content in `display:table;
66
+ min-width:100%`, which makes the CodeMirror editors size to their content
67
+ width and overflow the modal. A plain block gives `w-full` children a
68
+ definite width so each editor scrolls its own long lines internally. -->
69
+ <div class="flex min-w-0 flex-col gap-3 pr-3 [&>*]:min-w-0">
70
+ <!-- 数据源 -->
71
+ <h3 class="text-xs font-medium text-zinc-500">
72
+ {{ fieldTitle("dataSource") }}
73
+ </h3>
74
+
75
+ <Field orientation="vertical">
76
+ <FieldLabel class="text-xs text-zinc-500">
77
+ <template
78
+ v-if="dsDescription('request')"
79
+ #tooltip
80
+ >
81
+ <Markdown
82
+ :source="dsDescription('request')"
83
+ block
84
+ class="prose prose-sm prose-zinc"
85
+ />
86
+ </template>
87
+ {{ dsTitle("request") }}
88
+ </FieldLabel>
89
+ <ExpressionEditor
90
+ :model-value="draft.dataSource.request ?? ''"
91
+ placeholder="如 http.get('/api/nav/tree')"
92
+ result-type="HttpRequest"
93
+ multiline
94
+ class="min-h-20"
95
+ @update:model-value="setDataSourceRequest"
96
+ />
97
+ </Field>
98
+
99
+ <Field orientation="vertical">
100
+ <FieldLabel class="text-xs text-zinc-500">
101
+ <template
102
+ v-if="dsDescription('data')"
103
+ #tooltip
104
+ >
105
+ <Markdown
106
+ :source="dsDescription('data')"
107
+ block
108
+ class="prose prose-sm prose-zinc"
109
+ />
110
+ </template>
111
+ {{ dsTitle("data") }}
112
+ </FieldLabel>
113
+ <ExpressionEditor
114
+ :model-value="draft.dataSource.data"
115
+ placeholder="如 json.?value.roots.orValue([])"
116
+ result-type="list"
117
+ :extra-vars="jsonExtraVars"
118
+ @update:model-value="setDataSourceData"
119
+ />
120
+ </Field>
121
+
122
+ <!-- 节点 -->
123
+ <h3 class="text-xs font-medium text-zinc-500">
124
+ 节点
125
+ </h3>
126
+
127
+ <div class="grid grid-cols-2 gap-3 [&>*]:min-w-0">
128
+ <Field orientation="vertical">
129
+ <FieldLabel class="text-xs text-zinc-500">
130
+ <template
131
+ v-if="fieldDescription('nodeKey')"
132
+ #tooltip
133
+ >
134
+ <Markdown
135
+ :source="fieldDescription('nodeKey')"
136
+ block
137
+ class="prose prose-sm prose-zinc"
138
+ />
139
+ </template>
140
+ {{ fieldTitle("nodeKey") }}
141
+ </FieldLabel>
142
+ <ExpressionEditor
143
+ :model-value="draft.nodeKey"
144
+ placeholder="例:string(node.id)"
145
+ :result-type="['string', 'number', 'dyn']"
146
+ :extra-vars="nodeExtraVars"
147
+ class="min-h-10"
148
+ @update:model-value="(v) => setRequired('nodeKey', v)"
149
+ />
150
+ </Field>
151
+
152
+ <Field orientation="vertical">
153
+ <FieldLabel class="text-xs text-zinc-500">
154
+ <template
155
+ v-if="fieldDescription('nodeChildren')"
156
+ #tooltip
157
+ >
158
+ <Markdown
159
+ :source="fieldDescription('nodeChildren')"
160
+ block
161
+ class="prose prose-sm prose-zinc"
162
+ />
163
+ </template>
164
+ {{ fieldTitle("nodeChildren") }}
165
+ </FieldLabel>
166
+ <ExpressionEditor
167
+ :model-value="draft.nodeChildren"
168
+ placeholder="例:has(node.children) ? node.children : null"
169
+ result-type="list"
170
+ :extra-vars="nodeExtraVars"
171
+ class="min-h-10"
172
+ @update:model-value="(v) => setRequired('nodeChildren', v)"
173
+ />
174
+ </Field>
175
+ </div>
176
+
177
+ <Field orientation="vertical">
178
+ <FieldLabel class="text-xs text-zinc-500">
179
+ <template
180
+ v-if="fieldDescription('nodeLabel')"
181
+ #tooltip
182
+ >
183
+ <Markdown
184
+ :source="fieldDescription('nodeLabel')"
185
+ block
186
+ class="prose prose-sm prose-zinc"
187
+ />
188
+ </template>
189
+ {{ fieldTitle("nodeLabel") }}
190
+ </FieldLabel>
191
+ <LocaleField
192
+ markdown
193
+ translate-hint="sidebar nav node label"
194
+ :model-value="draft.nodeLabel"
195
+ @update:model-value="setNodeLabel"
196
+ />
197
+ </Field>
198
+
199
+ <div class="grid grid-cols-2 gap-3 [&>*]:min-w-0">
200
+ <Field orientation="vertical">
201
+ <FieldLabel class="text-xs text-zinc-500">
202
+ <template
203
+ v-if="fieldDescription('nodeIcon')"
204
+ #tooltip
205
+ >
206
+ <Markdown
207
+ :source="fieldDescription('nodeIcon')"
208
+ block
209
+ class="prose prose-sm prose-zinc"
210
+ />
211
+ </template>
212
+ {{ fieldTitle("nodeIcon") }}
213
+ </FieldLabel>
214
+ <ExpressionEditor
215
+ :model-value="draft.nodeIcon ?? ''"
216
+ placeholder="例:node.icon"
217
+ :result-type="['string', 'dyn']"
218
+ :extra-vars="nodeExtraVars"
219
+ class="min-h-10"
220
+ @update:model-value="(v) => setOptionalExpression('nodeIcon', v)"
221
+ />
222
+ </Field>
223
+
224
+ <Field orientation="vertical">
225
+ <FieldLabel class="text-xs text-zinc-500">
226
+ <template
227
+ v-if="fieldDescription('nodeRoute')"
228
+ #tooltip
229
+ >
230
+ <Markdown
231
+ :source="fieldDescription('nodeRoute')"
232
+ block
233
+ class="prose prose-sm prose-zinc"
234
+ />
235
+ </template>
236
+ {{ fieldTitle("nodeRoute") }}
237
+ </FieldLabel>
238
+ <ExpressionEditor
239
+ :model-value="draft.nodeRoute ?? ''"
240
+ placeholder="例:node.route"
241
+ :result-type="['string', 'dyn']"
242
+ :extra-vars="nodeExtraVars"
243
+ class="min-h-10"
244
+ @update:model-value="(v) => setOptionalExpression('nodeRoute', v)"
245
+ />
246
+ </Field>
247
+ </div>
248
+
249
+ <!-- 行为 -->
250
+ <Field orientation="vertical">
251
+ <FieldLabel class="text-xs text-zinc-500">
252
+ <template
253
+ v-if="fieldDescription('nodeVisible')"
254
+ #tooltip
255
+ >
256
+ <Markdown
257
+ :source="fieldDescription('nodeVisible')"
258
+ block
259
+ class="prose prose-sm prose-zinc"
260
+ />
261
+ </template>
262
+ {{ fieldTitle("nodeVisible") }}
263
+ </FieldLabel>
264
+ <ExpressionEditor
265
+ :model-value="draft.nodeVisible ?? ''"
266
+ placeholder="例:node.role == 'admin'"
267
+ result-type="bool"
268
+ :extra-vars="nodeExtraVars"
269
+ class="min-h-10"
270
+ @update:model-value="(v) => setOptionalExpression('nodeVisible', v)"
271
+ />
272
+ </Field>
273
+
274
+ <!-- 外观 -->
275
+ <h3 class="text-xs font-medium text-zinc-500">
276
+ 外观
277
+ </h3>
278
+
279
+ <Field orientation="vertical">
280
+ <FieldLabel class="text-xs text-zinc-500">
281
+ <template
282
+ v-if="fieldDescription('style')"
283
+ #tooltip
284
+ >
285
+ <Markdown
286
+ :source="fieldDescription('style')"
287
+ block
288
+ class="prose prose-sm prose-zinc"
289
+ />
290
+ </template>
291
+ {{ fieldTitle("style") }}
292
+ </FieldLabel>
293
+ <ExpressionEditor
294
+ :model-value="draft.style ?? ''"
295
+ placeholder="返回 CSS 字符串或样式对象的表达式,如 'width: 14rem'"
296
+ multiline
297
+ class="min-h-16"
298
+ @update:model-value="(v) => setOptionalExpression('style', v)"
299
+ />
300
+ </Field>
301
+ </div>
302
+ </template>
@@ -0,0 +1,7 @@
1
+ import type { SidebarEditorState } from './use-editor.js';
2
+ type __VLS_Props = {
3
+ state: SidebarEditorState;
4
+ };
5
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
6
+ declare const _default: typeof __VLS_export;
7
+ export default _default;
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Client-persisted sidebar UI state, namespaced by `storageKey` so multiple
3
+ * sidebars / apps don't collide. `@vueuse/core`'s `useLocalStorage` returns the
4
+ * default on the server, so callers must only render the state-dependent UI
5
+ * inside `<ClientOnly>` to avoid a hydration mismatch (see `index.vue`).
6
+ *
7
+ * - `favorites` — the starred node keys (link nodes only).
8
+ * - `open` — per-group open/closed overrides. `undefined` for a group
9
+ * means "fall back to the default" (groups start expanded).
10
+ */
11
+ export declare function useSidebarFavorites(storageKey: string): {
12
+ favorites: import("@vueuse/core").RemovableRef<string[]>;
13
+ isFavorite: (key: string) => boolean;
14
+ toggleFavorite: (key: string) => void;
15
+ isOpen: (key: string, fallback: boolean) => boolean;
16
+ setOpen: (key: string, value: boolean) => void;
17
+ };
18
+ export type SidebarFavorites = ReturnType<typeof useSidebarFavorites>;
@@ -0,0 +1,20 @@
1
+ import { computed } from "vue";
2
+ import { useLocalStorage } from "@vueuse/core";
3
+ export function useSidebarFavorites(storageKey) {
4
+ const favorites = useLocalStorage(`${storageKey}:favorites`, []);
5
+ const openOverrides = useLocalStorage(`${storageKey}:open`, {});
6
+ const favoriteSet = computed(() => new Set(favorites.value));
7
+ function isFavorite(key) {
8
+ return favoriteSet.value.has(key);
9
+ }
10
+ function toggleFavorite(key) {
11
+ favorites.value = isFavorite(key) ? favorites.value.filter((k) => k !== key) : [...favorites.value, key];
12
+ }
13
+ function isOpen(key, fallback) {
14
+ return openOverrides.value[key] ?? fallback;
15
+ }
16
+ function setOpen(key, value) {
17
+ openOverrides.value = { ...openOverrides.value, [key]: value };
18
+ }
19
+ return { favorites, isFavorite, toggleFavorite, isOpen, setOpen };
20
+ }
@@ -0,0 +1,11 @@
1
+ import type { SidebarEditorState } from './use-editor.js';
2
+ type __VLS_Props = {
3
+ state: SidebarEditorState;
4
+ };
5
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
6
+ close: () => any;
7
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
8
+ onClose?: (() => any) | undefined;
9
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
10
+ declare const _default: typeof __VLS_export;
11
+ export default _default;
@@ -0,0 +1,49 @@
1
+ <script setup>
2
+ import { Icon } from "@iconify/vue";
3
+ import { Button } from "../ui/button";
4
+ defineOptions({ name: "ShwfedSidebarEditorFooter" });
5
+ const props = defineProps({
6
+ state: { type: Object, required: true }
7
+ });
8
+ const emit = defineEmits(["close"]);
9
+ function onDismiss() {
10
+ props.state.dismiss();
11
+ emit("close");
12
+ }
13
+ function onConfirm() {
14
+ const errorBefore = props.state.validationError.value;
15
+ props.state.confirm();
16
+ const errorAfter = props.state.validationError.value;
17
+ if (errorAfter && errorAfter !== errorBefore) return;
18
+ if (!errorAfter) emit("close");
19
+ }
20
+ </script>
21
+
22
+ <template>
23
+ <div class="flex w-full items-center justify-between gap-3">
24
+ <div class="flex flex-1 flex-col gap-1 text-xs">
25
+ <span
26
+ v-if="props.state.validationError.value"
27
+ class="text-red-500 break-all"
28
+ >{{ props.state.validationError.value }}</span>
29
+ </div>
30
+ <Button
31
+ type="button"
32
+ variant="default"
33
+ size="sm"
34
+ @click="onDismiss"
35
+ >
36
+ <Icon icon="fluent:dismiss-20-regular" />
37
+ 取消
38
+ </Button>
39
+ <Button
40
+ type="button"
41
+ variant="primary"
42
+ size="sm"
43
+ @click="onConfirm"
44
+ >
45
+ <Icon icon="fluent:checkmark-20-regular" />
46
+ 确认
47
+ </Button>
48
+ </div>
49
+ </template>
@@ -0,0 +1,11 @@
1
+ import type { SidebarEditorState } from './use-editor.js';
2
+ type __VLS_Props = {
3
+ state: SidebarEditorState;
4
+ };
5
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
6
+ close: () => any;
7
+ }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
8
+ onClose?: (() => any) | undefined;
9
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
10
+ declare const _default: typeof __VLS_export;
11
+ export default _default;
@@ -0,0 +1,50 @@
1
+ import type { Environment } from '../../vendor/cel-js/lib/index.js';
2
+ import { type SidebarConfigValue } from './schema.js';
3
+ type __VLS_Props = {
4
+ configure?: (env: Environment) => void;
5
+ editable?: boolean;
6
+ storageKey?: string;
7
+ collapsible?: 'offcanvas' | 'icon' | 'none';
8
+ width?: string;
9
+ };
10
+ type __VLS_ModelProps = {
11
+ 'config'?: SidebarConfigValue | null | undefined;
12
+ };
13
+ type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
14
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
15
+ "update:config": (value: Readonly<{
16
+ kind: "shwfed.component.sidebar";
17
+ dataSource: Readonly<{
18
+ request?: string;
19
+ data: string;
20
+ }>;
21
+ nodeKey: string;
22
+ nodeChildren: string;
23
+ nodeLabel: import("../../share/locale.js").LocaleValue;
24
+ nodeIcon?: string;
25
+ nodeRoute?: string;
26
+ nodeVisible?: string;
27
+ style?: string;
28
+ }> | null | undefined) => any;
29
+ }, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
30
+ "onUpdate:config"?: ((value: Readonly<{
31
+ kind: "shwfed.component.sidebar";
32
+ dataSource: Readonly<{
33
+ request?: string;
34
+ data: string;
35
+ }>;
36
+ nodeKey: string;
37
+ nodeChildren: string;
38
+ nodeLabel: import("../../share/locale.js").LocaleValue;
39
+ nodeIcon?: string;
40
+ nodeRoute?: string;
41
+ nodeVisible?: string;
42
+ style?: string;
43
+ }> | null | undefined) => any) | undefined;
44
+ }>, {
45
+ width: string;
46
+ collapsible: "offcanvas" | "icon" | "none";
47
+ storageKey: string;
48
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
49
+ declare const _default: typeof __VLS_export;
50
+ export default _default;
@@ -0,0 +1,100 @@
1
+ <script setup>
2
+ import { computed, ref, watch } from "vue";
3
+ import { injectCELContext } from "../../utils/cel-context";
4
+ import { Sidebar, SidebarProvider } from "../ui/sidebar";
5
+ import ShwfedModal from "../modal.vue";
6
+ import SidebarTree from "./tree.vue";
7
+ import EditorBody from "./config.vue";
8
+ import EditorFooter from "./footer.vue";
9
+ import { useSidebarEditor } from "./use-editor";
10
+ import { createSidebarConfig } from "./schema";
11
+ defineOptions({ name: "ShwfedSidebar" });
12
+ const configModel = defineModel("config", { type: null });
13
+ const config = computed({
14
+ get: () => configModel.value ?? createSidebarConfig(),
15
+ set: (next) => {
16
+ configModel.value = next;
17
+ }
18
+ });
19
+ const props = defineProps({
20
+ configure: { type: Function, required: false },
21
+ editable: { type: Boolean, required: false },
22
+ storageKey: { type: String, required: false, default: "shwfed-sidebar" },
23
+ collapsible: { type: String, required: false, default: "none" },
24
+ width: { type: String, required: false, default: "13rem" }
25
+ });
26
+ const inheritedCEL = injectCELContext();
27
+ const hostConfigure = props.configure ?? (() => {
28
+ });
29
+ const mergedConfigure = (env) => {
30
+ hostConfigure(env);
31
+ const existing = new Set(env.getDefinitions().variables.map((v) => v.name));
32
+ for (const [name, v] of Object.entries(inheritedCEL)) {
33
+ if (existing.has(name)) continue;
34
+ env.registerVariable(name, v.type, { description: v.description, label: v.label });
35
+ }
36
+ };
37
+ const editorOpen = ref(false);
38
+ const editorState = useSidebarEditor(config, {
39
+ configure: mergedConfigure,
40
+ onClose: () => {
41
+ editorOpen.value = false;
42
+ }
43
+ });
44
+ watch(editorOpen, (open, prev) => {
45
+ if (open && !prev) editorState.reset();
46
+ });
47
+ function onRootClick(event) {
48
+ if (!props.editable) return;
49
+ if (!event.metaKey && !event.ctrlKey) return;
50
+ event.preventDefault();
51
+ event.stopPropagation();
52
+ editorOpen.value = true;
53
+ }
54
+ </script>
55
+
56
+ <template>
57
+ <ClientOnly>
58
+ <div
59
+ class="contents"
60
+ @click.capture="onRootClick"
61
+ >
62
+ <SidebarProvider
63
+ class="w-fit"
64
+ :style="{ '--sidebar-width': width }"
65
+ >
66
+ <Sidebar
67
+ :collapsible="collapsible"
68
+ class="sticky h-full"
69
+ >
70
+ <SidebarTree
71
+ :config="config"
72
+ :configure="mergedConfigure"
73
+ :storage-key="storageKey"
74
+ />
75
+ </Sidebar>
76
+ </SidebarProvider>
77
+ </div>
78
+
79
+ <ShwfedModal
80
+ v-if="editable"
81
+ v-model:open="editorOpen"
82
+ content-width="min(52rem, 92vw)"
83
+ :dismissible="true"
84
+ >
85
+ <template #title>
86
+ 导航侧栏
87
+ </template>
88
+ <template #description>
89
+ <span class="sr-only">编辑导航侧栏配置</span>
90
+ </template>
91
+ <EditorBody :state="editorState" />
92
+ <template #footer>
93
+ <EditorFooter
94
+ :state="editorState"
95
+ @close="editorOpen = false"
96
+ />
97
+ </template>
98
+ </ShwfedModal>
99
+ </ClientOnly>
100
+ </template>
@@ -0,0 +1,50 @@
1
+ import type { Environment } from '../../vendor/cel-js/lib/index.js';
2
+ import { type SidebarConfigValue } from './schema.js';
3
+ type __VLS_Props = {
4
+ configure?: (env: Environment) => void;
5
+ editable?: boolean;
6
+ storageKey?: string;
7
+ collapsible?: 'offcanvas' | 'icon' | 'none';
8
+ width?: string;
9
+ };
10
+ type __VLS_ModelProps = {
11
+ 'config'?: SidebarConfigValue | null | undefined;
12
+ };
13
+ type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
14
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
15
+ "update:config": (value: Readonly<{
16
+ kind: "shwfed.component.sidebar";
17
+ dataSource: Readonly<{
18
+ request?: string;
19
+ data: string;
20
+ }>;
21
+ nodeKey: string;
22
+ nodeChildren: string;
23
+ nodeLabel: import("../../share/locale.js").LocaleValue;
24
+ nodeIcon?: string;
25
+ nodeRoute?: string;
26
+ nodeVisible?: string;
27
+ style?: string;
28
+ }> | null | undefined) => any;
29
+ }, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
30
+ "onUpdate:config"?: ((value: Readonly<{
31
+ kind: "shwfed.component.sidebar";
32
+ dataSource: Readonly<{
33
+ request?: string;
34
+ data: string;
35
+ }>;
36
+ nodeKey: string;
37
+ nodeChildren: string;
38
+ nodeLabel: import("../../share/locale.js").LocaleValue;
39
+ nodeIcon?: string;
40
+ nodeRoute?: string;
41
+ nodeVisible?: string;
42
+ style?: string;
43
+ }> | null | undefined) => any) | undefined;
44
+ }>, {
45
+ width: string;
46
+ collapsible: "offcanvas" | "icon" | "none";
47
+ storageKey: string;
48
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
49
+ declare const _default: typeof __VLS_export;
50
+ export default _default;
@@ -0,0 +1,9 @@
1
+ import type { NavNode } from './types.js';
2
+ import type { SidebarFavorites } from './favorites.js';
3
+ type __VLS_Props = {
4
+ node: NavNode;
5
+ favorites: SidebarFavorites;
6
+ };
7
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
8
+ declare const _default: typeof __VLS_export;
9
+ export default _default;