@veltra/desktop 1.1.30 → 1.1.32

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 (92) hide show
  1. package/dist/components/action/action-group.vue.d.ts +2 -2
  2. package/dist/components/action/action.vue.d.ts +1 -1
  3. package/dist/components/auto-complete/auto-complete.vue.d.ts +1 -1
  4. package/dist/components/batch-edit/batch-edit.vue.d.ts +1 -1
  5. package/dist/components/cascade/cascade.vue.d.ts +1 -1
  6. package/dist/components/checkbox/checkbox-button.vue.d.ts +1 -1
  7. package/dist/components/checkbox-group/checkbox-group.vue.d.ts +1 -1
  8. package/dist/components/contextmenu/api.d.ts +8 -0
  9. package/dist/components/{context-menu → contextmenu}/api.js +2 -2
  10. package/dist/components/contextmenu/api.js.map +1 -0
  11. package/dist/components/contextmenu/contextmenu-item.js +64 -0
  12. package/dist/components/contextmenu/contextmenu-item.js.map +1 -0
  13. package/dist/components/contextmenu/contextmenu-panel.js +33 -0
  14. package/dist/components/contextmenu/contextmenu-panel.js.map +1 -0
  15. package/dist/components/contextmenu/contextmenu-sub.js +83 -0
  16. package/dist/components/contextmenu/contextmenu-sub.js.map +1 -0
  17. package/dist/components/contextmenu/contextmenu.js +79 -0
  18. package/dist/components/contextmenu/contextmenu.js.map +1 -0
  19. package/dist/components/{context-menu/context-menu.vue.d.ts → contextmenu/contextmenu.vue.d.ts} +5 -5
  20. package/dist/components/contextmenu/di.js +7 -0
  21. package/dist/components/contextmenu/di.js.map +1 -0
  22. package/dist/components/contextmenu/helper.js +8 -0
  23. package/dist/components/contextmenu/helper.js.map +1 -0
  24. package/dist/components/contextmenu/index.d.ts +2 -0
  25. package/dist/components/contextmenu/style2.css +154 -0
  26. package/dist/components/date-picker/date-picker.vue.d.ts +2 -2
  27. package/dist/components/date-range-picker/date-range-picker.vue.d.ts +2 -2
  28. package/dist/components/drawer/drawer.vue.d.ts +2 -2
  29. package/dist/components/empty/empty.vue.d.ts +1 -1
  30. package/dist/components/file-viewer/file-viewer.vue.d.ts +1 -1
  31. package/dist/components/file-viewer/previewers/sheet-previewer.js +33 -93
  32. package/dist/components/file-viewer/previewers/sheet-previewer.js.map +1 -1
  33. package/dist/components/file-viewer/sheet-parser.js +46 -0
  34. package/dist/components/file-viewer/sheet-parser.js.map +1 -0
  35. package/dist/components/index.d.ts +2 -2
  36. package/dist/components/index.js +3 -3
  37. package/dist/components/index.js.map +1 -1
  38. package/dist/components/input/input.vue.d.ts +1 -1
  39. package/dist/components/multi-select/multi-select.vue.d.ts +2 -2
  40. package/dist/components/multi-tree-select/multi-tree-select.vue.d.ts +2 -2
  41. package/dist/components/number-input/number-input.vue.d.ts +1 -1
  42. package/dist/components/number-range-input/number-range-input.vue.d.ts +2 -2
  43. package/dist/components/password-input/password-input.vue.d.ts +1 -1
  44. package/dist/components/progress-nodes/progress-nodes.vue.d.ts +2 -2
  45. package/dist/components/radio-group/radio-group.vue.d.ts +1 -1
  46. package/dist/components/rich-text-editor/rich-text-editor.vue.d.ts +1 -1
  47. package/dist/components/select/select.vue.d.ts +1 -1
  48. package/dist/components/steps/steps.vue.d.ts +1 -1
  49. package/dist/components/tabs/tabs-horizontal.vue.d.ts +2 -2
  50. package/dist/components/tabs/tabs-vertical.vue.d.ts +2 -2
  51. package/dist/components/tabs/tabs.vue.d.ts +2 -2
  52. package/dist/components/textarea/textarea.vue.d.ts +2 -2
  53. package/dist/components/tree-select/tree-select.vue.d.ts +2 -2
  54. package/dist/index.d.ts +5 -5
  55. package/dist/index.js +3 -3
  56. package/dist/style.js +1 -1
  57. package/dist/types/{context-menu.d.ts → contextmenu.d.ts} +12 -10
  58. package/dist/types/index.d.ts +2 -2
  59. package/package.json +6 -6
  60. package/src/components/{context-menu → contextmenu}/api.ts +4 -4
  61. package/src/components/contextmenu/contextmenu-item.vue +63 -0
  62. package/src/components/contextmenu/contextmenu-panel.vue +28 -0
  63. package/src/components/contextmenu/contextmenu-sub.vue +88 -0
  64. package/src/components/contextmenu/contextmenu.vue +77 -0
  65. package/src/components/contextmenu/di.ts +13 -0
  66. package/src/components/contextmenu/helper.ts +5 -0
  67. package/src/components/contextmenu/index.ts +3 -0
  68. package/src/components/contextmenu/style.scss +135 -0
  69. package/src/components/file-viewer/previewers/sheet-previewer.vue +35 -131
  70. package/src/components/file-viewer/sheet-parser.ts +52 -0
  71. package/src/components/index.ts +1 -1
  72. package/src/style.ts +1 -1
  73. package/src/types/{context-menu.ts → contextmenu.ts} +9 -7
  74. package/src/types/index.ts +1 -1
  75. package/dist/components/context-menu/api.d.ts +0 -8
  76. package/dist/components/context-menu/api.js.map +0 -1
  77. package/dist/components/context-menu/context-menu-item.js +0 -60
  78. package/dist/components/context-menu/context-menu-item.js.map +0 -1
  79. package/dist/components/context-menu/context-menu.js +0 -95
  80. package/dist/components/context-menu/context-menu.js.map +0 -1
  81. package/dist/components/context-menu/di.js +0 -6
  82. package/dist/components/context-menu/di.js.map +0 -1
  83. package/dist/components/context-menu/index.d.ts +0 -2
  84. package/dist/components/context-menu/style2.css +0 -52
  85. package/src/components/context-menu/context-menu-item.vue +0 -67
  86. package/src/components/context-menu/context-menu.vue +0 -117
  87. package/src/components/context-menu/di.ts +0 -5
  88. package/src/components/context-menu/index.ts +0 -3
  89. package/src/components/context-menu/style.scss +0 -51
  90. /package/dist/components/{context-menu → contextmenu}/style.d.ts +0 -0
  91. /package/dist/components/{context-menu → contextmenu}/style.js +0 -0
  92. /package/src/components/{context-menu → contextmenu}/style.ts +0 -0
