@shwfed/config 2.12.5 → 2.12.7

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 (137) hide show
  1. package/dist/module.json +1 -1
  2. package/dist/module.mjs +5 -0
  3. package/dist/runtime/components/config/blocks/2026-06-17/com.shwfed.block.tree.single/runtime.vue +54 -50
  4. package/dist/runtime/components/config/index.vue +23 -3
  5. package/dist/runtime/components/form/fields/2026-04-22/com.shwfed.form.field.text/config.d.vue.ts +22 -22
  6. package/dist/runtime/components/form/fields/2026-04-22/com.shwfed.form.field.text/config.vue.d.ts +22 -22
  7. package/dist/runtime/components/form/fields/2026-04-24/com.shwfed.form.field.combobox.single/config.d.vue.ts +16 -16
  8. package/dist/runtime/components/form/fields/2026-04-24/com.shwfed.form.field.combobox.single/config.vue.d.ts +16 -16
  9. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.date/config.d.vue.ts +16 -16
  10. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.date/config.vue.d.ts +16 -16
  11. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.daterange/config.d.vue.ts +24 -24
  12. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.daterange/config.vue.d.ts +24 -24
  13. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.datetime/config.d.vue.ts +16 -16
  14. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.datetime/config.vue.d.ts +16 -16
  15. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.datetimerange/config.d.vue.ts +26 -26
  16. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.datetimerange/config.vue.d.ts +26 -26
  17. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.timerange/config.d.vue.ts +2 -2
  18. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.timerange/config.vue.d.ts +2 -2
  19. package/dist/runtime/components/form/fields/2026-04-28/com.shwfed.form.field.number/config.d.vue.ts +30 -28
  20. package/dist/runtime/components/form/fields/2026-04-28/com.shwfed.form.field.number/config.vue +38 -0
  21. package/dist/runtime/components/form/fields/2026-04-28/com.shwfed.form.field.number/config.vue.d.ts +30 -28
  22. package/dist/runtime/components/form/fields/2026-04-28/com.shwfed.form.field.number/runtime.vue +11 -2
  23. package/dist/runtime/components/form/fields/2026-04-28/com.shwfed.form.field.number/schema.d.ts +3 -0
  24. package/dist/runtime/components/form/fields/2026-04-28/com.shwfed.form.field.number/schema.js +7 -0
  25. package/dist/runtime/components/form/fields/2026-04-28/com.shwfed.form.field.numberrange/config.d.vue.ts +6 -6
  26. package/dist/runtime/components/form/fields/2026-04-28/com.shwfed.form.field.numberrange/config.vue.d.ts +6 -6
  27. package/dist/runtime/components/form/fields/2026-04-28/com.shwfed.form.field.switch/config.d.vue.ts +22 -22
  28. package/dist/runtime/components/form/fields/2026-04-28/com.shwfed.form.field.switch/config.vue.d.ts +22 -22
  29. package/dist/runtime/components/form/fields/2026-05-13/com.shwfed.form.field.combobox.single.remote/config.d.vue.ts +16 -16
  30. package/dist/runtime/components/form/fields/2026-05-13/com.shwfed.form.field.combobox.single.remote/config.vue.d.ts +16 -16
  31. package/dist/runtime/components/form/fields/2026-05-23/com.shwfed.form.field.tree.multi/config.d.vue.ts +10 -10
  32. package/dist/runtime/components/form/fields/2026-05-23/com.shwfed.form.field.tree.multi/config.vue.d.ts +10 -10
  33. package/dist/runtime/components/form/fields/2026-05-24/com.shwfed.form.field.month/config.d.vue.ts +16 -16
  34. package/dist/runtime/components/form/fields/2026-05-24/com.shwfed.form.field.month/config.vue.d.ts +16 -16
  35. package/dist/runtime/components/form/fields/2026-05-24/com.shwfed.form.field.monthrange/config.d.vue.ts +24 -24
  36. package/dist/runtime/components/form/fields/2026-05-24/com.shwfed.form.field.monthrange/config.vue.d.ts +24 -24
  37. package/dist/runtime/components/form/fields/2026-05-25/com.shwfed.form.field.combobox.multi/config.d.vue.ts +16 -16
  38. package/dist/runtime/components/form/fields/2026-05-25/com.shwfed.form.field.combobox.multi/config.vue.d.ts +16 -16
  39. package/dist/runtime/components/form/fields/2026-05-26/com.shwfed.form.field.tree.combobox.multi/config.d.vue.ts +10 -10
  40. package/dist/runtime/components/form/fields/2026-05-26/com.shwfed.form.field.tree.combobox.multi/config.vue.d.ts +10 -10
  41. package/dist/runtime/components/form/fields/2026-05-26/com.shwfed.form.field.tree.combobox.single/config.d.vue.ts +10 -10
  42. package/dist/runtime/components/form/fields/2026-05-26/com.shwfed.form.field.tree.combobox.single/config.vue.d.ts +10 -10
  43. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.multi/config.d.vue.ts +10 -10
  44. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.multi/config.vue.d.ts +10 -10
  45. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.single/config.d.vue.ts +10 -10
  46. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.single/config.vue.d.ts +10 -10
  47. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.multi/config.d.vue.ts +10 -10
  48. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.multi/config.vue.d.ts +10 -10
  49. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.single/config.d.vue.ts +10 -10
  50. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.single/config.vue.d.ts +10 -10
  51. package/dist/runtime/components/sidebar/index.d.vue.ts +22 -3
  52. package/dist/runtime/components/sidebar/index.vue +66 -5
  53. package/dist/runtime/components/sidebar/index.vue.d.ts +22 -3
  54. package/dist/runtime/components/sidebar/node.d.vue.ts +1 -1
  55. package/dist/runtime/components/sidebar/node.vue +33 -13
  56. package/dist/runtime/components/sidebar/node.vue.d.ts +1 -1
  57. package/dist/runtime/components/sidebar/tree.vue +113 -83
  58. package/dist/runtime/components/sidebar/types.d.ts +8 -0
  59. package/dist/runtime/components/sidebar/types.js +1 -0
  60. package/dist/runtime/components/table/columns/2026-04-14/com.shwfed.table.column.number/runtime.vue +6 -73
  61. package/dist/runtime/components/table/columns/2026-05-20/com.shwfed.table.column.combobox-single/config.d.vue.ts +2 -2
  62. package/dist/runtime/components/table/columns/2026-05-20/com.shwfed.table.column.combobox-single/config.vue.d.ts +2 -2
  63. package/dist/runtime/components/table/columns/2026-05-20/com.shwfed.table.column.number-input/config.vue +44 -0
  64. package/dist/runtime/components/table/columns/2026-05-20/com.shwfed.table.column.number-input/runtime.vue +8 -2
  65. package/dist/runtime/components/table/columns/2026-05-20/com.shwfed.table.column.number-input/schema.d.ts +3 -0
  66. package/dist/runtime/components/table/columns/2026-05-20/com.shwfed.table.column.number-input/schema.js +7 -0
  67. package/dist/runtime/components/table/columns/2026-05-24/com.shwfed.table.column.combobox-single.remote.options-remote/config.d.vue.ts +6 -6
  68. package/dist/runtime/components/table/columns/2026-05-24/com.shwfed.table.column.combobox-single.remote.options-remote/config.vue.d.ts +6 -6
  69. package/dist/runtime/components/table/columns/2026-05-24/com.shwfed.table.column.combobox-single.remote.options-static/config.d.vue.ts +2 -2
  70. package/dist/runtime/components/table/columns/2026-05-24/com.shwfed.table.column.combobox-single.remote.options-static/config.vue.d.ts +2 -2
  71. package/dist/runtime/components/table/columns/2026-05-25/com.shwfed.table.column.combobox-multi/config.d.vue.ts +2 -2
  72. package/dist/runtime/components/table/columns/2026-05-25/com.shwfed.table.column.combobox-multi/config.vue.d.ts +2 -2
  73. package/dist/runtime/components/table/columns/2026-05-25/com.shwfed.table.column.combobox-multi.remote.options-remote/config.d.vue.ts +6 -6
  74. package/dist/runtime/components/table/columns/2026-05-25/com.shwfed.table.column.combobox-multi.remote.options-remote/config.vue.d.ts +6 -6
  75. package/dist/runtime/components/table/columns/2026-05-25/com.shwfed.table.column.combobox-multi.remote.options-static/config.d.vue.ts +2 -2
  76. package/dist/runtime/components/table/columns/2026-05-25/com.shwfed.table.column.combobox-multi.remote.options-static/config.vue.d.ts +2 -2
  77. package/dist/runtime/components/table/columns/2026-05-26/com.shwfed.table.column.combobox-multi/config.d.vue.ts +2 -2
  78. package/dist/runtime/components/table/columns/2026-05-26/com.shwfed.table.column.combobox-multi/config.vue.d.ts +2 -2
  79. package/dist/runtime/components/table/columns/2026-05-26/com.shwfed.table.column.combobox-multi.remote/config.d.vue.ts +2 -2
  80. package/dist/runtime/components/table/columns/2026-05-26/com.shwfed.table.column.combobox-multi.remote/config.vue.d.ts +2 -2
  81. package/dist/runtime/components/table/columns/2026-05-26/com.shwfed.table.column.combobox-single/config.d.vue.ts +2 -2
  82. package/dist/runtime/components/table/columns/2026-05-26/com.shwfed.table.column.combobox-single/config.vue.d.ts +2 -2
  83. package/dist/runtime/components/table/columns/2026-05-26/com.shwfed.table.column.combobox-single.remote/config.d.vue.ts +2 -2
  84. package/dist/runtime/components/table/columns/2026-05-26/com.shwfed.table.column.combobox-single.remote/config.vue.d.ts +2 -2
  85. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-multi/config.d.vue.ts +10 -10
  86. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-multi/config.vue.d.ts +10 -10
  87. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-single/config.d.vue.ts +10 -10
  88. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-single/config.vue.d.ts +10 -10
  89. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-multi/config.d.vue.ts +2 -2
  90. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-multi/config.vue.d.ts +2 -2
  91. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-single/config.d.vue.ts +2 -2
  92. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-single/config.vue.d.ts +2 -2
  93. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-multi/config.d.vue.ts +10 -10
  94. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-multi/config.vue.d.ts +10 -10
  95. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-single/config.d.vue.ts +10 -10
  96. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-single/config.vue.d.ts +10 -10
  97. package/dist/runtime/components/table/columns/2026-06-14/com.shwfed.table.column.combobox-multi/config.d.vue.ts +2 -2
  98. package/dist/runtime/components/table/columns/2026-06-14/com.shwfed.table.column.combobox-multi/config.vue.d.ts +2 -2
  99. package/dist/runtime/components/table/columns/2026-06-14/com.shwfed.table.column.combobox-single/config.d.vue.ts +2 -2
  100. package/dist/runtime/components/table/columns/2026-06-14/com.shwfed.table.column.combobox-single/config.vue.d.ts +2 -2
  101. package/dist/runtime/components/table/columns/2026-06-14/com.shwfed.table.column.tree-combobox-multi/config.d.vue.ts +10 -10
  102. package/dist/runtime/components/table/columns/2026-06-14/com.shwfed.table.column.tree-combobox-multi/config.vue.d.ts +10 -10
  103. package/dist/runtime/components/table/columns/2026-06-14/com.shwfed.table.column.tree-combobox-single/config.d.vue.ts +10 -10
  104. package/dist/runtime/components/table/columns/2026-06-14/com.shwfed.table.column.tree-combobox-single/config.vue.d.ts +10 -10
  105. package/dist/runtime/components/table/utils/row-reorder.d.ts +3 -2
  106. package/dist/runtime/components/table/utils/row-reorder.js +1 -12
  107. package/dist/runtime/components/tabs/index.d.vue.ts +9 -0
  108. package/dist/runtime/components/tabs/index.vue +92 -0
  109. package/dist/runtime/components/tabs/index.vue.d.ts +9 -0
  110. package/dist/runtime/components/tabs/tab.d.vue.ts +22 -0
  111. package/dist/runtime/components/tabs/tab.vue +85 -0
  112. package/dist/runtime/components/tabs/tab.vue.d.ts +22 -0
  113. package/dist/runtime/components/tabs/types.d.ts +19 -0
  114. package/dist/runtime/components/tabs/types.js +0 -0
  115. package/dist/runtime/components/tabs/use-reorder.d.ts +10 -0
  116. package/dist/runtime/components/tabs/use-reorder.js +90 -0
  117. package/dist/runtime/components/tabs/use-tabs.d.ts +46 -0
  118. package/dist/runtime/components/tabs/use-tabs.js +101 -0
  119. package/dist/runtime/components/ui/date-picker/DatePickerInput.d.vue.ts +1 -1
  120. package/dist/runtime/components/ui/date-picker/DatePickerInput.vue.d.ts +1 -1
  121. package/dist/runtime/components/ui/date-picker/DatePickerTimeInput.d.vue.ts +1 -1
  122. package/dist/runtime/components/ui/date-picker/DatePickerTimeInput.vue.d.ts +1 -1
  123. package/dist/runtime/components/ui/date-range-picker/DateRangePickerInput.d.vue.ts +1 -1
  124. package/dist/runtime/components/ui/date-range-picker/DateRangePickerInput.vue.d.ts +1 -1
  125. package/dist/runtime/components/ui/date-range-picker/DateRangePickerTimeInput.d.vue.ts +2 -2
  126. package/dist/runtime/components/ui/date-range-picker/DateRangePickerTimeInput.vue.d.ts +2 -2
  127. package/dist/runtime/components/ui/sidebar/SidebarMenuAction.vue +1 -1
  128. package/dist/runtime/components/ui/sidebar/index.js +2 -2
  129. package/dist/runtime/share/number-format.d.ts +7 -0
  130. package/dist/runtime/share/number-format.js +72 -0
  131. package/dist/runtime/share/reorder.d.ts +2 -0
  132. package/dist/runtime/share/reorder.js +12 -0
  133. package/dist/runtime/utils/nav-registry.d.ts +19 -0
  134. package/dist/runtime/utils/nav-registry.js +14 -0
  135. package/dist/runtime/utils/page-title-registry.d.ts +3 -0
  136. package/dist/runtime/utils/page-title-registry.js +11 -0
  137. package/package.json +1 -1
