niuma-ui 1.0.0

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 (220) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/LICENSE +202 -0
  3. package/NOTICE +25 -0
  4. package/README.en.md +99 -0
  5. package/README.md +161 -0
  6. package/package.json +106 -0
  7. package/src/__tests__/RsBadge.spec.ts +40 -0
  8. package/src/__tests__/RsBreadcrumb.spec.ts +172 -0
  9. package/src/__tests__/RsButton.spec.ts +108 -0
  10. package/src/__tests__/RsCalendarGrid.spec.ts +82 -0
  11. package/src/__tests__/RsCard.spec.ts +97 -0
  12. package/src/__tests__/RsCheckbox.spec.ts +36 -0
  13. package/src/__tests__/RsCodeEditor.spec.ts +111 -0
  14. package/src/__tests__/RsConfirmDialog.spec.ts +158 -0
  15. package/src/__tests__/RsContainer.spec.ts +89 -0
  16. package/src/__tests__/RsContextMenu.spec.ts +118 -0
  17. package/src/__tests__/RsDatePicker.spec.ts +88 -0
  18. package/src/__tests__/RsDateTimePicker.spec.ts +69 -0
  19. package/src/__tests__/RsDialog.spec.ts +404 -0
  20. package/src/__tests__/RsDrawer.spec.ts +145 -0
  21. package/src/__tests__/RsDropdown.spec.ts +135 -0
  22. package/src/__tests__/RsEmpty.spec.ts +99 -0
  23. package/src/__tests__/RsForm.spec.ts +173 -0
  24. package/src/__tests__/RsIcon.spec.ts +244 -0
  25. package/src/__tests__/RsInput.spec.ts +269 -0
  26. package/src/__tests__/RsInputNumber.spec.ts +118 -0
  27. package/src/__tests__/RsLabel.spec.ts +106 -0
  28. package/src/__tests__/RsLink.spec.ts +49 -0
  29. package/src/__tests__/RsLoading.spec.ts +84 -0
  30. package/src/__tests__/RsMarkdown.spec.ts +143 -0
  31. package/src/__tests__/RsMenu.spec.ts +119 -0
  32. package/src/__tests__/RsNewComponents.spec.ts +17 -0
  33. package/src/__tests__/RsPagination.spec.ts +158 -0
  34. package/src/__tests__/RsPopover.spec.ts +126 -0
  35. package/src/__tests__/RsScrollbar.spec.ts +53 -0
  36. package/src/__tests__/RsSelect.spec.ts +291 -0
  37. package/src/__tests__/RsSidebar.spec.ts +119 -0
  38. package/src/__tests__/RsSplitPane.spec.ts +177 -0
  39. package/src/__tests__/RsStatCard.spec.ts +79 -0
  40. package/src/__tests__/RsSteps.spec.ts +125 -0
  41. package/src/__tests__/RsTable.perf.spec.ts +103 -0
  42. package/src/__tests__/RsTable.spec.ts +1135 -0
  43. package/src/__tests__/RsTabs.spec.ts +328 -0
  44. package/src/__tests__/RsTerminal.spec.ts +218 -0
  45. package/src/__tests__/RsTimePicker.spec.ts +77 -0
  46. package/src/__tests__/RsToaster.spec.ts +95 -0
  47. package/src/__tests__/RsToolbar.spec.ts +75 -0
  48. package/src/__tests__/RsTooltip.spec.ts +111 -0
  49. package/src/__tests__/RsTree.spec.ts +572 -0
  50. package/src/__tests__/RsUpload.spec.ts +160 -0
  51. package/src/__tests__/RsVirtualList.spec.ts +77 -0
  52. package/src/__tests__/date-picker-utils.spec.ts +70 -0
  53. package/src/__tests__/dialog-viewport.spec.ts +38 -0
  54. package/src/__tests__/iso-local-datetime.spec.ts +58 -0
  55. package/src/__tests__/rs-clipboard.spec.ts +142 -0
  56. package/src/__tests__/setup.ts +12 -0
  57. package/src/__tests__/split-pane-utils.spec.ts +136 -0
  58. package/src/__tests__/table-drag.spec.ts +35 -0
  59. package/src/__tests__/table-edit-utils.spec.ts +194 -0
  60. package/src/__tests__/table-utils.spec.ts +286 -0
  61. package/src/__tests__/theme.spec.ts +22 -0
  62. package/src/__tests__/tree-utils.spec.ts +234 -0
  63. package/src/__tests__/useTableCellTooltip.spec.ts +101 -0
  64. package/src/components/RsAvatar.vue +115 -0
  65. package/src/components/RsBadge.vue +59 -0
  66. package/src/components/RsBreadcrumb.vue +65 -0
  67. package/src/components/RsBreadcrumbItems.vue +36 -0
  68. package/src/components/RsButton.vue +393 -0
  69. package/src/components/RsCalendarGrid.vue +284 -0
  70. package/src/components/RsCard.vue +237 -0
  71. package/src/components/RsCheckbox.vue +189 -0
  72. package/src/components/RsCodeBlock.vue +278 -0
  73. package/src/components/RsCodeEditor.vue +597 -0
  74. package/src/components/RsConfigProvider.vue +92 -0
  75. package/src/components/RsConfirmDialog.vue +178 -0
  76. package/src/components/RsContainer.vue +235 -0
  77. package/src/components/RsContextMenu.vue +238 -0
  78. package/src/components/RsContextMenuItems.vue +77 -0
  79. package/src/components/RsDatePicker.vue +756 -0
  80. package/src/components/RsDateTimePicker.vue +42 -0
  81. package/src/components/RsDialog.vue +486 -0
  82. package/src/components/RsDrawer.vue +175 -0
  83. package/src/components/RsDropdown.vue +252 -0
  84. package/src/components/RsDropdownItems.vue +90 -0
  85. package/src/components/RsEmpty.vue +107 -0
  86. package/src/components/RsForm.vue +131 -0
  87. package/src/components/RsIcon.vue +104 -0
  88. package/src/components/RsInput.vue +1101 -0
  89. package/src/components/RsInputNumber.vue +532 -0
  90. package/src/components/RsLabel.vue +54 -0
  91. package/src/components/RsLink.vue +106 -0
  92. package/src/components/RsLoading.vue +171 -0
  93. package/src/components/RsMarkdown.vue +329 -0
  94. package/src/components/RsMenu.vue +256 -0
  95. package/src/components/RsMenuItems.vue +125 -0
  96. package/src/components/RsMonacoEditor.vue +541 -0
  97. package/src/components/RsPagination.vue +184 -0
  98. package/src/components/RsPopover.vue +77 -0
  99. package/src/components/RsProseEditor.vue +160 -0
  100. package/src/components/RsScrollbar.vue +171 -0
  101. package/src/components/RsSelect.vue +1045 -0
  102. package/src/components/RsSidebar.vue +121 -0
  103. package/src/components/RsSidebarGroup.vue +32 -0
  104. package/src/components/RsSidebarItem.vue +72 -0
  105. package/src/components/RsSplitPane.vue +619 -0
  106. package/src/components/RsStatCard.vue +85 -0
  107. package/src/components/RsSteps.vue +138 -0
  108. package/src/components/RsTable.vue +2664 -0
  109. package/src/components/RsTableColgroup.vue +17 -0
  110. package/src/components/RsTableHeaderRow.vue +30 -0
  111. package/src/components/RsTabs.vue +951 -0
  112. package/src/components/RsTerminal.vue +697 -0
  113. package/src/components/RsTimePicker.vue +554 -0
  114. package/src/components/RsTimePickerColumns.vue +226 -0
  115. package/src/components/RsToaster.vue +396 -0
  116. package/src/components/RsToolbar.vue +135 -0
  117. package/src/components/RsTooltip.vue +142 -0
  118. package/src/components/RsTooltipProvider.vue +20 -0
  119. package/src/components/RsTree.vue +1248 -0
  120. package/src/components/RsUpload.vue +279 -0
  121. package/src/components/RsVirtualList.vue +217 -0
  122. package/src/components/avatar-utils.ts +19 -0
  123. package/src/components/breadcrumb-utils.ts +19 -0
  124. package/src/components/class-utils.ts +29 -0
  125. package/src/components/code-editor-utils.ts +106 -0
  126. package/src/components/code-mirror-completion.ts +40 -0
  127. package/src/components/code-mirror-diagnostics.ts +52 -0
  128. package/src/components/code-mirror-ghost.ts +158 -0
  129. package/src/components/code-mirror-inline-edit.ts +55 -0
  130. package/src/components/code-mirror-intel.ts +81 -0
  131. package/src/components/code-mirror-lang.ts +128 -0
  132. package/src/components/context-menu-utils.ts +20 -0
  133. package/src/components/date-picker-utils.ts +284 -0
  134. package/src/components/date-range-validation.ts +29 -0
  135. package/src/components/date-validation.ts +38 -0
  136. package/src/components/dialog-viewport.ts +48 -0
  137. package/src/components/dialog-window.ts +253 -0
  138. package/src/components/dropdown-utils.ts +31 -0
  139. package/src/components/form-utils.ts +77 -0
  140. package/src/components/input-number-utils.ts +128 -0
  141. package/src/components/input-rules.ts +84 -0
  142. package/src/components/loading-utils.ts +8 -0
  143. package/src/components/markdown-utils.ts +126 -0
  144. package/src/components/menu-utils.ts +48 -0
  145. package/src/components/overlay-utils.ts +47 -0
  146. package/src/components/pagination-utils.ts +38 -0
  147. package/src/components/popover-utils.ts +8 -0
  148. package/src/components/reka.ts +106 -0
  149. package/src/components/resolve-radius.ts +22 -0
  150. package/src/components/resolve-size.ts +29 -0
  151. package/src/components/scrollbar-utils.ts +10 -0
  152. package/src/components/select-utils.ts +72 -0
  153. package/src/components/split-pane-utils.ts +187 -0
  154. package/src/components/steps-utils.ts +22 -0
  155. package/src/components/table/RsTableBodyRow.vue +287 -0
  156. package/src/components/table/RsTableCell.vue +239 -0
  157. package/src/components/table/RsTableCellContent.ts +18 -0
  158. package/src/components/table/RsTableCellEditor.vue +351 -0
  159. package/src/components/table/RsTableEditGutter.vue +54 -0
  160. package/src/components/table/RsTableHeaderFilter.vue +107 -0
  161. package/src/components/table/RsTableRowStatus.vue +69 -0
  162. package/src/components/table/rs-table.css +1141 -0
  163. package/src/components/table/table-context-menu.ts +53 -0
  164. package/src/components/table/table-edit-utils.ts +496 -0
  165. package/src/components/table/table-keys.ts +12 -0
  166. package/src/components/table-drag.ts +215 -0
  167. package/src/components/table-utils.ts +950 -0
  168. package/src/components/tabs-utils.ts +107 -0
  169. package/src/components/terminal-utils.ts +301 -0
  170. package/src/components/terminal-wheel.ts +49 -0
  171. package/src/components/time-picker-utils.ts +167 -0
  172. package/src/components/time-range-validation.ts +23 -0
  173. package/src/components/time-validation.ts +20 -0
  174. package/src/components/tree-utils.ts +518 -0
  175. package/src/components/upload-utils.ts +55 -0
  176. package/src/components/virtual-list-utils.ts +17 -0
  177. package/src/composables/useClickOutside.ts +22 -0
  178. package/src/composables/useRsConfig.ts +91 -0
  179. package/src/composables/useRsI18n.ts +22 -0
  180. package/src/composables/useRsTabsNav.ts +187 -0
  181. package/src/composables/useRsToast.ts +48 -0
  182. package/src/composables/useTableCellTooltip.ts +239 -0
  183. package/src/composables/useTableEdit.ts +271 -0
  184. package/src/composables/useTableRowHighlight.ts +50 -0
  185. package/src/dev/vite-codemirror-deps.ts +20 -0
  186. package/src/icons/custom/api.ts +54 -0
  187. package/src/icons/custom/clickhouse.ts +52 -0
  188. package/src/icons/custom/dameng.ts +83 -0
  189. package/src/icons/custom/ftp.ts +61 -0
  190. package/src/icons/custom/kingbase.ts +52 -0
  191. package/src/icons/custom/mongodb.ts +50 -0
  192. package/src/icons/custom/mysql.ts +51 -0
  193. package/src/icons/custom/oracle.ts +52 -0
  194. package/src/icons/custom/redis.ts +51 -0
  195. package/src/icons/custom/sqlite.ts +50 -0
  196. package/src/icons/custom/sqlserver.ts +52 -0
  197. package/src/icons/custom/vastbase.ts +57 -0
  198. package/src/icons/lucide.ts +78 -0
  199. package/src/icons/registry.ts +35 -0
  200. package/src/index.ts +425 -0
  201. package/src/lib/iso-local-datetime.ts +152 -0
  202. package/src/lib/rs-dayjs.ts +56 -0
  203. package/src/locale/messages.ts +362 -0
  204. package/src/locale/types.ts +5 -0
  205. package/src/monaco/debug-decorations.css +20 -0
  206. package/src/monaco/debug-decorations.ts +70 -0
  207. package/src/monaco/index.ts +22 -0
  208. package/src/monaco/languages/index.ts +21 -0
  209. package/src/monaco/languages/mongodb-shell.ts +125 -0
  210. package/src/monaco/languages/types.ts +55 -0
  211. package/src/monaco/setup.ts +101 -0
  212. package/src/styles.css +1040 -0
  213. package/src/theme/apply.ts +12 -0
  214. package/src/theme/brand.example.css +37 -0
  215. package/src/theme/presets.ts +69 -0
  216. package/src/theme/types.ts +81 -0
  217. package/src/utils/rs-clipboard.ts +272 -0
  218. package/src/vite-env.d.ts +7 -0
  219. package/vite-plugins/monaco-zh-nls.ts +101 -0
  220. package/vite-plugins/silence-antlr-parse-console.ts +29 -0