@@ -0,0 +1,135 @@
1
+ @use 'pkg:@veltra/styles/mixins' as m;
2
+ @use 'pkg:@veltra/styles/functions' as fn;
3
+
4
+ $root-name: contextmenu;
5
+ $arrow-size: 12px;
6
+
7
+ @mixin panel-surface {
8
+ margin: 0;
9
+ padding: 4px;
10
+ list-style: none;
11
+ display: flex;
12
+ flex-direction: column;
13
+ gap: 1px;
14
+ user-select: none;
15
+ color: fn.use-var(text-color, main);
16
+ background-color: fn.use-var(bg-color, top);
17
+ border: 1px solid fn.use-var(border, color);
18
+ border-radius: calc(fn.use-var(radius, default) + 2px);
19
+ box-shadow:
20
+ 0 1px 2px rgba(15, 23, 42, 0.05),
21
+ 0 8px 20px rgba(15, 23, 42, 0.08);
22
+ backdrop-filter: fn.use-var(bg-filter);
23
+ -webkit-backdrop-filter: fn.use-var(bg-filter);
24
+ }
25
+
26
+ @include m.b($root-name) {
27
+ $b: &;
28
+
29
+ position: fixed;
30
+ @include panel-surface;
31
+
32
+ @include m.e(label) {
33
+ flex: 1;
34
+ min-width: 0;
35
+ @include m.ellipsis;
36
+ }
37
+
38
+ @include m.e(item) {
39
+ position: relative;
40
+ cursor: pointer;
41
+ padding: 0;
42
+
43
+ @include m.is(disabled, loading) {
44
+ opacity: 0.55;
45
+ cursor: not-allowed;
46
+ color: fn.use-var(text-color, disabled);
47
+ }
48
+
49
+ @include m.is(open) {
50
+ &::after {
51
+ content: '';
52
+ position: absolute;
53
+ top: 0;
54
+ left: 100%;
55
+ width: 6px;
56
+ height: 100%;
57
+ }
58
+
59
+ @include m.is(flip-x) {
60
+ &::after {
61
+ left: auto;
62
+ right: 100%;
63
+ }
64
+ }
65
+ }
66
+ }
67
+
68
+ @include m.e(item-content) {
69
+ gap: 8px;
70
+ width: 100%;
71
+ padding: 0 8px;
72
+ min-height: 28px;
73
+ border-radius: calc(fn.use-var(radius, default) + 1px);
74
+ transition:
75
+ background-color 0.15s ease,
76
+ color 0.15s ease;
77
+ @include m.flex($align: center);
78
+
79
+ #{$b}__item:not(.is-disabled):not(.is-loading) > & {
80
+ &:hover {
81
+ background-color: var(--u-menu-hover-bg);
82
+ color: var(--u-menu-hover-color);
83
+ }
84
+ }
85
+ }
86
+
87
+ #{$b}__item.is-open:not(.is-disabled) > #{$b}__item-content {
88
+ background-color: var(--u-menu-hover-bg);
89
+ color: var(--u-menu-hover-color);
90
+ }
91
+
92
+ @include m.e(icon-place) {
93
+ width: 1em;
94
+ flex-shrink: 0;
95
+ }
96
+
97
+ @include m.e(arrow) {
98
+ width: $arrow-size;
99
+ flex-shrink: 0;
100
+ font-size: $arrow-size;
101
+ opacity: 0.65;
102
+ }
103
+
104
+ @include m.e(arrow-place) {
105
+ width: $arrow-size;
106
+ flex-shrink: 0;
107
+ }
108
+
109
+ @include m.e(sub) {
110
+ position: absolute;
111
+ top: 0;
112
+ left: 100%;
113
+ margin-left: -4px;
114
+ min-width: 120px;
115
+ width: max-content;
116
+ @include panel-surface;
117
+
118
+ @include m.is(flip-x) {
119
+ left: auto;
120
+ right: 100%;
121
+ margin-left: 0;
122
+ margin-right: -4px;
123
+ }
124
+ }
125
+
126
+ @include m.size using ($size) {
127
+ font-size: fn.use-var(font-size-main, $size);
128
+
129
+ @include m.e(item-content) {
130
+ padding: 0 fn.use-var(gap, $size);
131
+ min-height: calc(var(--u-menu-height-#{$size}) - 8px);
132
+ border-radius: calc(fn.use-var(radius, $size) + 1px);
133
+ }
134
+ }
135
+ }
@@ -20,9 +20,11 @@
20
20
 
21
21
  <script lang="ts" setup>
22
22
  import { bem } from '@veltra/utils'
23
+ import { ListTable } from '@visactor/vtable'
23
24
  import { onBeforeUnmount, ref, shallowRef, useTemplateRef, watch } from 'vue'
24
25
 
25
26
  import type { FileViewerItem } from '../../../types/file-viewer'
27
+ import { parseSheetFile, type SheetPreview } from '../sheet-parser'
26
28
 
27
29
  defineOptions({ name: 'FileViewerSheetPreviewer' })
28
30
 
@@ -33,73 +35,53 @@ const props = withDefaults(defineProps<{ file: FileViewerItem; maxRows?: number
33
35
  const emit = defineEmits<{ (e: 'error', err: unknown): void }>()
34
36
 
35
37
  const cls = bem('file-viewer')
36
-
37
38
  const container = useTemplateRef<HTMLDivElement>('container')
38
39
  const loading = ref(true)
39
40
  const truncated = ref(false)
40
41
  const totalRows = ref(0)
41
42
  const renderedRows = ref(0)
42
-
43
- interface SheetData {
44
- name: string
45
- headers: string[]
46
- rows: string[][]
47
- totalCount: number
48
- }
49
-
50
- const sheets = shallowRef<SheetData[]>([])
43
+ const sheets = shallowRef<SheetPreview[]>([])
51
44
  const activeSheetIndex = ref(0)
52
45
 
53
46
  let controller: AbortController | undefined
54
- let instance: { release?: () => void; resize?: () => void } | undefined
47
+ let table: ListTable | undefined
55
48
  let resizeObserver: ResizeObserver | undefined
56
49
 
50
+ function releaseTable() {
51
+ table?.release()
52
+ table = undefined
53
+ }
54
+
55
+ function renderActive() {
56
+ const sheet = sheets.value[activeSheetIndex.value]
57
+ const el = container.value
58
+ if (!sheet || !el) return
59
+
60
+ releaseTable()
61
+
62
+ const limit = props.maxRows > 0 ? Math.min(props.maxRows, sheet.rows.length) : sheet.rows.length
63
+ totalRows.value = sheet.rows.length
64
+ renderedRows.value = limit
65
+ truncated.value = props.maxRows > 0 && sheet.rows.length > props.maxRows
66
+
67
+ table = new ListTable(el, {
68
+ records: sheet.rows.slice(0, limit),
69
+ columns: sheet.headers.map((title, i) => ({ field: String(i), title, width: 'auto' })),
70
+ widthMode: 'standard'
71
+ })
72
+ }
73
+
57
74
  async function load() {
58
75
  controller?.abort()
59
76
  controller = new AbortController()
60
- const signal = controller.signal
61
77
  loading.value = true
62
78
  sheets.value = []
63
79
  activeSheetIndex.value = 0
64
80
 
65
81
  try {
66
- const ext = props.file.name.slice(props.file.name.lastIndexOf('.') + 1).toLowerCase()
67
- const { toArrayBuffer, parseCsv } = await import('../helper')
68
- const buf = await toArrayBuffer(props.file.src, signal)
69
- if (signal.aborted) return
70
-
71
- if (ext === 'csv') {
72
- const text = new TextDecoder('utf-8', { fatal: false }).decode(buf)
73
- const parsed = parseCsv(text).filter((row) => row.some((c) => c.length > 0))
74
- const headers = parsed[0] ?? []
75
- const rows = parsed.slice(1)
76
- sheets.value = [
77
- {
78
- name: props.file.name,
79
- headers: headers.map((h, i) => String(h) || `Column ${i + 1}`),
80
- rows,
81
- totalCount: rows.length
82
- }
83
- ]
84
- } else {
85
- const { readWorkbook } = await import('@cat-kit/excel')
86
- const workbook = await readWorkbook(new Uint8Array(buf))
87
- if (signal.aborted) return
88
- sheets.value = workbook.worksheets.map((ws) => {
89
- const wsRows = ws.getRows()
90
- const firstRow = wsRows[0]
91
- const headers = firstRow ? firstRow.toValues().map((v) => cellToString(v)) : []
92
- const rows = wsRows.slice(1).map((r) => r.toValues().map(cellToString))
93
- return {
94
- name: ws.name,
95
- headers: headers.map((h, i) => h || `Column ${i + 1}`),
96
- rows,
97
- totalCount: rows.length
98
- }
99
- })
100
- }
101
-
102
- await renderActive()
82
+ sheets.value = await parseSheetFile(props.file, controller.signal)
83
+ if (controller.signal.aborted) return
84
+ renderActive()
103
85
  } catch (err) {
104
86
  if ((err as { name?: string })?.name === 'AbortError') return
105
87
  emit('error', err)
@@ -108,97 +90,19 @@ async function load() {
108
90
  }
109
91
  }
110
92
 
111
- function cellToString(v: unknown): string {
112
- if (v === null || v === undefined) return ''
113
- if (typeof v === 'string') return v
114
- if (typeof v === 'number' || typeof v === 'boolean') return String(v)
115
- if (v instanceof Date) return v.toLocaleString()
116
- if (typeof v === 'object' && v !== null && 'formula' in v) {
117
- const f = v as { formula: string; result?: unknown }
118
- if (f.result !== undefined && f.result !== null) return cellToString(f.result)
119
- return `=${f.formula}`
120
- }
121
- return String(v)
122
- }
123
-
124
- async function renderActive() {
125
- const sheet = sheets.value[activeSheetIndex.value]
126
- if (!sheet || !container.value) return
127
-
128
- releaseInstance()
129
-
130
- const limit = props.maxRows > 0 ? Math.min(props.maxRows, sheet.rows.length) : sheet.rows.length
131
- totalRows.value = sheet.totalCount
132
- renderedRows.value = limit
133
- truncated.value = props.maxRows > 0 && sheet.rows.length > props.maxRows
134
-
135
- const columns = sheet.headers.map((h, i) => ({
136
- field: 'c' + i,
137
- title: h,
138
- width: 'auto' as const
139
- }))
140
-
141
- const records: Record<string, string>[] = []
142
- for (let i = 0; i < limit; i++) {
143
- const row = sheet.rows[i]
144
- if (!row) continue
145
- const record: Record<string, string> = {}
146
- for (let j = 0; j < columns.length; j++) {
147
- record['c' + j] = row[j] ?? ''
148
- }
149
- records.push(record)
150
- }
151
-
152
- const VTable = await import('@visactor/vtable')
153
- if (!container.value) return
154
-
155
- instance = new VTable.ListTable(container.value, {
156
- records,
157
- columns,
158
- widthMode: 'standard',
159
- heightMode: 'standard',
160
- defaultRowHeight: 32,
161
- defaultHeaderRowHeight: 36,
162
- autoFillWidth: true,
163
- frozenColCount: 0,
164
- theme: (VTable.themes.ARCO ?? VTable.themes.DEFAULT).extends({
165
- defaultStyle: { borderLineWidth: 1 }
166
- })
167
- })
168
- }
169
-
170
- function releaseInstance() {
171
- if (instance && typeof instance.release === 'function') {
172
- try {
173
- instance.release()
174
- } catch {
175
- /* noop */
176
- }
177
- }
178
- instance = undefined
179
- }
180
-
181
- watch(
182
- () => props.file,
183
- () => load(),
184
- { immediate: true }
185
- )
186
-
187
- watch(activeSheetIndex, () => renderActive())
188
-
93
+ watch(() => props.file, load, { immediate: true })
94
+ watch(activeSheetIndex, renderActive)
189
95
  watch(container, (el) => {
190
96
  resizeObserver?.disconnect()
191
97
  if (!el) return
192
- resizeObserver = new ResizeObserver(() => {
193
- instance?.resize?.()
194
- })
98
+ resizeObserver = new ResizeObserver(() => table?.resize?.())
195
99
  resizeObserver.observe(el)
196
100
  })
197
101
 
198
102
  onBeforeUnmount(() => {
199
103
  controller?.abort()
200
104
  resizeObserver?.disconnect()
201
- releaseInstance()
105
+ releaseTable()
202
106
  sheets.value = []
203
107
  })
204
108
  </script>
@@ -0,0 +1,52 @@
1
+ import { readWorkbook } from '@cat-kit/excel'
2
+
3
+ import type { FileViewerItem } from '../../types/file-viewer'
4
+ import { getExtension, parseCsv, toArrayBuffer } from './helper'
5
+
6
+ export interface SheetPreview {
7
+ name: string
8
+ headers: string[]
9
+ rows: string[][]
10
+ }
11
+
12
+ function cellToString(v: unknown): string {
13
+ if (v == null) return ''
14
+ if (typeof v === 'string') return v
15
+ if (typeof v === 'number' || typeof v === 'boolean') return String(v)
16
+ if (v instanceof Date) return v.toLocaleString()
17
+ if (typeof v === 'object' && 'formula' in v) {
18
+ const f = v as { formula: string; result?: unknown }
19
+ return f.result != null ? cellToString(f.result) : `=${f.formula}`
20
+ }
21
+ return JSON.stringify(v)
22
+ }
23
+
24
+ /** 解析 CSV / Excel 为表格预览数据 */
25
+ export async function parseSheetFile(
26
+ file: FileViewerItem,
27
+ signal?: AbortSignal
28
+ ): Promise<SheetPreview[]> {
29
+ const ext = getExtension(file.name)
30
+ const buf = await toArrayBuffer(file.src, signal)
31
+ if (signal?.aborted) return []
32
+
33
+ if (ext === 'csv') {
34
+ const text = new TextDecoder('utf-8', { fatal: false }).decode(buf)
35
+ const parsed = parseCsv(text).filter((row) => row.some((c) => c.length > 0))
36
+ const headers = (parsed[0] ?? []).map((h, i) => String(h) || `Column ${i + 1}`)
37
+ return [{ name: file.name, headers, rows: parsed.slice(1) }]
38
+ }
39
+
40
+ const workbook = await readWorkbook(new Uint8Array(buf))
41
+ if (signal?.aborted) return []
42
+
43
+ return workbook.worksheets.map((ws) => {
44
+ const wsRows = ws.getRows()
45
+ const firstRow = wsRows[0]
46
+ const headers = (firstRow ? firstRow.toValues().map(cellToString) : []).map(
47
+ (h, i) => h || `Column ${i + 1}`
48
+ )
49
+ const rows = wsRows.slice(1).map((r) => r.toValues().map(cellToString))
50
+ return { name: ws.name, headers, rows }
51
+ })
52
+ }
@@ -66,7 +66,7 @@ export * from './table-editor'
66
66
 
67
67
  export * from './check-tag'
68
68
 
69
- export * from './context-menu'
69
+ export * from './contextmenu'
70
70
 
71
71
  export * from './password-input'
72
72
 
package/src/style.ts CHANGED
@@ -13,7 +13,7 @@ import './components/checkbox/style'
13
13
  import './components/code-editor/style'
14
14
  import './components/collapse/style'
15
15
  import './components/condition-editor/style'
16
- import './components/context-menu/style'
16
+ import './components/contextmenu/style'
17
17
  import './components/date-panel/style'
18
18
  import './components/date-picker/style'
19
19
  import './components/date-range-picker/style'
@@ -4,21 +4,23 @@ import type { Component } from 'vue'
4
4
  /**
5
5
  * 右键菜单项
6
6
  */
7
- export interface ContextMenuItem {
7
+ export interface ContextmenuItem {
8
8
  /** 菜单名称 */
9
9
  label: string
10
10
  /** 菜单描述 */
11
11
  description?: string
12
12
  /** 菜单图标 */
13
13
  icon?: Component
14
+ /** 子菜单 */
15
+ children?: ContextmenuItem[]
14
16
  /** 菜单点击时的回调 */
15
- callback?: () => void | Promise<void>
17
+ callback?: () => any
16
18
  /** 是否禁用 */
17
19
  disabled?: boolean | (() => boolean)
18
20
  }
19
21
 
20
22
  /** 鼠标右键菜单组件属性 */
21
- export interface ContextMenuProps extends ComponentProps {
23
+ export interface ContextmenuProps extends ComponentProps {
22
24
  /** 鼠标位置 */
23
25
  mousePosition: { x: number; y: number }
24
26
  /**
@@ -27,16 +29,16 @@ export interface ContextMenuProps extends ComponentProps {
27
29
  */
28
30
  width?: number | string
29
31
  /** 菜单项 */
30
- menus: ContextMenuItem[] | (() => ContextMenuItem[])
32
+ menus: ContextmenuItem[] | (() => ContextmenuItem[])
31
33
  }
32
34
 
33
35
  /** 鼠标右键菜单组件定义的事件 */
34
- export interface ContextMenuEmits {
36
+ export interface ContextmenuEmits {
35
37
  (e: 'destroy'): void
36
38
  }
37
39
 
38
40
  /** 鼠标右键菜单组件暴露的属性和方法(组件内部使用) */
39
- export interface _ContextMenuExposed {}
41
+ export interface _ContextmenuExposed {}
40
42
 
41
43
  /** 鼠标右键菜单组件暴露的属性和方法(组件外部使用, 引用的值会被自动解构) */
42
- export type ContextMenuExposed = DeconstructValue<_ContextMenuExposed>
44
+ export type ContextmenuExposed = DeconstructValue<_ContextmenuExposed>
@@ -51,7 +51,7 @@ export * from './menu'
51
51
  export * from './password-input'
52
52
  export * from './date-picker'
53
53
  export * from './dropdown'
54
- export * from './context-menu'
54
+ export * from './contextmenu'
55
55
  export * from './select'
56
56
  export * from './radio'
57
57
  export * from './checkbox'
@@ -1,8 +0,0 @@
1
- import { ContextMenuProps } from "../../types/context-menu.js";
2
- //#region src/components/context-menu/api.d.ts
3
- declare const contextmenu: {
4
- pop(options: ContextMenuProps): void;
5
- };
6
- //#endregion
7
- export { contextmenu };
8
- //# sourceMappingURL=api.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"api.js","names":["MContextMenu"],"sources":["../../../src/components/context-menu/api.ts"],"sourcesContent":["import { createVNode, render, type VNode } from 'vue'\n\nimport type { ContextMenuProps } from '../../types'\nimport MContextMenu from './context-menu.vue'\n\nlet node: VNode\n\nexport const contextmenu = {\n pop(options: ContextMenuProps): void {\n if (node) {\n render(null, document.body)\n }\n\n node = createVNode(MContextMenu, {\n ...options,\n onDestroy() {\n render(null, document.body)\n }\n })\n\n render(node, document.body)\n }\n}\n"],"mappings":";;;AAKA,IAAI;AAEJ,MAAa,cAAc,EACzB,IAAI,SAAiC;CACnC,IAAI,MACF,OAAO,MAAM,SAAS,IAAI;CAG5B,OAAO,YAAYA,WAAc;EAC/B,GAAG;EACH,YAAY;GACV,OAAO,MAAM,SAAS,IAAI;EAC5B;CACF,CAAC;CAED,OAAO,MAAM,SAAS,IAAI;AAC5B,EACF"}
@@ -1,60 +0,0 @@
1
- import _sfc_main$1 from "../icon/icon.js";
2
- import { ContextMenuDIKey } from "./di.js";
3
- import { Fragment, computed, createBlock, createElementBlock, createElementVNode, createVNode, defineComponent, inject, normalizeClass, openBlock, resolveDynamicComponent, shallowRef, toDisplayString, unref, withCtx, withDirectives } from "vue";
4
- import { bem } from "@veltra/utils";
5
- import { Loading } from "@veltra/icons/normal";
6
- import { vRipple } from "@veltra/directives";
7
- //#region src/components/context-menu/context-menu-item.vue
8
- const _sfc_main = /* @__PURE__ */ defineComponent({
9
- name: "ContextMenuItem",
10
- __name: "context-menu-item",
11
- props: { menu: {} },
12
- emits: ["click-start", "click-end"],
13
- setup(__props, { emit: __emit }) {
14
- const emit = __emit;
15
- const { cls } = inject(ContextMenuDIKey);
16
- const loading = shallowRef(false);
17
- const disabled = computed(() => {
18
- return (typeof __props.menu.disabled === "function" ? __props.menu.disabled() : __props.menu.disabled) ?? false;
19
- });
20
- function handleClickMenu() {
21
- if (disabled.value || loading.value) return;
22
- emit("click-start");
23
- loading.value = true;
24
- const result = __props.menu.callback?.();
25
- if (result instanceof Promise) return result.then(() => {}).finally(() => {
26
- emit("click-end");
27
- loading.value = false;
28
- });
29
- loading.value = false;
30
- emit("click-end");
31
- }
32
- return (_ctx, _cache) => {
33
- return withDirectives((openBlock(), createElementBlock("li", {
34
- class: normalizeClass([
35
- unref(cls).e("item"),
36
- unref(bem).is("disabled", disabled.value),
37
- unref(bem).is("loading", loading.value),
38
- unref(cls).em("item", "menu")
39
- ]),
40
- onClick: handleClickMenu
41
- }, [loading.value ? (openBlock(), createBlock(unref(_sfc_main$1), {
42
- key: 0,
43
- class: normalizeClass(unref(bem).is("loading"))
44
- }, {
45
- default: withCtx(() => [createVNode(unref(Loading))]),
46
- _: 1
47
- }, 8, ["class"])) : (openBlock(), createElementBlock(Fragment, { key: 1 }, [__props.menu.icon ? (openBlock(), createBlock(unref(_sfc_main$1), { key: 0 }, {
48
- default: withCtx(() => [(openBlock(), createBlock(resolveDynamicComponent(__props.menu.icon)))]),
49
- _: 1
50
- })) : (openBlock(), createElementBlock("i", {
51
- key: 1,
52
- class: normalizeClass(unref(cls).e("icon-place"))
53
- }, null, 2))], 64)), createElementVNode("span", { class: normalizeClass(unref(cls).e("label")) }, toDisplayString(__props.menu.label), 3)], 2)), [[unref(vRipple), !disabled.value && !loading.value]]);
54
- };
55
- }
56
- });
57
- //#endregion
58
- export { _sfc_main as default };
59
-
60
- //# sourceMappingURL=context-menu-item.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"context-menu-item.js","names":[],"sources":["../../../src/components/context-menu/context-menu-item.vue"],"sourcesContent":["<template>\n <li\n :class=\"[\n cls.e('item'),\n bem.is('disabled', disabled),\n bem.is('loading', loading),\n cls.em('item', 'menu')\n ]\"\n v-ripple=\"!disabled && !loading\"\n @click=\"handleClickMenu\"\n >\n <u-icon v-if=\"loading\" :class=\"bem.is('loading')\">\n <Loading />\n </u-icon>\n <template v-else>\n <u-icon v-if=\"menu.icon\">\n <component :is=\"menu.icon\" />\n </u-icon>\n <i v-else :class=\"cls.e('icon-place')\"></i>\n </template>\n\n <span :class=\"cls.e('label')\">{{ menu.label }}</span>\n </li>\n</template>\n\n<script lang=\"ts\" setup>\nimport { vRipple } from '@veltra/directives'\nimport { Loading } from '@veltra/icons/normal'\nimport { bem } from '@veltra/utils'\nimport { computed, inject, shallowRef } from 'vue'\n\nimport type { ContextMenuItem } from '../../types'\nimport { UIcon } from '../icon'\nimport { ContextMenuDIKey } from './di'\n\ndefineOptions({ name: 'ContextMenuItem' })\n\nconst { menu } = defineProps<{ menu: ContextMenuItem }>()\n\nconst emit = defineEmits<{ (e: 'click-start'): void; (e: 'click-end'): void }>()\n\nconst { cls } = inject(ContextMenuDIKey)!\n\nconst loading = shallowRef(false)\n\nconst disabled = computed(() => {\n return (typeof menu.disabled === 'function' ? menu.disabled() : menu.disabled) ?? false\n})\n\nfunction handleClickMenu() {\n if (disabled.value || loading.value) return\n emit('click-start')\n loading.value = true\n const result = menu.callback?.()\n\n if (result instanceof Promise) {\n return result\n .then(() => {})\n .finally(() => {\n emit('click-end')\n loading.value = false\n })\n }\n loading.value = false\n emit('click-end')\n}\n</script>\n"],"mappings":";;;;;;;;;;;;;EAuCA,MAAM,OAAO;EAEb,MAAM,EAAE,QAAQ,OAAO,gBAAgB;EAEvC,MAAM,UAAU,WAAW,KAAK;EAEhC,MAAM,WAAW,eAAe;GAC9B,QAAQ,OAAO,QAAA,KAAK,aAAa,aAAa,QAAA,KAAK,SAAS,IAAI,QAAA,KAAK,aAAa;EACpF,CAAC;EAED,SAAS,kBAAkB;GACzB,IAAI,SAAS,SAAS,QAAQ,OAAO;GACrC,KAAK,aAAa;GAClB,QAAQ,QAAQ;GAChB,MAAM,SAAS,QAAA,KAAK,WAAW;GAE/B,IAAI,kBAAkB,SACpB,OAAO,OACJ,WAAW,CAAC,CAAC,EACb,cAAc;IACb,KAAK,WAAW;IAChB,QAAQ,QAAQ;GAClB,CAAC;GAEL,QAAQ,QAAQ;GAChB,KAAK,WAAW;EAClB;;uCAhEE,mBAqBK,MAAA;IApBF,OAAK,eAAA;KAAU,MAAA,GAAA,EAAI,EAAC,MAAA;KAAgB,MAAA,GAAA,EAAI,GAAE,YAAa,SAAA,KAAQ;KAAS,MAAA,GAAA,EAAI,GAAE,WAAY,QAAA,KAAO;KAAS,MAAA,GAAA,EAAI,GAAE,QAAA,MAAA;;IAOhH,SAAO;OAEM,QAAA,SAAA,UAAA,GAAd,YAES,MAAA,WAAA,GAAA;;IAFe,OAAK,eAAE,MAAA,GAAA,EAAI,GAAE,SAAA,CAAA;;2BACxB,CAAX,YAAW,MAAA,OAAA,CAAA,CAAA,CAAA;;qCAEb,mBAKW,UAAA,EAAA,KAAA,EAAA,GAAA,CAJK,QAAA,KAAK,QAAA,UAAA,GAAnB,YAES,MAAA,WAAA,GAAA,EAAA,KAAA,EAAA,GAAA;2BADsB,EAAA,UAAA,GAA7B,YAA6B,wBAAb,QAAA,KAAK,IAAI,CAAA,EAAA,CAAA;;uBAE3B,mBAA2C,KAAA;;IAAhC,OAAK,eAAE,MAAA,GAAA,EAAI,EAAC,YAAA,CAAA;wBAGzB,mBAAqD,QAAA,EAA9C,OAAK,eAAE,MAAA,GAAA,EAAI,EAAC,OAAA,CAAA,EAAA,GAAA,gBAAc,QAAA,KAAK,KAAK,GAAA,CAAA,CAAA,GAAA,CAAA,IAAA,CAAA,CAAA,MAAA,OAAA,GAAA,CAbhC,SAAA,SAAQ,CAAK,QAAA,KAAO,CAAA,CAAA"}
@@ -1,95 +0,0 @@
1
- import { ContextMenuDIKey } from "./di.js";
2
- import _sfc_main$1 from "./context-menu-item.js";
3
- import { Fragment, Transition, computed, createBlock, createCommentVNode, createElementBlock, defineComponent, normalizeClass, normalizeStyle, openBlock, provide, renderList, shallowRef, unref, withCtx, withDirectives } from "vue";
4
- import { useFallbackProps } from "@veltra/compositions";
5
- import { bem, withUnit, zIndex } from "@veltra/utils";
6
- import { vClickOutside } from "@veltra/directives";
7
- //#region src/components/context-menu/context-menu.vue
8
- const _sfc_main = /* @__PURE__ */ defineComponent({
9
- name: "ContextMenu",
10
- __name: "context-menu",
11
- props: {
12
- mousePosition: {},
13
- width: { default: 150 },
14
- menus: {},
15
- size: {}
16
- },
17
- emits: ["destroy"],
18
- setup(__props, { emit: __emit }) {
19
- const props = __props;
20
- const emit = __emit;
21
- const { size } = useFallbackProps([props], { size: "default" });
22
- const cls = bem("context-menu");
23
- const contextMenuRef = shallowRef();
24
- const visible = shallowRef(true);
25
- const computePosition = () => {
26
- const position = {};
27
- const { mousePosition } = props;
28
- const { x, y } = mousePosition;
29
- if (x > window.innerWidth / 2) position.right = window.innerWidth - x - 1;
30
- else position.left = x + 1;
31
- if (y > window.innerHeight / 2) position.bottom = window.innerHeight - y - 1;
32
- else position.top = y + 1;
33
- position.transformOrigin = `${position.top ? "top" : "bottom"} ${position.left ? "left" : "right"}`;
34
- return Object.fromEntries(Object.entries(position).map(([k, v]) => [k, withUnit(v, "px")]));
35
- };
36
- const style = computed(() => {
37
- return {
38
- width: withUnit(props.width, "px"),
39
- ...computePosition(),
40
- zIndex: zIndex()
41
- };
42
- });
43
- const menus = computed(() => {
44
- const { menus } = props;
45
- if (typeof menus === "function") return menus();
46
- return menus;
47
- });
48
- const getMenuDisabled = (menu) => {
49
- return typeof menu.disabled === "function" ? menu.disabled() : menu.disabled;
50
- };
51
- function close() {
52
- visible.value = false;
53
- }
54
- let loading = false;
55
- function handleClickStart() {
56
- loading = true;
57
- }
58
- function handleClickEnd() {
59
- loading = false;
60
- close();
61
- }
62
- function handleClickOutside() {
63
- if (loading) return;
64
- close();
65
- }
66
- provide(ContextMenuDIKey, { cls });
67
- return (_ctx, _cache) => {
68
- return openBlock(), createBlock(Transition, {
69
- name: "zoom-in",
70
- appear: "",
71
- onAfterLeave: _cache[0] || (_cache[0] = ($event) => emit("destroy"))
72
- }, {
73
- default: withCtx(() => [visible.value ? withDirectives((openBlock(), createElementBlock("ul", {
74
- key: 0,
75
- class: normalizeClass([unref(cls).b, unref(cls).m(unref(size))]),
76
- style: normalizeStyle(style.value),
77
- ref_key: "contextMenuRef",
78
- ref: contextMenuRef
79
- }, [(openBlock(true), createElementBlock(Fragment, null, renderList(menus.value, (menu) => {
80
- return openBlock(), createBlock(_sfc_main$1, {
81
- menu,
82
- disabled: getMenuDisabled(menu),
83
- onClickStart: handleClickStart,
84
- onClickEnd: handleClickEnd
85
- }, null, 8, ["menu", "disabled"]);
86
- }), 256))], 6)), [[unref(vClickOutside), handleClickOutside]]) : createCommentVNode("v-if", true)]),
87
- _: 1
88
- });
89
- };
90
- }
91
- });
92
- //#endregion
93
- export { _sfc_main as default };
94
-
95
- //# sourceMappingURL=context-menu.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"context-menu.js","names":[],"sources":["../../../src/components/context-menu/context-menu.vue"],"sourcesContent":["<template>\n <transition name=\"zoom-in\" appear @after-leave=\"emit('destroy')\">\n <ul\n :class=\"[cls.b, cls.m(size)]\"\n :style=\"style\"\n ref=\"contextMenuRef\"\n v-if=\"visible\"\n v-click-outside=\"handleClickOutside\"\n >\n <UContextMenuItem\n v-for=\"menu of menus\"\n :menu=\"menu\"\n :disabled=\"getMenuDisabled(menu)\"\n @click-start=\"handleClickStart\"\n @click-end=\"handleClickEnd\"\n />\n </ul>\n </transition>\n</template>\n\n<script lang=\"ts\" setup>\nimport { useFallbackProps } from '@veltra/compositions'\nimport { vClickOutside } from '@veltra/directives'\nimport { bem, withUnit, zIndex } from '@veltra/utils'\nimport { computed, provide, shallowRef, type CSSProperties } from 'vue'\n\nimport type {\n ContextMenuEmits,\n ContextMenuItem,\n ContextMenuProps,\n ComponentSize\n} from '../../types'\nimport UContextMenuItem from './context-menu-item.vue'\nimport { ContextMenuDIKey } from './di'\n\ndefineOptions({ name: 'ContextMenu' })\n\nconst props = withDefaults(defineProps<ContextMenuProps>(), { width: 150 })\n\nconst emit = defineEmits<ContextMenuEmits>()\n\nconst { size } = useFallbackProps([props], { size: 'default' as ComponentSize })\n\nconst cls = bem('context-menu')\n\nconst contextMenuRef = shallowRef<HTMLElement>()\n\nconst visible = shallowRef(true)\n\nconst computePosition = () => {\n const position: {\n top?: number\n left?: number\n right?: number\n bottom?: number\n transformOrigin?: string\n } = {}\n\n const { mousePosition } = props\n const { x, y } = mousePosition\n if (x > window.innerWidth / 2) {\n position.right = window.innerWidth - x - 1\n } else {\n position.left = x + 1\n }\n if (y > window.innerHeight / 2) {\n position.bottom = window.innerHeight - y - 1\n } else {\n position.top = y + 1\n }\n\n const positionY = position.top ? 'top' : 'bottom'\n const positionX = position.left ? 'left' : 'right'\n position.transformOrigin = `${positionY} ${positionX}`\n\n return Object.fromEntries(\n Object.entries(position).map(([k, v]) => [k, withUnit(v as number | string | undefined, 'px')])\n ) as CSSProperties\n}\n\nconst style = computed<CSSProperties>(() => {\n return { width: withUnit(props.width, 'px'), ...computePosition(), zIndex: zIndex() }\n})\n\nconst menus = computed(() => {\n const { menus } = props\n if (typeof menus === 'function') {\n return menus()\n }\n return menus\n})\n\nconst getMenuDisabled = (menu: ContextMenuItem) => {\n return typeof menu.disabled === 'function' ? menu.disabled() : menu.disabled\n}\n\nfunction close() {\n visible.value = false\n}\n\nlet loading = false\nfunction handleClickStart() {\n loading = true\n}\n\nfunction handleClickEnd() {\n loading = false\n close()\n}\n\nfunction handleClickOutside() {\n if (loading) return\n close()\n}\n\nprovide(ContextMenuDIKey, { cls })\n</script>\n"],"mappings":";;;;;;;;;;;;;;;;;;EAqCA,MAAM,QAAQ;EAEd,MAAM,OAAO;EAEb,MAAM,EAAE,SAAS,iBAAiB,CAAC,KAAK,GAAG,EAAE,MAAM,UAA2B,CAAC;EAE/E,MAAM,MAAM,IAAI,cAAc;EAE9B,MAAM,iBAAiB,WAAwB;EAE/C,MAAM,UAAU,WAAW,IAAI;EAE/B,MAAM,wBAAwB;GAC5B,MAAM,WAMF,CAAC;GAEL,MAAM,EAAE,kBAAkB;GAC1B,MAAM,EAAE,GAAG,MAAM;GACjB,IAAI,IAAI,OAAO,aAAa,GAC1B,SAAS,QAAQ,OAAO,aAAa,IAAI;QAEzC,SAAS,OAAO,IAAI;GAEtB,IAAI,IAAI,OAAO,cAAc,GAC3B,SAAS,SAAS,OAAO,cAAc,IAAI;QAE3C,SAAS,MAAM,IAAI;GAKrB,SAAS,kBAAkB,GAFT,SAAS,MAAM,QAAQ,SAED,GADtB,SAAS,OAAO,SAAS;GAG3C,OAAO,OAAO,YACZ,OAAO,QAAQ,QAAQ,EAAE,KAAK,CAAC,GAAG,OAAO,CAAC,GAAG,SAAS,GAAkC,IAAI,CAAC,CAAC,CAChG;EACF;EAEA,MAAM,QAAQ,eAA8B;GAC1C,OAAO;IAAE,OAAO,SAAS,MAAM,OAAO,IAAI;IAAG,GAAG,gBAAgB;IAAG,QAAQ,OAAO;GAAE;EACtF,CAAC;EAED,MAAM,QAAQ,eAAe;GAC3B,MAAM,EAAE,UAAU;GAClB,IAAI,OAAO,UAAU,YACnB,OAAO,MAAM;GAEf,OAAO;EACT,CAAC;EAED,MAAM,mBAAmB,SAA0B;GACjD,OAAO,OAAO,KAAK,aAAa,aAAa,KAAK,SAAS,IAAI,KAAK;EACtE;EAEA,SAAS,QAAQ;GACf,QAAQ,QAAQ;EAClB;EAEA,IAAI,UAAU;EACd,SAAS,mBAAmB;GAC1B,UAAU;EACZ;EAEA,SAAS,iBAAiB;GACxB,UAAU;GACV,MAAM;EACR;EAEA,SAAS,qBAAqB;GAC5B,IAAI,SAAS;GACb,MAAM;EACR;EAEA,QAAQ,kBAAkB,EAAE,IAAI,CAAC;;uBAlH/B,YAgBa,YAAA;IAhBD,MAAK;IAAU,QAAA;IAAQ,cAAW,OAAA,OAAA,OAAA,MAAA,WAAE,KAAI,SAAA;;2BAe7C,CAVG,QAAA,QAAA,gBAAA,UAAA,GAJR,mBAcK,MAAA;;KAbF,OAAK,eAAA,CAAG,MAAA,GAAA,EAAI,GAAG,MAAA,GAAA,EAAI,EAAE,MAAA,IAAA,CAAI,CAAA,CAAA;KACzB,OAAK,eAAE,MAAA,KAAK;cACT;KAAJ,KAAI;0BAIJ,mBAME,UAAA,MAAA,WALe,MAAA,QAAR,SAAI;yBADb,YAME,aAAA;MAJO;MACN,UAAU,gBAAgB,IAAI;MAC9B,cAAa;MACb,YAAW;;6CAPG,kBAAkB,CAAA,CAAA,IAAA,mBAAA,QAAA,IAAA,CAAA,CAAA"}
@@ -1,6 +0,0 @@
1
- //#region src/components/context-menu/di.ts
2
- const ContextMenuDIKey = Symbol("ContextMenuDIKey");
3
- //#endregion
4
- export { ContextMenuDIKey };
5
-
6
- //# sourceMappingURL=di.js.map