@@ -1,4 +1,4 @@
1
- import type { NavNode } from './types.js';
1
+ import { type NavNode } from './types.js';
2
2
  import type { SidebarFavorites } from './favorites.js';
3
3
  type __VLS_Props = {
4
4
  node: NavNode;
@@ -1,4 +1,5 @@
1
1
  <script setup>
2
+ import { computed, inject } from "vue";
2
3
  import { Icon } from "@iconify/vue";
3
4
  import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "../ui/collapsible";
4
5
  import {
@@ -7,35 +8,52 @@ import {
7
8
  SidebarMenuItem,
8
9
  SidebarMenuSub
9
10
  } from "../ui/sidebar";
11
+ import { SIDEBAR_ACTIVE_KEYS } from "./types";
10
12
  defineOptions({ name: "ShwfedSidebarNode" });
11
13
  const props = defineProps({
12
14
  node: { type: Object, required: true },
13
15
  favorites: { type: null, required: true }
14
16
  });
17
+ const activeKeys = inject(SIDEBAR_ACTIVE_KEYS, void 0);
18
+ const isActive = computed(() => {
19
+ const keys = activeKeys?.value;
20
+ if (!keys) return false;
21
+ if (keys.has(props.node.key)) return true;
22
+ const stack = [...props.node.children];
23
+ while (stack.length) {
24
+ const n = stack.pop();
25
+ if (keys.has(n.key)) return true;
26
+ for (const c of n.children) stack.push(c);
27
+ }
28
+ return false;
29
+ });
30
+ const isLeaf = computed(() => props.node.children.length === 0 && !!props.node.route);
15
31
  function onOpenUpdate(open) {
16
32
  props.favorites.setOpen(props.node.key, open);
17
33
  }
18
34
  </script>
19
35
 
20
36
  <template>
21
- <SidebarMenuItem>
37
+ <SidebarMenuItem :class="isLeaf ? 'group/nav-leaf' : void 0">
22
38
  <!-- Group: collapsible, recurses into a sub-menu -->
23
39
  <Collapsible
24
40
  v-if="node.children.length"
25
- class="group/collapsible"
26
- :open="favorites.isOpen(node.key, true)"
41
+ :open="favorites.isOpen(node.key, false)"
27
42
  @update:open="onOpenUpdate"
28
43
  >
29
44
  <CollapsibleTrigger as-child>
30
- <SidebarMenuButton>
45
+ <SidebarMenuButton
46
+ :is-active="isActive"
47
+ :data-nav-key="node.key"
48
+ >
31
49
  <Icon
32
50
  v-if="node.icon"
33
51
  :icon="node.icon"
34
52
  />
35
- <span>{{ node.label }}</span>
53
+ <span class="truncate">{{ node.label }}</span>
36
54
  <Icon
37
- icon="fluent:chevron-right-20-regular"
38
- class="ml-auto transition-transform group-data-[state=open]/collapsible:rotate-90"
55
+ icon="fluent:chevron-down-20-regular"
56
+ class="ml-auto shrink-0 text-zinc-400"
39
57
  />
40
58
  </SidebarMenuButton>
41
59
  </CollapsibleTrigger>
@@ -57,28 +75,30 @@ function onOpenUpdate(open) {
57
75
  :to="node.route"
58
76
  custom
59
77
  >
60
- <template #default="{ navigate, isExactActive }">
78
+ <template #default="{ navigate }">
61
79
  <SidebarMenuButton
62
80
  as-child
63
- :is-active="isExactActive"
81
+ :is-active="isActive"
82
+ :class="isActive ? void 0 : 'group-hover/nav-leaf:bg-zinc-100 group-hover/nav-leaf:text-zinc-900'"
64
83
  >
65
84
  <button
66
85
  type="button"
86
+ :data-nav-key="node.key"
67
87
  @click="navigate"
68
88
  >
69
89
  <Icon
70
90
  v-if="node.icon"
71
91
  :icon="node.icon"
72
92
  />
73
- <span>{{ node.label }}</span>
93
+ <span class="truncate">{{ node.label }}</span>
74
94
  </button>
75
95
  </SidebarMenuButton>
76
96
  </template>
77
97
  </NuxtLink>
78
98
  <SidebarMenuAction
79
99
  v-if="node.favoritable"
80
- :show-on-hover="!favorites.isFavorite(node.key)"
81
- class="text-yellow-500!"
100
+ class="text-yellow-500! transition-opacity"
101
+ :class="favorites.isFavorite(node.key) ? 'opacity-100' : 'md:opacity-0 group-hover/nav-leaf:opacity-100 group-focus-within/nav-leaf:opacity-100'"
82
102
  @click.stop="favorites.toggleFavorite(node.key)"
83
103
  >
84
104
  <Icon :icon="favorites.isFavorite(node.key) ? 'fluent:star-20-filled' : 'fluent:star-20-regular'" />
@@ -95,7 +115,7 @@ function onOpenUpdate(open) {
95
115
  v-if="node.icon"
96
116
  :icon="node.icon"
97
117
  />
98
- <span>{{ node.label }}</span>
118
+ <span class="truncate">{{ node.label }}</span>
99
119
  </span>
100
120
  </SidebarMenuButton>
101
121
  </SidebarMenuItem>
@@ -1,4 +1,4 @@
1
- import type { NavNode } from './types.js';
1
+ import { type NavNode } from './types.js';
2
2
  import type { SidebarFavorites } from './favorites.js';
3
3
  type __VLS_Props = {
4
4
  node: NavNode;
@@ -1,19 +1,21 @@
1
1
  <script setup>
2
- import { Icon } from "@iconify/vue";
3
2
  import { Effect, Fiber, Option } from "effect";
4
3
  import { Fetch } from "fx-fetch";
5
- import { computed, ref, watch } from "vue";
4
+ import { computed, nextTick, onBeforeUnmount, provide, ref, watch } from "vue";
6
5
  import { useI18n } from "vue-i18n";
6
+ import { useRoute } from "#app";
7
+ import { clearNavLabels, publishNavLabels } from "../../utils/nav-registry";
7
8
  import { fetchJsonOption } from "../../share/request";
8
9
  import { cel as _rawCel } from "../../utils/cel";
9
10
  import { celBindings, injectCELContext } from "../../utils/cel-context";
10
11
  import { getLocalizedText } from "../../share/locale";
11
12
  import { interpolateMarkdown } from "../table/utils/runtime";
12
- import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "../ui/collapsible";
13
- import { SidebarContent, SidebarGroup, SidebarGroupContent, SidebarGroupLabel, SidebarMenu } from "../ui/sidebar";
13
+ import { SidebarGroup, SidebarGroupContent, SidebarGroupLabel, SidebarMenu } from "../ui/sidebar";
14
+ import { ScrollArea } from "../ui/scroll-area";
14
15
  import { Skeleton } from "../ui/skeleton";
15
16
  import SidebarNode from "./node.vue";
16
17
  import { useSidebarFavorites } from "./favorites";
18
+ import { SIDEBAR_ACTIVE_KEYS } from "./types";
17
19
  defineOptions({ name: "ShwfedSidebarTree" });
18
20
  const props = defineProps({
19
21
  config: { type: Object, required: true },
@@ -24,10 +26,10 @@ const { locale, t } = useI18n({
24
26
  inheritLocale: true,
25
27
  useScope: "global",
26
28
  messages: {
27
- zh: { "sidebar-favorites": "\u6536\u85CF" },
28
- en: { "sidebar-favorites": "Favorites" },
29
- ja: { "sidebar-favorites": "\u304A\u6C17\u306B\u5165\u308A" },
30
- ko: { "sidebar-favorites": "\uC990\uACA8\uCC3E\uAE30" }
29
+ zh: { "sidebar-favorites": "\u6536\u85CF", "sidebar-menu": "\u83DC\u5355" },
30
+ en: { "sidebar-favorites": "Favorites", "sidebar-menu": "Menu" },
31
+ ja: { "sidebar-favorites": "\u304A\u6C17\u306B\u5165\u308A", "sidebar-menu": "\u30E1\u30CB\u30E5\u30FC" },
32
+ ko: { "sidebar-favorites": "\uC990\uACA8\uCC3E\uAE30", "sidebar-menu": "\uBA54\uB274" }
31
33
  }
32
34
  });
33
35
  const favorites = useSidebarFavorites(props.storageKey);
@@ -143,13 +145,13 @@ function nodeLabelText(node) {
143
145
  function buildNode(raw) {
144
146
  if (!nodeVisible(raw)) return null;
145
147
  const children = getChildren(raw).map(buildNode).filter((n) => n !== null);
146
- const route = getOptionalString(props.config.nodeRoute, raw);
148
+ const route2 = getOptionalString(props.config.nodeRoute, raw);
147
149
  return {
148
150
  key: getKey(raw),
149
151
  label: nodeLabelText(raw),
150
152
  icon: getOptionalString(props.config.nodeIcon, raw),
151
- route,
152
- favoritable: children.length === 0 && !!route,
153
+ route: route2,
154
+ favoritable: children.length === 0 && !!route2,
153
155
  children
154
156
  };
155
157
  }
@@ -167,87 +169,115 @@ const favoriteNodes = computed(() => {
167
169
  walk(tree.value);
168
170
  return out;
169
171
  });
172
+ const route = useRoute();
173
+ function nodePath(r) {
174
+ if (!r) return void 0;
175
+ return r.split(/[?#]/, 1)[0];
176
+ }
177
+ function nodeFull(r) {
178
+ if (!r) return void 0;
179
+ return r.split("#")[0];
180
+ }
181
+ const routedNodes = computed(() => {
182
+ const out = [];
183
+ const walk = (ns) => {
184
+ for (const n of ns) {
185
+ if (n.route) out.push(n);
186
+ if (n.children.length) walk(n.children);
187
+ }
188
+ };
189
+ walk(tree.value);
190
+ return out;
191
+ });
192
+ watch(routedNodes, (nodes) => {
193
+ const full = /* @__PURE__ */ new Map();
194
+ const path = /* @__PURE__ */ new Map();
195
+ for (const n of nodes) {
196
+ const f = nodeFull(n.route);
197
+ const p = nodePath(n.route);
198
+ if (f && !full.has(f)) full.set(f, { label: n.label, icon: n.icon });
199
+ if (p && !path.has(p)) path.set(p, { label: n.label, icon: n.icon });
200
+ }
201
+ publishNavLabels(full, path);
202
+ }, { immediate: true });
203
+ onBeforeUnmount(() => clearNavLabels());
204
+ const activeKeys = computed(() => {
205
+ const full = nodeFull(route.fullPath);
206
+ const path = nodePath(route.fullPath);
207
+ const exact = routedNodes.value.filter((n) => nodeFull(n.route) === full);
208
+ if (exact.length > 0) return new Set(exact.map((n) => n.key));
209
+ return new Set(routedNodes.value.filter((n) => nodePath(n.route) === path).map((n) => n.key));
210
+ });
211
+ provide(SIDEBAR_ACTIVE_KEYS, activeKeys);
212
+ function findTrail(nodes, key) {
213
+ for (const n of nodes) {
214
+ if (n.key === key) return [n.key];
215
+ const sub = findTrail(n.children, key);
216
+ if (sub) return [n.key, ...sub];
217
+ }
218
+ return null;
219
+ }
220
+ watch(activeKeys, (keys) => {
221
+ const first = keys.values().next().value;
222
+ if (!first) return;
223
+ const trail = findTrail(tree.value, first);
224
+ if (!trail) return;
225
+ for (const key of trail.slice(0, -1)) favorites.setOpen(key, true);
226
+ void nextTick(() => {
227
+ for (let i = trail.length - 1; i >= 0; i--) {
228
+ const key = trail[i];
229
+ if (!key) continue;
230
+ const el = document.querySelector(`[data-nav-key="${key.replace(/["\\]/g, "\\$&")}"]`);
231
+ if (el) {
232
+ el.scrollIntoView({ block: "nearest" });
233
+ break;
234
+ }
235
+ }
236
+ });
237
+ }, { immediate: true });
170
238
  </script>
171
239
 
172
240
  <template>
173
- <SidebarContent
174
- class="gap-2 py-1"
175
- :style="styleValue"
176
- >
241
+ <ScrollArea class="min-h-0 w-full flex-1">
177
242
  <div
178
- v-if="loading && roots.length === 0"
179
- class="flex flex-col gap-1.5 px-2 py-1"
180
- aria-busy="true"
243
+ class="flex flex-col gap-2 py-1"
244
+ :style="styleValue"
181
245
  >
182
- <Skeleton class="h-6 w-2/3" />
183
- <Skeleton class="h-6 w-1/2" />
184
- <Skeleton class="h-6 w-3/5" />
185
- </div>
186
-
187
- <template v-else>
188
- <SidebarGroup v-if="favoriteNodes.length">
189
- <SidebarGroupLabel class="text-sm text-zinc-700">
190
- {{ t("sidebar-favorites") }}
191
- </SidebarGroupLabel>
192
- <SidebarGroupContent>
193
- <SidebarMenu>
194
- <SidebarNode
195
- v-for="n in favoriteNodes"
196
- :key="`fav-${n.key}`"
197
- :node="n"
198
- :favorites="favorites"
199
- />
200
- </SidebarMenu>
201
- </SidebarGroupContent>
202
- </SidebarGroup>
203
-
204
- <template
205
- v-for="n in tree"
206
- :key="n.key"
246
+ <div
247
+ v-if="loading && roots.length === 0"
248
+ class="flex flex-col gap-1.5 px-2 py-1"
249
+ aria-busy="true"
207
250
  >
208
- <!-- Top-level group: the group label IS the collapsible trigger -->
209
- <SidebarGroup v-if="n.children.length">
210
- <Collapsible
211
- class="group/collapsible"
212
- :open="favorites.isOpen(n.key, true)"
213
- @update:open="(v) => favorites.setOpen(n.key, v)"
214
- >
215
- <SidebarGroupLabel
216
- as-child
217
- class="group/label w-full cursor-pointer text-sm text-zinc-700 hover:bg-zinc-100 hover:text-zinc-900"
218
- >
219
- <CollapsibleTrigger class="w-full">
220
- <Icon
221
- v-if="n.icon"
222
- :icon="n.icon"
223
- />
224
- {{ n.label }}
225
- <Icon
226
- icon="fluent:chevron-right-20-regular"
227
- class="ml-auto transition-transform group-data-[state=open]/collapsible:rotate-90"
228
- />
229
- </CollapsibleTrigger>
230
- </SidebarGroupLabel>
231
- <CollapsibleContent class="overflow-hidden data-[state=open]:overflow-visible">
232
- <SidebarGroupContent>
233
- <SidebarMenu class="pl-4">
234
- <SidebarNode
235
- v-for="child in n.children"
236
- :key="child.key"
237
- :node="child"
238
- :favorites="favorites"
239
- />
240
- </SidebarMenu>
241
- </SidebarGroupContent>
242
- </CollapsibleContent>
243
- </Collapsible>
251
+ <Skeleton class="h-6 w-2/3" />
252
+ <Skeleton class="h-6 w-1/2" />
253
+ <Skeleton class="h-6 w-3/5" />
254
+ </div>
255
+
256
+ <template v-else>
257
+ <!-- User favorites -->
258
+ <SidebarGroup v-if="favoriteNodes.length">
259
+ <SidebarGroupLabel>{{ t("sidebar-favorites") }}</SidebarGroupLabel>
260
+ <SidebarGroupContent>
261
+ <SidebarMenu>
262
+ <SidebarNode
263
+ v-for="n in favoriteNodes"
264
+ :key="`fav-${n.key}`"
265
+ :node="n"
266
+ :favorites="favorites"
267
+ />
268
+ </SidebarMenu>
269
+ </SidebarGroupContent>
244
270
  </SidebarGroup>
245
271
 
246
- <!-- Top-level direct link -->
247
- <SidebarGroup v-else>
272
+ <!-- System menu — top-level items render inline (collapsible); deeper
273
+ nesting cascades in a flyout (see node.vue). -->
274
+ <SidebarGroup v-if="tree.length">
275
+ <SidebarGroupLabel>{{ t("sidebar-menu") }}</SidebarGroupLabel>
248
276
  <SidebarGroupContent>
249
277
  <SidebarMenu>
250
278
  <SidebarNode
279
+ v-for="n in tree"
280
+ :key="n.key"
251
281
  :node="n"
252
282
  :favorites="favorites"
253
283
  />
@@ -255,6 +285,6 @@ const favoriteNodes = computed(() => {
255
285
  </SidebarGroupContent>
256
286
  </SidebarGroup>
257
287
  </template>
258
- </template>
259
- </SidebarContent>
288
+ </div>
289
+ </ScrollArea>
260
290
  </template>
@@ -1,3 +1,11 @@
1
+ import type { ComputedRef, InjectionKey } from 'vue';
2
+ /**
3
+ * The set of node keys that are "active" for the current location, computed once
4
+ * in `tree.vue` (query-aware — exact full-route match wins, path match is the
5
+ * fallback) and injected into every `node.vue` so highlighting is consistent and
6
+ * a query variant lights up only its own node.
7
+ */
8
+ export declare const SIDEBAR_ACTIVE_KEYS: InjectionKey<ComputedRef<Set<string>>>;
1
9
  /**
2
10
  * A normalized navigation node — the product of walking the raw `DataSource`
3
11
  * payload and evaluating every per-node CEL expression once. The recursive
@@ -0,0 +1 @@
1
+ export const SIDEBAR_ACTIVE_KEYS = Symbol("shwfed-sidebar-active-keys");
@@ -1,84 +1,17 @@
1
1
  <script setup>
2
2
  import { computed } from "vue";
3
3
  import { JUSTIFY_CLASS } from "../../../utils/runtime";
4
+ import { formatNumberDisplay } from "../../../../../share/number-format";
4
5
  defineOptions({ name: "ShwfedTableNumberRendererRuntime" });
5
6
  const props = defineProps({
6
7
  column: { type: null, required: true },
7
8
  ctx: { type: Object, required: true }
8
9
  });
9
- const CHINESE_DIGITS = ["\u96F6", "\u58F9", "\u8D30", "\u53C1", "\u8086", "\u4F0D", "\u9646", "\u67D2", "\u634C", "\u7396"];
10
- const CHINESE_UNITS = ["", "\u62FE", "\u4F70", "\u4EDF"];
11
- const CHINESE_GROUP_UNITS = ["", "\u4E07", "\u4EBF", "\u5146"];
12
- function toChineseUppercase(n) {
13
- if (Number.isNaN(n)) return "-";
14
- if (n === 0) return "\u96F6";
15
- const isNegative = n < 0;
16
- const absN = Math.abs(n);
17
- const [intPart, decPart] = String(absN).split(".");
18
- let result = "";
19
- const digits = intPart.split("").reverse();
20
- let zeroFlag = false;
21
- for (let i = 0; i < digits.length; i++) {
22
- const d = Number(digits[i]);
23
- const groupIndex = Math.floor(i / 4);
24
- const posInGroup = i % 4;
25
- if (d === 0) {
26
- zeroFlag = true;
27
- } else {
28
- if (zeroFlag) {
29
- result = CHINESE_DIGITS[0] + result;
30
- zeroFlag = false;
31
- }
32
- result = CHINESE_DIGITS[d] + CHINESE_UNITS[posInGroup] + result;
33
- }
34
- if (posInGroup === 0 && groupIndex > 0 && !zeroFlag) {
35
- result = (CHINESE_GROUP_UNITS[groupIndex] ?? "") + result;
36
- }
37
- }
38
- if (decPart) {
39
- result += "\u70B9";
40
- for (const ch of decPart) {
41
- result += CHINESE_DIGITS[Number(ch)];
42
- }
43
- }
44
- return isNegative ? `\u8D1F${result}` : result;
45
- }
46
- function formatNumber(value, column) {
47
- if (value === void 0 || value === null) return "-";
48
- const n = Number(value);
49
- if (Number.isNaN(n)) return "-";
50
- const displayMode = column.displayMode ?? "plain";
51
- if (displayMode === "uppercaseChinese") {
52
- return toChineseUppercase(n);
53
- }
54
- let result;
55
- if (column.preserveDigits !== void 0) {
56
- const mode = column.preserveMode ?? "round";
57
- const digits = column.preserveDigits;
58
- const factor = 10 ** digits;
59
- let processed;
60
- switch (mode) {
61
- case "floor":
62
- processed = Math.floor(n * factor) / factor;
63
- break;
64
- case "ceil":
65
- processed = Math.ceil(n * factor) / factor;
66
- break;
67
- default:
68
- processed = Math.round(n * factor) / factor;
69
- }
70
- result = processed.toFixed(digits);
71
- } else {
72
- result = String(n);
73
- }
74
- if (displayMode === "monoThousand") {
75
- const [integer, decimal] = result.split(".");
76
- const formattedInt = integer.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
77
- result = decimal !== void 0 ? `${formattedInt}.${decimal}` : formattedInt;
78
- }
79
- return result;
80
- }
81
- const formatted = computed(() => formatNumber(props.ctx.cell.getValue(), props.column));
10
+ const formatted = computed(() => formatNumberDisplay(props.ctx.cell.getValue(), {
11
+ displayMode: props.column.displayMode,
12
+ precision: props.column.preserveDigits,
13
+ roundingMode: props.column.preserveMode
14
+ }));
82
15
  const isNan = computed(() => formatted.value === "-");
83
16
  const align = computed(() => isNan.value ? "center" : props.column.align ?? "right");
84
17
  const justifyClass = computed(() => JUSTIFY_CLASS[align.value] ?? JUSTIFY_CLASS.right);
@@ -58,12 +58,12 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
58
58
  readonly message: string;
59
59
  }[]] | undefined;
60
60
  readonly readonly?: string | undefined;
61
- readonly enableSorting?: boolean | undefined;
62
61
  readonly binding: string;
63
62
  readonly derived?: {
64
63
  readonly mode: "formula" | "prefill";
65
64
  readonly expression: string;
66
65
  } | undefined;
66
+ readonly enableSorting?: boolean | undefined;
67
67
  readonly sortKey?: string | undefined;
68
68
  }) => any;
69
69
  }, string, import("vue").PublicProps, Readonly<__VLS_ModelProps> & Readonly<{
@@ -122,12 +122,12 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
122
122
  readonly message: string;
123
123
  }[]] | undefined;
124
124
  readonly readonly?: string | undefined;
125
- readonly enableSorting?: boolean | undefined;
126
125
  readonly binding: string;
127
126
  readonly derived?: {
128
127
  readonly mode: "formula" | "prefill";
129
128
  readonly expression: string;
130
129
  } | undefined;
130
+ readonly enableSorting?: boolean | undefined;
131
131
  readonly sortKey?: string | undefined;
132
132
  }) => any) | undefined;
133
133
  }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
@@ -58,12 +58,12 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
58
58
  readonly message: string;
59
59
  }[]] | undefined;
60
60
  readonly readonly?: string | undefined;
61
- readonly enableSorting?: boolean | undefined;
62
61
  readonly binding: string;
63
62
  readonly derived?: {
64
63
  readonly mode: "formula" | "prefill";
65
64
  readonly expression: string;
66
65
  } | undefined;
66
+ readonly enableSorting?: boolean | undefined;
67
67
  readonly sortKey?: string | undefined;
68
68
  }) => any;
69
69
  }, string, import("vue").PublicProps, Readonly<__VLS_ModelProps> & Readonly<{
@@ -122,12 +122,12 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
122
122
  readonly message: string;
123
123
  }[]] | undefined;
124
124
  readonly readonly?: string | undefined;
125
- readonly enableSorting?: boolean | undefined;
126
125
  readonly binding: string;
127
126
  readonly derived?: {
128
127
  readonly mode: "formula" | "prefill";
129
128
  readonly expression: string;
130
129
  } | undefined;
130
+ readonly enableSorting?: boolean | undefined;
131
131
  readonly sortKey?: string | undefined;
132
132
  }) => any) | undefined;
133
133
  }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
@@ -19,6 +19,13 @@ import {
19
19
  InputGroupInput,
20
20
  InputGroupNumberField
21
21
  } from "../../../../ui/input-group";
22
+ import {
23
+ Select,
24
+ SelectContent,
25
+ SelectItem,
26
+ SelectTrigger,
27
+ SelectValue
28
+ } from "../../../../ui/select";
22
29
  import ActionsConfigEditor from "../../../../actions/config.vue";
23
30
  import { getStructFieldDescription, getStructFieldTitle } from "../../../utils/schema-meta";
24
31
  import { Markdown } from "../../../../ui/markdown";
@@ -92,6 +99,11 @@ const ROUNDING_MODE_OPTIONS = [
92
99
  { value: "floor", label: "\u5411\u4E0B\u53D6\u6574" },
93
100
  { value: "ceil", label: "\u5411\u4E0A\u53D6\u6574" }
94
101
  ];
102
+ const DISPLAY_MODE_OPTIONS = [
103
+ { value: "plain", label: "\u6570\u503C" },
104
+ { value: "uppercaseChinese", label: "\u4E2D\u6587\u5927\u5199" },
105
+ { value: "monoThousand", label: "\u7B49\u5BBD\u5B57\u4F53\u52A0\u5343\u5206\u4F4D" }
106
+ ];
95
107
  const bindingText = computed({
96
108
  get: () => value.value.binding ?? "",
97
109
  set: (v) => {
@@ -439,6 +451,38 @@ function onMaxChange(v) {
439
451
  />
440
452
  </div>
441
453
  </Field>
454
+ <Field orientation="vertical">
455
+ <FieldLabel class="text-xs text-zinc-500">
456
+ <template
457
+ v-if="fieldDescription('displayMode')"
458
+ #tooltip
459
+ >
460
+ <Markdown
461
+ :source="fieldDescription('displayMode')"
462
+ block
463
+ class="prose prose-sm prose-zinc"
464
+ />
465
+ </template>
466
+ {{ fieldTitle("displayMode") }}
467
+ </FieldLabel>
468
+ <Select
469
+ :model-value="value.displayMode ?? 'plain'"
470
+ @update:model-value="(v) => value = { ...value, displayMode: v }"
471
+ >
472
+ <SelectTrigger class="w-full">
473
+ <SelectValue />
474
+ </SelectTrigger>
475
+ <SelectContent>
476
+ <SelectItem
477
+ v-for="opt in DISPLAY_MODE_OPTIONS"
478
+ :key="opt.value"
479
+ :value="opt.value"
480
+ >
481
+ {{ opt.label }}
482
+ </SelectItem>
483
+ </SelectContent>
484
+ </Select>
485
+ </Field>
442
486
  </div>
443
487
  <div class="grid grid-cols-2 gap-x-6 gap-y-4">
444
488
  <Field orientation="vertical">
@@ -7,6 +7,7 @@ import { cel as _rawCel } from "../../../../../utils/cel";
7
7
  import { celScope, injectCELContext } from "../../../../../utils/cel-context";
8
8
  import { useFormReadonly } from "../../../../form/utils/readonly";
9
9
  import { getLocalizedText } from "../../../../../share/locale";
10
+ import { formatNumberDisplay } from "../../../../../share/number-format";
10
11
  import { InputGroup, InputGroupAddon, InputGroupButton, InputGroupNumberField } from "../../../../ui/input-group";
11
12
  import ShwfedActions from "../../../../actions/components/group.vue";
12
13
  import { useFieldValue } from "../../../../form/utils/field-value";
@@ -70,6 +71,11 @@ const { draft, commit } = useFieldValue({
70
71
  return props.column.valueAsString ? String(next) : next;
71
72
  }
72
73
  });
74
+ const readonlyDisplay = computed(() => formatNumberDisplay(draft.value, {
75
+ displayMode: props.column.displayMode,
76
+ precision: props.column.precision,
77
+ roundingMode: props.column.roundingMode
78
+ }));
73
79
  function applyRounding(n, precision, mode) {
74
80
  const factor = 10 ** precision;
75
81
  switch (mode) {
@@ -133,10 +139,10 @@ async function onBlur() {
133
139
  v-if="effectiveReadonly"
134
140
  :class="[
135
141
  'flex items-center h-7 w-full px-2 text-[0.75rem] truncate',
136
- draft !== void 0 ? ['text-zinc-700', justifyClass] : 'justify-center font-mono text-zinc-300 select-none'
142
+ draft !== void 0 ? ['text-zinc-700', justifyClass, column.displayMode === 'monoThousand' && 'font-mono'] : 'justify-center font-mono text-zinc-300 select-none'
137
143
  ]"
138
144
  >
139
- {{ draft ?? "-" }}
145
+ {{ readonlyDisplay }}
140
146
  </span>
141
147
  <InputGroup
142
148
  v-else
@@ -33,6 +33,9 @@ export declare function schema(configure: (env: Environment) => void): Schema.St
33
33
  valueAsString: Schema.optional<Schema.SchemaClass<boolean, boolean, never>>;
34
34
  min: Schema.optional<Schema.Schema<string, string, never>>;
35
35
  max: Schema.optional<Schema.Schema<string, string, never>>;
36
+ displayMode: Schema.optionalWith<Schema.Literal<["plain", "uppercaseChinese", "monoThousand"]>, {
37
+ default: () => "plain";
38
+ }>;
36
39
  derived: Schema.optional<Schema.Struct<{
37
40
  mode: Schema.Literal<["formula", "prefill"]>;
38
41
  expression: Schema.Schema<string, string, never>;
@@ -68,6 +68,13 @@ export function schema(configure) {
68
68
  title: "\u6700\u5927\u503C",
69
69
  description: "\u5141\u8BB8\u8F93\u5165\u7684\u6700\u5927\u503C\u8868\u8FBE\u5F0F\uFF0C\u53EF\u8BBF\u95EE `row` / `index` \u548C `form`\uFF1B\u7559\u7A7A\u65F6\u4E0D\u9650\u5236\u4E0A\u9650"
70
70
  })),
71
+ displayMode: Schema.optionalWith(
72
+ Schema.Literal("plain", "uppercaseChinese", "monoThousand").annotations({
73
+ title: "\u6A21\u5F0F",
74
+ description: "\u53EA\u8BFB\u5C55\u793A\u65F6\u7684\u6A21\u5F0F\uFF1A\u6570\u503C\uFF08\u539F\u6837\uFF09\u3001\u4E2D\u6587\u5927\u5199\uFF08\u5982 4200 \u2192 `\u8086\u4EDF\u8D30\u4F70\u96F6\u62FE`\uFF09\u3001\u7B49\u5BBD\u5B57\u4F53\u52A0\u5343\u5206\u4F4D\uFF08\u5982 `4,200`\uFF09\uFF1B\u7F16\u8F91\u6001\u4E0D\u53D7\u5F71\u54CD"
75
+ }),
76
+ { default: () => "plain" }
77
+ ),
71
78
  derived: derivedRowField(configure, "number"),
72
79
  // `Schema.optional` rebuilds the struct's union member, and because the
73
80
  // `optionalWith`-default fields make `AddonActions` a `Transformation`, the