@@ -0,0 +1,271 @@
1
+ import { shallowRef, ref, type Ref } from 'vue'
2
+ import { makeCellKey } from '../components/table/table-keys'
3
+
4
+ export interface RsTableEditingCell {
5
+ rowKey: string
6
+ colKey: string
7
+ rowIndex: number
8
+ }
9
+
10
+ export interface RsTableStagedCell {
11
+ rowKey: string
12
+ colKey: string
13
+ rowIndex: number
14
+ draft: string
15
+ original: unknown
16
+ }
17
+
18
+ export interface RsTableFocusCell {
19
+ rowKey: string
20
+ colKey: string
21
+ rowIndex: number
22
+ }
23
+
24
+ export interface RsTableUndoEntry {
25
+ items: Array<{
26
+ rowKey: string
27
+ colKey: string
28
+ rowIndex: number
29
+ previous: unknown
30
+ next: unknown
31
+ }>
32
+ }
33
+
34
+ export function useTableEdit(options: {
35
+ enabled: () => boolean
36
+ undoLimit?: () => number
37
+ }): {
38
+ editingCell: Ref<RsTableEditingCell | null>
39
+ editingDraft: Ref<string>
40
+ focusCell: Ref<RsTableFocusCell | null>
41
+ stagedMap: Ref<Map<string, RsTableStagedCell>>
42
+ errorMap: Ref<Map<string, string>>
43
+ validatingMap: Ref<Map<string, boolean>>
44
+ undoStack: Ref<RsTableUndoEntry[]>
45
+ redoStack: Ref<RsTableUndoEntry[]>
46
+ isEditing: (rowKey: string, colKey: string) => boolean
47
+ isFocused: (rowKey: string, colKey: string) => boolean
48
+ getDraft: (rowKey: string, colKey: string) => string | undefined
49
+ isDirty: (rowKey: string, colKey: string) => boolean
50
+ isRowDirty: (rowKey: string) => boolean
51
+ getCellError: (rowKey: string, colKey: string) => string | undefined
52
+ setCellError: (rowKey: string, colKey: string, message: string | null) => void
53
+ clearCellError: (rowKey: string, colKey: string) => void
54
+ isValidating: (rowKey: string, colKey: string) => boolean
55
+ setValidating: (rowKey: string, colKey: string, value: boolean) => void
56
+ getRowStagedCells: (rowKey: string) => RsTableStagedCell[]
57
+ startEdit: (cell: RsTableEditingCell, initialText: string) => void
58
+ updateDraft: (text: string) => void
59
+ cancelEdit: () => void
60
+ cancelAll: () => void
61
+ setFocusCell: (cell: RsTableFocusCell | null) => void
62
+ stageCell: (cell: RsTableStagedCell) => void
63
+ unstageCell: (rowKey: string, colKey: string) => void
64
+ rollbackRow: (rowKey: string) => void
65
+ commitRow: (rowKey: string) => RsTableStagedCell[]
66
+ pushUndo: (entry: RsTableUndoEntry | RsTableUndoEntry['items'][number]) => void
67
+ undo: () => RsTableUndoEntry | null
68
+ redo: () => RsTableUndoEntry | null
69
+ } {
70
+ const editingCell = ref<RsTableEditingCell | null>(null)
71
+ const editingDraft = ref('')
72
+ const focusCell = ref<RsTableFocusCell | null>(null)
73
+ const stagedMap = shallowRef(new Map<string, RsTableStagedCell>())
74
+ const errorMap = shallowRef(new Map<string, string>())
75
+ const validatingMap = shallowRef(new Map<string, boolean>())
76
+ const undoStack = shallowRef<RsTableUndoEntry[]>([])
77
+ const redoStack = shallowRef<RsTableUndoEntry[]>([])
78
+
79
+ function isEditing(rowKey: string, colKey: string): boolean {
80
+ const active = editingCell.value
81
+ return active?.rowKey === rowKey && active.colKey === colKey
82
+ }
83
+
84
+ function isFocused(rowKey: string, colKey: string): boolean {
85
+ const active = focusCell.value
86
+ return active?.rowKey === rowKey && active.colKey === colKey
87
+ }
88
+
89
+ function getDraft(rowKey: string, colKey: string): string | undefined {
90
+ const staged = stagedMap.value.get(makeCellKey(rowKey, colKey))
91
+ if (staged) return staged.draft
92
+ if (isEditing(rowKey, colKey)) return editingDraft.value
93
+ return undefined
94
+ }
95
+
96
+ function isDirty(rowKey: string, colKey: string): boolean {
97
+ return stagedMap.value.has(makeCellKey(rowKey, colKey))
98
+ }
99
+
100
+ function getRowStagedCells(rowKey: string): RsTableStagedCell[] {
101
+ return [...stagedMap.value.values()].filter((item) => item.rowKey === rowKey)
102
+ }
103
+
104
+ function isRowDirty(rowKey: string): boolean {
105
+ return getRowStagedCells(rowKey).length > 0
106
+ }
107
+
108
+ function getCellError(rowKey: string, colKey: string): string | undefined {
109
+ return errorMap.value.get(makeCellKey(rowKey, colKey))
110
+ }
111
+
112
+ function setCellError(rowKey: string, colKey: string, message: string | null): void {
113
+ const key = makeCellKey(rowKey, colKey)
114
+ const next = new Map(errorMap.value)
115
+ if (!message) next.delete(key)
116
+ else next.set(key, message)
117
+ errorMap.value = next
118
+ }
119
+
120
+ function clearCellError(rowKey: string, colKey: string): void {
121
+ setCellError(rowKey, colKey, null)
122
+ }
123
+
124
+ function isValidating(rowKey: string, colKey: string): boolean {
125
+ return validatingMap.value.get(makeCellKey(rowKey, colKey)) === true
126
+ }
127
+
128
+ function setValidating(rowKey: string, colKey: string, value: boolean): void {
129
+ const key = makeCellKey(rowKey, colKey)
130
+ const next = new Map(validatingMap.value)
131
+ if (!value) next.delete(key)
132
+ else next.set(key, true)
133
+ validatingMap.value = next
134
+ }
135
+
136
+ function startEdit(cell: RsTableEditingCell, initialText: string): void {
137
+ if (!options.enabled()) return
138
+ editingCell.value = cell
139
+ focusCell.value = cell
140
+ const staged = stagedMap.value.get(makeCellKey(cell.rowKey, cell.colKey))
141
+ editingDraft.value = staged?.draft ?? initialText
142
+ clearCellError(cell.rowKey, cell.colKey)
143
+ }
144
+
145
+ function updateDraft(text: string): void {
146
+ if (!editingCell.value) return
147
+ editingDraft.value = text
148
+ }
149
+
150
+ function cancelEdit(): void {
151
+ editingCell.value = null
152
+ editingDraft.value = ''
153
+ }
154
+
155
+ function cancelAll(): void {
156
+ editingCell.value = null
157
+ editingDraft.value = ''
158
+ stagedMap.value = new Map()
159
+ errorMap.value = new Map()
160
+ validatingMap.value = new Map()
161
+ }
162
+
163
+ function setFocusCell(cell: RsTableFocusCell | null): void {
164
+ focusCell.value = cell
165
+ }
166
+
167
+ function stageCell(cell: RsTableStagedCell): void {
168
+ const key = makeCellKey(cell.rowKey, cell.colKey)
169
+ const next = new Map(stagedMap.value)
170
+ next.set(key, cell)
171
+ stagedMap.value = next
172
+ clearCellError(cell.rowKey, cell.colKey)
173
+ if (editingCell.value?.rowKey === cell.rowKey && editingCell.value.colKey === cell.colKey) {
174
+ editingCell.value = null
175
+ editingDraft.value = ''
176
+ }
177
+ }
178
+
179
+ function removeStagedKeys(keys: string[]): void {
180
+ if (!keys.length) return
181
+ const next = new Map(stagedMap.value)
182
+ for (const key of keys) next.delete(key)
183
+ stagedMap.value = next
184
+ }
185
+
186
+ function unstageCell(rowKey: string, colKey: string): void {
187
+ removeStagedKeys([makeCellKey(rowKey, colKey)])
188
+ }
189
+
190
+ function rollbackRow(rowKey: string): void {
191
+ const keys = [...stagedMap.value.keys()].filter((key) => key.startsWith(`${rowKey}:`))
192
+ removeStagedKeys(keys)
193
+ const errNext = new Map(errorMap.value)
194
+ for (const key of [...errNext.keys()]) {
195
+ if (key.startsWith(`${rowKey}:`)) errNext.delete(key)
196
+ }
197
+ errorMap.value = errNext
198
+ if (editingCell.value?.rowKey === rowKey) cancelEdit()
199
+ }
200
+
201
+ function commitRow(rowKey: string): RsTableStagedCell[] {
202
+ const changes = getRowStagedCells(rowKey)
203
+ rollbackRow(rowKey)
204
+ return changes
205
+ }
206
+
207
+ function normalizeUndo(
208
+ entry: RsTableUndoEntry | RsTableUndoEntry['items'][number],
209
+ ): RsTableUndoEntry {
210
+ if ('items' in entry) return entry
211
+ return { items: [entry] }
212
+ }
213
+
214
+ function pushUndo(entry: RsTableUndoEntry | RsTableUndoEntry['items'][number]): void {
215
+ const limit = options.undoLimit?.() ?? 50
216
+ undoStack.value = [...undoStack.value, normalizeUndo(entry)].slice(-Math.max(1, limit))
217
+ redoStack.value = []
218
+ }
219
+
220
+ function undo(): RsTableUndoEntry | null {
221
+ const stack = undoStack.value
222
+ if (!stack.length) return null
223
+ const entry = stack[stack.length - 1]!
224
+ undoStack.value = stack.slice(0, -1)
225
+ redoStack.value = [...redoStack.value, entry]
226
+ return entry
227
+ }
228
+
229
+ function redo(): RsTableUndoEntry | null {
230
+ const stack = redoStack.value
231
+ if (!stack.length) return null
232
+ const entry = stack[stack.length - 1]!
233
+ redoStack.value = stack.slice(0, -1)
234
+ undoStack.value = [...undoStack.value, entry]
235
+ return entry
236
+ }
237
+
238
+ return {
239
+ editingCell,
240
+ editingDraft,
241
+ focusCell,
242
+ stagedMap,
243
+ errorMap,
244
+ validatingMap,
245
+ undoStack,
246
+ redoStack,
247
+ isEditing,
248
+ isFocused,
249
+ getDraft,
250
+ isDirty,
251
+ isRowDirty,
252
+ getCellError,
253
+ setCellError,
254
+ clearCellError,
255
+ isValidating,
256
+ setValidating,
257
+ getRowStagedCells,
258
+ startEdit,
259
+ updateDraft,
260
+ cancelEdit,
261
+ cancelAll,
262
+ setFocusCell,
263
+ stageCell,
264
+ unstageCell,
265
+ rollbackRow,
266
+ commitRow,
267
+ pushUndo,
268
+ undo,
269
+ redo,
270
+ }
271
+ }
@@ -0,0 +1,50 @@
1
+ import { computed, ref, type ComputedRef, type Ref } from 'vue'
2
+
3
+ export function useTableRowHighlight(options: {
4
+ enabled: () => boolean
5
+ highlightRowOnClick: () => boolean
6
+ isControlled: () => boolean
7
+ highlightedRowKey: () => string | undefined
8
+ defaultHighlightedRowKey: () => string | undefined
9
+ onUpdate: (value: string | undefined) => void
10
+ }): {
11
+ highlightedKey: ComputedRef<string | undefined>
12
+ setHighlightedKey: (value: string | undefined) => void
13
+ isHighlighted: (rowKey: string) => boolean
14
+ applyRowClickHighlight: (rowKey: string) => void
15
+ } {
16
+ const internalHighlightedKey = ref<string | undefined>(options.defaultHighlightedRowKey())
17
+
18
+ const highlightedKey = computed({
19
+ get: () => (options.isControlled() ? options.highlightedRowKey() : internalHighlightedKey.value),
20
+ set: (value: string | undefined) => {
21
+ if (options.isControlled()) {
22
+ options.onUpdate(value)
23
+ return
24
+ }
25
+ internalHighlightedKey.value = value
26
+ options.onUpdate(value)
27
+ },
28
+ })
29
+
30
+ function setHighlightedKey(value: string | undefined): void {
31
+ highlightedKey.value = value
32
+ }
33
+
34
+ function isHighlighted(rowKey: string): boolean {
35
+ if (!options.enabled()) return false
36
+ return highlightedKey.value === rowKey
37
+ }
38
+
39
+ function applyRowClickHighlight(rowKey: string): void {
40
+ if (!options.enabled() || !options.highlightRowOnClick()) return
41
+ setHighlightedKey(rowKey)
42
+ }
43
+
44
+ return {
45
+ highlightedKey,
46
+ setHighlightedKey,
47
+ isHighlighted,
48
+ applyRowClickHighlight,
49
+ }
50
+ }
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Vite optimizeDeps 扫描入口:在 dev server 启动时预构建全部 CodeMirror 语言包,
3
+ * 避免辅助窗口动态 import 命中过期 hash 导致 504 (Outdated Optimize Dep)。
4
+ */
5
+ import 'codemirror'
6
+ import '@codemirror/lang-cpp'
7
+ import '@codemirror/lang-css'
8
+ import '@codemirror/lang-go'
9
+ import '@codemirror/lang-html'
10
+ import '@codemirror/lang-java'
11
+ import '@codemirror/lang-javascript'
12
+ import '@codemirror/lang-json'
13
+ import '@codemirror/lang-markdown'
14
+ import '@codemirror/lang-python'
15
+ import '@codemirror/lang-rust'
16
+ import '@codemirror/lang-sql'
17
+ import '@codemirror/lang-xml'
18
+ import '@codemirror/lang-yaml'
19
+ import '@codemirror/language'
20
+ import '@codemirror/legacy-modes/mode/shell'
@@ -0,0 +1,54 @@
1
+ import { defineComponent, h, type PropType } from 'vue'
2
+
3
+ /**
4
+ * Activity Bar「API」字标 — 粗圆角字重,随 currentColor 着色。
5
+ */
6
+ export const ApiIcon = defineComponent({
7
+ name: 'ApiIcon',
8
+ inheritAttrs: false,
9
+ props: {
10
+ size: { type: [Number, String] as PropType<number | string>, default: 24 },
11
+ strokeWidth: { type: [Number, String] as PropType<number | string>, default: 2 },
12
+ color: { type: String, default: 'currentColor' },
13
+ },
14
+ setup(props, { attrs }) {
15
+ return () => {
16
+ const size = Number(props.size) || 24
17
+ const { class: attrClass, style: attrStyle, ...restAttrs } = attrs
18
+ const style: Record<string, string | number> = {
19
+ ...(typeof attrStyle === 'object' && attrStyle && !Array.isArray(attrStyle)
20
+ ? (attrStyle as Record<string, string | number>)
21
+ : {}),
22
+ color: props.color || 'currentColor',
23
+ }
24
+
25
+ return h(
26
+ 'svg',
27
+ {
28
+ ...restAttrs,
29
+ xmlns: 'http://www.w3.org/2000/svg',
30
+ width: size,
31
+ height: size,
32
+ viewBox: '0 0 24 24',
33
+ fill: 'none',
34
+ overflow: 'visible',
35
+ style,
36
+ class: ['lucide', 'lucide-api-icon', attrClass].filter(Boolean),
37
+ },
38
+ [
39
+ h(
40
+ 'text',
41
+ {
42
+ class: 'api-icon__label',
43
+ x: 12,
44
+ y: 12,
45
+ textAnchor: 'middle',
46
+ dy: '0.35em',
47
+ },
48
+ 'API',
49
+ ),
50
+ ],
51
+ )
52
+ }
53
+ },
54
+ })
@@ -0,0 +1,52 @@
1
+ import { defineComponent, h, type PropType } from 'vue'
2
+
3
+ /**
4
+ * ClickHouse 官方品牌 mark(竖条 barcode 形,不含 ClickHouse 字样)。
5
+ * 来自 Simple Icons clickhouse.svg(CC0 1.0),已归一到 24×24。
6
+ * 来源:https://github.com/simple-icons/simple-icons/blob/develop/icons/clickhouse.svg
7
+ * 品牌色:ClickHouse 黄 #FFCC01。
8
+ */
9
+ const CLICKHOUSE_MARK_PATH =
10
+ 'M21.333 10H24v4h-2.667ZM16 1.335h2.667v21.33H16Zm-5.333 0h2.666v21.33h-2.666ZM0 22.665V1.335h2.667v21.33zm5.333-21.33H8v21.33H5.333Z'
11
+
12
+ /**
13
+ * NiuMa ClickHouse —— 官方品牌 mark,单色填充,默认走 ClickHouse 黄并随主题明暗自动调整对比度。
14
+ */
15
+ export const ClickhouseIcon = defineComponent({
16
+ name: 'ClickhouseIcon',
17
+ inheritAttrs: false,
18
+ props: {
19
+ size: { type: [Number, String] as PropType<number | string>, default: 24 },
20
+ strokeWidth: { type: [Number, String] as PropType<number | string>, default: 2 },
21
+ color: { type: String, default: 'currentColor' },
22
+ },
23
+ setup(props, { attrs }) {
24
+ return () => {
25
+ const size = Number(props.size) || 24
26
+ const { class: attrClass, style: attrStyle, ...restAttrs } = attrs
27
+ const accent = props.color && props.color !== 'currentColor' ? props.color : undefined
28
+ const style: Record<string, string> = {
29
+ ...(typeof attrStyle === 'object' && attrStyle && !Array.isArray(attrStyle)
30
+ ? (attrStyle as Record<string, string>)
31
+ : {}),
32
+ ...(accent ? { '--rs-icon-clickhouse-accent': accent } : {}),
33
+ }
34
+
35
+ return h(
36
+ 'svg',
37
+ {
38
+ ...restAttrs,
39
+ xmlns: 'http://www.w3.org/2000/svg',
40
+ width: size,
41
+ height: size,
42
+ viewBox: '0 0 24 24',
43
+ fill: 'none',
44
+ overflow: 'visible',
45
+ style: Object.keys(style).length > 0 ? style : undefined,
46
+ class: ['lucide', 'lucide-clickhouse-icon', attrClass].filter(Boolean),
47
+ },
48
+ [h('path', { class: 'clickhouse-icon__mark', d: CLICKHOUSE_MARK_PATH })],
49
+ )
50
+ }
51
+ },
52
+ })
@@ -0,0 +1,83 @@
1
+ import { defineComponent, h, useId, type PropType } from 'vue'
2
+
3
+ /**
4
+ * 达梦官方品牌 mark:倾斜蓝椭圆 + 三条红色波浪带(不含「达梦数据库」字样)。
5
+ * 按官网 header logo 左侧图形归一到 24×24。
6
+ * 来源:https://www.dameng.com/static/cn/images/dm_cn/logo.png
7
+ * 品牌色取样:蓝 #0000D2、红 #EC1B34。
8
+ */
9
+
10
+ /** 椭圆内三条平行 S 形波浪带(局部坐标:中心 0,0,长轴水平) */
11
+ const DAMENG_WAVE_PATHS = [
12
+ 'M -10.2 -2.7 C -6.5 -4.2 -3.5 -1.4 0 -2.4 C 3.5 -3.4 6.5 -1 10.2 -2.3 L 10.2 -0.9 C 6.5 0.4 3.5 -2 0 -1 C -3.5 0 -6.5 -2.8 -10.2 -1.3 Z',
13
+ 'M -10.2 -0.4 C -6.5 -1.9 -3.5 0.9 0 -0.1 C 3.5 -1.1 6.5 1.3 10.2 0 L 10.2 1.4 C 6.5 2.7 3.5 0.3 0 1.3 C -3.5 2.3 -6.5 -0.5 -10.2 1 Z',
14
+ 'M -10.2 1.9 C -6.5 0.4 -3.5 3.2 0 2.2 C 3.5 1.2 6.5 3.6 10.2 2.3 L 10.2 3.7 C 6.5 5 3.5 2.6 0 3.6 C -3.5 4.6 -6.5 1.8 -10.2 3.3 Z',
15
+ ] as const
16
+
17
+ /**
18
+ * NiuMa Dameng —— 官方品牌 mark,双色填充,默认走官网蓝/红并随主题明暗调整。
19
+ */
20
+ export const DamengIcon = defineComponent({
21
+ name: 'DamengIcon',
22
+ inheritAttrs: false,
23
+ props: {
24
+ size: { type: [Number, String] as PropType<number | string>, default: 24 },
25
+ strokeWidth: { type: [Number, String] as PropType<number | string>, default: 2 },
26
+ color: { type: String, default: 'currentColor' },
27
+ },
28
+ setup(props, { attrs }) {
29
+ const clipId = useId()
30
+
31
+ return () => {
32
+ const size = Number(props.size) || 24
33
+ const { class: attrClass, style: attrStyle, ...restAttrs } = attrs
34
+ const accent = props.color && props.color !== 'currentColor' ? props.color : undefined
35
+ const style: Record<string, string> = {
36
+ ...(typeof attrStyle === 'object' && attrStyle && !Array.isArray(attrStyle)
37
+ ? (attrStyle as Record<string, string>)
38
+ : {}),
39
+ ...(accent ? { '--rs-icon-dameng-accent': accent } : {}),
40
+ }
41
+
42
+ return h(
43
+ 'svg',
44
+ {
45
+ ...restAttrs,
46
+ xmlns: 'http://www.w3.org/2000/svg',
47
+ width: size,
48
+ height: size,
49
+ viewBox: '0 0 24 24',
50
+ fill: 'none',
51
+ overflow: 'visible',
52
+ style: Object.keys(style).length > 0 ? style : undefined,
53
+ class: ['lucide', 'lucide-dameng-icon', attrClass].filter(Boolean),
54
+ },
55
+ [
56
+ h('defs', [
57
+ h('clipPath', { id: clipId }, [
58
+ h('ellipse', { cx: 0, cy: 0, rx: 10.2, ry: 6.55 }),
59
+ ]),
60
+ ]),
61
+ h(
62
+ 'g',
63
+ { transform: 'translate(12 12) rotate(-42)' },
64
+ [
65
+ h('ellipse', {
66
+ class: 'dameng-icon__oval',
67
+ cx: 0,
68
+ cy: 0,
69
+ rx: 10.2,
70
+ ry: 6.55,
71
+ }),
72
+ h(
73
+ 'g',
74
+ { class: 'dameng-icon__waves', 'clip-path': `url(#${clipId})` },
75
+ DAMENG_WAVE_PATHS.map((d) => h('path', { class: 'dameng-icon__wave', d })),
76
+ ),
77
+ ],
78
+ ),
79
+ ],
80
+ )
81
+ }
82
+ },
83
+ })
@@ -0,0 +1,61 @@
1
+ import { defineComponent, h, type PropType } from 'vue'
2
+
3
+ /** Lucide folder 轮廓 */
4
+ const FOLDER_PATH =
5
+ 'M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z'
6
+
7
+ /**
8
+ * NiuMa FTP — 橙色实心文件夹 + 居中白色「FTP」,避免轮廓与色块半覆盖。
9
+ */
10
+ export const FtpIcon = defineComponent({
11
+ name: 'FtpIcon',
12
+ inheritAttrs: false,
13
+ props: {
14
+ size: { type: [Number, String] as PropType<number | string>, default: 24 },
15
+ strokeWidth: { type: [Number, String] as PropType<number | string>, default: 2 },
16
+ color: { type: String, default: 'currentColor' },
17
+ },
18
+ setup(props, { attrs }) {
19
+ return () => {
20
+ const size = Number(props.size) || 24
21
+ const { class: attrClass, style: attrStyle, ...restAttrs } = attrs
22
+ const accent =
23
+ props.color && props.color !== 'currentColor' ? props.color : undefined
24
+ const style: Record<string, string> = {
25
+ ...(typeof attrStyle === 'object' && attrStyle && !Array.isArray(attrStyle)
26
+ ? (attrStyle as Record<string, string>)
27
+ : {}),
28
+ ...(accent ? { '--rs-icon-ftp-accent': accent } : {}),
29
+ }
30
+
31
+ return h(
32
+ 'svg',
33
+ {
34
+ ...restAttrs,
35
+ xmlns: 'http://www.w3.org/2000/svg',
36
+ width: size,
37
+ height: size,
38
+ viewBox: '0 0 24 24',
39
+ fill: 'none',
40
+ overflow: 'visible',
41
+ style: Object.keys(style).length > 0 ? style : undefined,
42
+ class: ['lucide', 'lucide-ftp-icon', attrClass].filter(Boolean),
43
+ },
44
+ [
45
+ h('path', { class: 'ftp-icon__folder', d: FOLDER_PATH }),
46
+ h(
47
+ 'text',
48
+ {
49
+ class: 'ftp-icon__label',
50
+ x: 12,
51
+ y: 15,
52
+ textAnchor: 'middle',
53
+ dy: '0.35em',
54
+ },
55
+ 'FTP',
56
+ ),
57
+ ],
58
+ )
59
+ }
60
+ },
61
+ })
@@ -0,0 +1,52 @@
1
+ import { defineComponent, h, type PropType } from 'vue'
2
+
3
+ /**
4
+ * 人大金仓 / KINGBASE 官方品牌 lettermark(stylized「K」:竖干中段向左尖角箭头)。
5
+ * 路径从官网 LOGO 组合包 AI 源文件(英文横排红标)中拆出 K 字形并归一到 24×24。
6
+ * 来源:https://www.kingbase.com.cn/about/about.html → LOGO组合包下载
7
+ * 品牌色取样官网 header logo:#C9151E(政务红)。
8
+ */
9
+ const KINGBASE_MARK_PATH =
10
+ 'M22.5 6.301L22.5 1.973L10.629 7.641L10.629 1.973L6.374 1.973L6.374 9.673L1.5 12L6.374 14.32L6.374 22.027L10.629 22.027L10.629 16.344L22.5 21.994L22.5 17.665L10.629 12.003L10.629 11.997Z'
11
+
12
+ /**
13
+ * NiuMa Kingbase —— 官方品牌 mark,单色填充,默认走政务红并随主题明暗自动调整对比度。
14
+ */
15
+ export const KingbaseIcon = defineComponent({
16
+ name: 'KingbaseIcon',
17
+ inheritAttrs: false,
18
+ props: {
19
+ size: { type: [Number, String] as PropType<number | string>, default: 24 },
20
+ strokeWidth: { type: [Number, String] as PropType<number | string>, default: 2 },
21
+ color: { type: String, default: 'currentColor' },
22
+ },
23
+ setup(props, { attrs }) {
24
+ return () => {
25
+ const size = Number(props.size) || 24
26
+ const { class: attrClass, style: attrStyle, ...restAttrs } = attrs
27
+ const accent = props.color && props.color !== 'currentColor' ? props.color : undefined
28
+ const style: Record<string, string> = {
29
+ ...(typeof attrStyle === 'object' && attrStyle && !Array.isArray(attrStyle)
30
+ ? (attrStyle as Record<string, string>)
31
+ : {}),
32
+ ...(accent ? { '--rs-icon-kingbase-accent': accent } : {}),
33
+ }
34
+
35
+ return h(
36
+ 'svg',
37
+ {
38
+ ...restAttrs,
39
+ xmlns: 'http://www.w3.org/2000/svg',
40
+ width: size,
41
+ height: size,
42
+ viewBox: '0 0 24 24',
43
+ fill: 'none',
44
+ overflow: 'visible',
45
+ style: Object.keys(style).length > 0 ? style : undefined,
46
+ class: ['lucide', 'lucide-kingbase-icon', attrClass].filter(Boolean),
47
+ },
48
+ [h('path', { class: 'kingbase-icon__mark', d: KINGBASE_MARK_PATH })],
49
+ )
50
+ }
51
+ },
52
+ })