fit2cloud-ui-plus 0.0.1-beta.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 (89) hide show
  1. package/LICENSE +674 -0
  2. package/README.md +16 -0
  3. package/lib/favicon.bmp +0 -0
  4. package/lib/fit2cloud-ui-plus.es.js +3796 -0
  5. package/lib/fit2cloud-ui-plus.umd.js +1 -0
  6. package/package.json +48 -0
  7. package/src/components/filter-bar/FuFilter.vue +175 -0
  8. package/src/components/filter-bar/FuFilterBar.vue +75 -0
  9. package/src/components/filter-bar/FuFilterConditions.vue +29 -0
  10. package/src/components/filter-bar/FuSearchInput.vue +31 -0
  11. package/src/components/filter-bar/filter-components/FuFilterDate.vue +62 -0
  12. package/src/components/filter-bar/filter-components/FuFilterDateTime.vue +65 -0
  13. package/src/components/filter-bar/filter-components/FuFilterOption.vue +38 -0
  14. package/src/components/filter-bar/filter-components/FuFilterSelect.vue +143 -0
  15. package/src/components/filter-bar/index.ts +19 -0
  16. package/src/components/filter-bar/types.ts +31 -0
  17. package/src/components/read-write-switch/FuInputRwSwitch.vue +44 -0
  18. package/src/components/read-write-switch/FuReadWriteSwitch.vue +91 -0
  19. package/src/components/read-write-switch/FuSelectRwSwitch.vue +53 -0
  20. package/src/components/read-write-switch/index.ts +13 -0
  21. package/src/components/search-bar/FuComplexSearch.vue +108 -0
  22. package/src/components/search-bar/FuQuickSearch.vue +43 -0
  23. package/src/components/search-bar/FuSearchBar.vue +165 -0
  24. package/src/components/search-bar/FuSearchBarButton.vue +14 -0
  25. package/src/components/search-bar/FuSearchContions.vue +24 -0
  26. package/src/components/search-bar/index.ts +13 -0
  27. package/src/components/search-bar/store.ts +25 -0
  28. package/src/components/speed-dial/FuSpeedDial.vue +280 -0
  29. package/src/components/speed-dial/FuSpeedDialActionButton.vue +88 -0
  30. package/src/components/speed-dial/FuSpeedDialButton.vue +42 -0
  31. package/src/components/speed-dial/FuSpeedDialItem.vue +88 -0
  32. package/src/components/speed-dial/index.ts +11 -0
  33. package/src/components/split-pane/FuSplitPane.vue +228 -0
  34. package/src/components/split-pane/index.ts +8 -0
  35. package/src/components/steps/FuHorizontalNavigation.vue +18 -0
  36. package/src/components/steps/FuHorizontalSteps.vue +94 -0
  37. package/src/components/steps/FuStep.vue +13 -0
  38. package/src/components/steps/FuSteps.vue +22 -0
  39. package/src/components/steps/FuStepsFooter.ts +79 -0
  40. package/src/components/steps/FuVerticalNavigation.vue +35 -0
  41. package/src/components/steps/FuVerticalSteps.vue +79 -0
  42. package/src/components/steps/Stepper.ts +188 -0
  43. package/src/components/steps/index.ts +11 -0
  44. package/src/components/table/FuTable.vue +145 -0
  45. package/src/components/table/FuTableBody.ts +40 -0
  46. package/src/components/table/FuTablePagination.vue +42 -0
  47. package/src/components/table/index.ts +15 -0
  48. package/src/components/table/table-column-dropdown/FuTableColumnDropdown.vue +102 -0
  49. package/src/components/table/table-column-dropdown/index.ts +7 -0
  50. package/src/components/table/table-column-select/FuTableColumnSelect.vue +22 -0
  51. package/src/components/table/table-column-select/FuTableColumnSelectDialog.vue +99 -0
  52. package/src/components/table/table-column-select/FuTableColumnSelectPopover.vue +80 -0
  53. package/src/components/table/table-column-select/index.ts +8 -0
  54. package/src/components/table/table-column-select/utils.ts +59 -0
  55. package/src/components/table/table-operations/FuTableButton.vue +19 -0
  56. package/src/components/table/table-operations/FuTableMoreButton.vue +52 -0
  57. package/src/components/table/table-operations/FuTableOperations.vue +88 -0
  58. package/src/components/table/table-operations/index.ts +12 -0
  59. package/src/components/tabs/FuTabs.vue +84 -0
  60. package/src/components/tabs/index.ts +8 -0
  61. package/src/components/virtual-scroller/FuVirtualHorizontalScroll.js +96 -0
  62. package/src/components/virtual-scroller/FuVirtualScroll.js +15 -0
  63. package/src/components/virtual-scroller/FuVirtualVerticalScroll.js +95 -0
  64. package/src/components/virtual-scroller/index.js +10 -0
  65. package/src/hooks/index.ts +3 -0
  66. package/src/hooks/use-global-config/index.ts +32 -0
  67. package/src/hooks/use-locale/index.ts +47 -0
  68. package/src/index.ts +19 -0
  69. package/src/locale/index.ts +12 -0
  70. package/src/locale/lang/en.ts +58 -0
  71. package/src/locale/lang/zh-cn.ts +58 -0
  72. package/src/locale/lang/zh-tw.ts +58 -0
  73. package/src/styles/common/config.scss +5 -0
  74. package/src/styles/common/function.scss +81 -0
  75. package/src/styles/common/mixins.scss +85 -0
  76. package/src/styles/common/variables.scss +28 -0
  77. package/src/styles/components/filter-bar.scss +227 -0
  78. package/src/styles/components/read-write-switch.scss +6 -0
  79. package/src/styles/components/search-bar.scss +285 -0
  80. package/src/styles/components/speed-dial.scss +107 -0
  81. package/src/styles/components/split-pane.scss +111 -0
  82. package/src/styles/components/steps.scss +110 -0
  83. package/src/styles/components/table.scss +105 -0
  84. package/src/styles/components/tabs.scss +10 -0
  85. package/src/styles/components/virtual-scroller.scss +24 -0
  86. package/src/styles/index.scss +11 -0
  87. package/src/tools/theme.ts +23 -0
  88. package/src/tools/time.ts +30 -0
  89. package/src/tools/utils.ts +60 -0
@@ -0,0 +1,80 @@
1
+ <template>
2
+ <el-popover class="fu-table-column-select" popper-class="fu-table-column-select-popper" :trigger="trigger"
3
+ :show-arrow="false" v-show="hasSelect">
4
+ <h3>
5
+ {{ t('fu.table.custom_table_fields') }}
6
+ </h3>
7
+ <div class="fu-table-column-select-popper__body">
8
+ <div v-for="(c, i) in columns" :key="i" class="fu-table-column-select-popper__item">
9
+ <el-checkbox v-model="c.show" :checked="c.show !== false" draggable="true" @dragstart="dragstart($event, i)"
10
+ @dragenter="dragenter" @dragleave="dragleave" @dragover.prevent @dragend="dragend"
11
+ @drop="drop($event, columns, i)" v-show="!c.fix">
12
+ {{ c.label }}
13
+ </el-checkbox>
14
+ </div>
15
+ </div>
16
+ <div class="fu-table-column-select-popper__footer">
17
+ <el-button @click="reset" v-if="columnsKey">
18
+ {{ t('fu.table.reset') }}
19
+ </el-button>
20
+ </div>
21
+
22
+ <template #reference>
23
+ <el-button class="fu-search-bar-button" :icon="icon">{{t('fu.table.custom_table_rows')}}</el-button>
24
+ </template>
25
+ <!-- :size="configSize" -->
26
+ </el-popover>
27
+ </template>
28
+
29
+ <script setup lang="ts">
30
+ import {computed, inject} from "vue";
31
+ import {tableColumnSelect} from "./utils"
32
+ import {useLocale} from "@/hooks"
33
+
34
+ const props = defineProps({
35
+ icon: {
36
+ type: String,
37
+ default: "Setting"
38
+ },
39
+ trigger: {
40
+ type: String,
41
+ default: "click",
42
+ validator: (value: string) => ['click', 'hover'].includes(value)
43
+ },
44
+ columns: {
45
+ type: Array,
46
+ default: () => []
47
+ },
48
+
49
+ });
50
+
51
+ const {t} = useLocale()
52
+
53
+ const localKey = inject("localKey")
54
+
55
+ const {
56
+ columnsKey,
57
+ dragstart,
58
+ dragenter,
59
+ dragleave,
60
+ dragend,
61
+ drop
62
+ } = tableColumnSelect(localKey)
63
+
64
+ const isFixAll = computed(() => {
65
+ return props.columns?.every((c: any) => {
66
+ return c.fix
67
+ })
68
+ });
69
+
70
+ const hasSelect = computed(() => {
71
+ return props.columns?.length > 0 && !isFixAll.value
72
+ });
73
+
74
+ function reset() {
75
+ if (columnsKey) {
76
+ localStorage.removeItem(columnsKey.value)
77
+ }
78
+ props.columns.splice(0, props.columns.length)
79
+ }
80
+ </script>
@@ -0,0 +1,8 @@
1
+ import FuTableColumnSelect from './FuTableColumnSelect.vue';
2
+ import type { App } from 'vue'
3
+
4
+ FuTableColumnSelect.install = (app: App): void => {
5
+ app.component(FuTableColumnSelect.name, FuTableColumnSelect);
6
+ };
7
+
8
+ export default FuTableColumnSelect;
@@ -0,0 +1,59 @@
1
+ import {computed} from "vue";
2
+
3
+ export const tableColumnSelect = (localKey: any) => {
4
+
5
+ const columnsKey = computed((): string => {
6
+ return localKey ? "FU-T-" + localKey : ''
7
+ })
8
+
9
+ function dragstart(event: DragEvent, index: string) {
10
+ if (event.dataTransfer) {
11
+ event.dataTransfer.effectAllowed = "move"
12
+ event.dataTransfer.setData("source_index", index)
13
+ }
14
+ }
15
+
16
+ function dragenter(event: DragEvent) {
17
+ event.preventDefault()
18
+ if (event.target) {
19
+ event.target.style.opacity = .2
20
+ }
21
+ }
22
+
23
+ function dragleave(event: DragEvent) {
24
+ event.preventDefault()
25
+ if (event.target) {
26
+ event.target.style.opacity = ""
27
+ }
28
+ }
29
+
30
+ function dragend(event: DragEvent) {
31
+ if (event.dataTransfer) {
32
+ event.dataTransfer.clearData()
33
+ }
34
+ }
35
+
36
+ function drop(event: DragEvent, list: any, index: number) {
37
+ let source_index = Number(event.dataTransfer?.getData("source_index"))
38
+ let target_index = index
39
+ if (target_index > source_index) {
40
+ list.splice(target_index + 1, 0, list[source_index])
41
+ list.splice(source_index, 1)
42
+ } else {
43
+ list.splice(target_index, 0, list[source_index])
44
+ list.splice(source_index + 1, 1)
45
+ }
46
+ if (event.target) {
47
+ event.target.style.opacity = ""
48
+ }
49
+ }
50
+
51
+ return {
52
+ columnsKey,
53
+ dragstart,
54
+ dragenter,
55
+ dragleave,
56
+ dragend,
57
+ drop
58
+ }
59
+ }
@@ -0,0 +1,19 @@
1
+ <template>
2
+ <el-tooltip :content="label" :disabled="!icon">
3
+ <el-button link v-bind="$attrs" :disabled="disabled">
4
+ <slot></slot>
5
+ </el-button>
6
+ </el-tooltip>
7
+ </template>
8
+ <script lang="ts" setup>
9
+ defineProps({
10
+ size: {
11
+ type: String,
12
+ default: "default"
13
+ },
14
+ label: String,
15
+ disabled: Boolean,
16
+ icon: Boolean,
17
+ });
18
+
19
+ </script>
@@ -0,0 +1,52 @@
1
+ <template>
2
+ <el-dropdown @command="handleCommand" class="fu-table-more-button">
3
+ <el-button link type="primary" @click.stop>
4
+ <el-icon v-if="type === 'icon'">
5
+ <MoreFilled />
6
+ </el-icon>
7
+ <template v-else>
8
+ {{ t('fu.table.more') }}
9
+ </template>
10
+ </el-button>
11
+ <template #dropdown>
12
+ <el-dropdown-menu>
13
+ <el-dropdown-item v-for="(btn, i) in buttons" :key="i" :icon="type === 'icon'&& btn.icon" :disabled="disabled(btn)"
14
+ :command="btn">
15
+ {{ btn.label }}
16
+ </el-dropdown-item>
17
+ </el-dropdown-menu>
18
+ </template>
19
+ </el-dropdown>
20
+ </template>
21
+ <script lang="ts" setup>
22
+ import { computed } from "vue";
23
+ import { useLocale } from "@/hooks"
24
+
25
+ const { t } = useLocale()
26
+ const props = defineProps({
27
+ row: Object,
28
+ buttons: {
29
+ type: Array,
30
+ required: true
31
+ },
32
+ size: {
33
+ type: String,
34
+ default: "default"
35
+ },
36
+ type: {
37
+ type: String,
38
+ default: "label",
39
+ validator: (value: string) => ['icon', 'label'].includes(value)
40
+ },
41
+ });
42
+
43
+ const disabled = computed(() => {
44
+ return function (btn: any) {
45
+ return typeof btn.disabled === "function" ? btn.disabled(props.row) : btn.disabled
46
+ }
47
+ });
48
+
49
+ function handleCommand(btn: any) {
50
+ btn.click(props.row)
51
+ }
52
+ </script>
@@ -0,0 +1,88 @@
1
+ <template>
2
+ <el-table-column class-name="fu-table-operations" :align="align" :width="computeWidth" v-bind="$attrs">
3
+ <template #header>
4
+ {{ $attrs.label }}
5
+ </template>
6
+ <template #default="{ row }">
7
+ <fu-table-button :icon="type === 'icon'" v-for="(btn, i) in defaultButtons(row)" :key="i"
8
+ @click.stop="btn.click(row)" :disabled="disableButton(btn, row)" :label="btn.label" :type="btn.type || 'primary'"
9
+ link>
10
+ <el-icon v-if="type === 'icon'">
11
+ <component :is="btn.icon" />
12
+ </el-icon>
13
+ <template v-else>
14
+ {{ btn.label }}
15
+ </template>
16
+ </fu-table-button>
17
+ <fu-table-more-button :type="type" :buttons="moreButtons(row)" :row="row" v-if="moreButtons(row).length > 0" />
18
+ </template>
19
+ </el-table-column>
20
+ </template>
21
+
22
+ <script lang="ts" setup>
23
+ import { computed } from "vue";
24
+ import FuTableButton from "./FuTableButton.vue";
25
+ import FuTableMoreButton from "./FuTableMoreButton.vue";
26
+
27
+ defineOptions({ name: "FuTableOperations" });
28
+ const props = defineProps({
29
+ // columns: Array,
30
+ align: {
31
+ type: String,
32
+ default: "center"
33
+ },
34
+ width: [String, Number],
35
+ minWidth: [String, Number],
36
+ ellipsis: { // 超过几个按钮时显示省略号,如果只超过一个也不显示省略号
37
+ type: Number,
38
+ default: 3
39
+ },
40
+ buttons: {
41
+ type: Array,
42
+ required: true
43
+ },
44
+ type: {
45
+ type: String,
46
+ default: "label",
47
+ validator: (value: string) => ['icon', 'label'].includes(value)
48
+ },
49
+ });
50
+
51
+ const hasShowFunc = computed(() => {
52
+ return props.buttons.some((btn: any) => typeof btn.show === "function")
53
+ });
54
+
55
+ const defaultButtons = computed(() => {
56
+ return function (row: any) {
57
+ return hasMore(row) ? showButtons(row).slice(0, props.ellipsis) : showButtons(row)
58
+ }
59
+ });
60
+
61
+ const moreButtons = computed(() => {
62
+ return function (row: any) {
63
+ return hasMore(row) ? showButtons(row).slice(props.ellipsis) : []
64
+ }
65
+ });
66
+
67
+ const computeWidth = computed(() => {
68
+ let length = hasShowFunc.value ? props.ellipsis : defaultButtons.value.length
69
+ let buttonsWidth = 35 + length * 58 + 58
70
+ if (props.minWidth) {
71
+ buttonsWidth = buttonsWidth < props.minWidth ? props.minWidth : buttonsWidth
72
+ }
73
+ return props.width ? props.width : buttonsWidth
74
+ });
75
+
76
+ const disableButton = computed(() => {
77
+ return function (btn: any, row: any) {
78
+ return typeof btn.disabled === "function" ? btn.disabled(row) : btn.disabled
79
+ }
80
+ });
81
+
82
+ function showButtons(row: any) {
83
+ return props.buttons?.filter((btn: any) => typeof btn.show === "function" ? btn.show(row) !== false : btn.show !== false)
84
+ }
85
+ function hasMore(row: any) {
86
+ return showButtons(row)?.length > props.ellipsis + 1
87
+ }
88
+ </script>
@@ -0,0 +1,12 @@
1
+ import FuTableOperations from "./FuTableOperations.vue";
2
+ import FuTableButton from "./FuTableButton.vue";
3
+ import FuTableMoreButton from "./FuTableMoreButton.vue";
4
+ import type { App } from 'vue'
5
+
6
+ FuTableOperations.install = (app: App): void => {
7
+ app.component(FuTableOperations.name, FuTableOperations);
8
+ app.component(FuTableButton.name, FuTableButton);
9
+ app.component(FuTableMoreButton.name, FuTableMoreButton);
10
+ };
11
+
12
+ export default FuTableOperations;
@@ -0,0 +1,84 @@
1
+ <template>
2
+ <el-tabs class="fu-tabs" :before-leave="beforeLeave" :editable="false" :addable="false" v-bind="$attrs">
3
+ <slot></slot>
4
+ <el-tab-pane name="add" key="add" v-if="addable">
5
+ <template v-slot:label>
6
+ <slot name="add">
7
+ <!-- 下拉方式 -->
8
+ <el-dropdown @command="handleCommand" v-if="addType === 'dropdown'" :trigger="addTrigger">
9
+ <slot name="dropdownButton">
10
+ <el-button type="primary" plain>
11
+ <el-icon>
12
+ <component :is="addIcon" />
13
+ </el-icon>
14
+ <template v-if="addButtonLabel">{{ addButtonLabel }}</template>
15
+ </el-button>
16
+ </slot>
17
+ <template #dropdown>
18
+ <el-dropdown-menu>
19
+ <el-dropdown-item v-for="(item, i) in dropdownMenus" :key="i" :icon="item.icon"
20
+ :disabled="item.disabled" :divided="item.divided" :command="item.command">
21
+ {{ item.label }}
22
+ </el-dropdown-item>
23
+ </el-dropdown-menu>
24
+ </template>
25
+ </el-dropdown>
26
+ <!-- 默认 -->
27
+ <el-button v-else @click="handleCommand" type="primary" plain>
28
+ <el-icon>
29
+ <component :is="addIcon" />
30
+ </el-icon>
31
+ <template v-if="addButtonLabel">{{ addButtonLabel }}</template>
32
+
33
+ </el-button>
34
+ </slot>
35
+ </template>
36
+ </el-tab-pane>
37
+ </el-tabs>
38
+ </template>
39
+
40
+ <script lang="ts" setup>
41
+ import { uuid } from "@/tools/utils";
42
+ defineOptions({ name: "FuTabs" });
43
+ type TabPanelName = string | number
44
+ const props = defineProps({
45
+ addType: {
46
+ type: String,
47
+ default: "default",
48
+ validator: (val: string) => ["default", "dropdown"].includes(val),
49
+ },
50
+ dropdownMenus: {
51
+ type: Array,
52
+ default: () => [],
53
+ },
54
+ addTrigger: {
55
+ type: String,
56
+ default: "hover",
57
+ validator: (val: string) => ["hover", "click"].includes(val),
58
+ },
59
+ addIcon: {
60
+ type: String,
61
+ default: "Plus",
62
+ },
63
+ addButtonLabel: String,
64
+ addable: Boolean,
65
+ });
66
+ const emit = defineEmits(["command"])
67
+
68
+ function handleCommand(e: any) {
69
+ const name = uuid();
70
+ let obj = null;
71
+ if (e) {
72
+ obj = props.dropdownMenus.find((item: any) => item.command === e);
73
+ }
74
+ emit("command", name, obj);
75
+ }
76
+
77
+ /* 活动标签切换时触发 */
78
+ function beforeLeave(currentName: TabPanelName, oldName: TabPanelName) {
79
+ // 如果name是add,则什么都不触发
80
+ if (currentName === "add") {
81
+ return false;
82
+ }
83
+ }
84
+ </script>
@@ -0,0 +1,8 @@
1
+ import FuTabs from "./FuTabs.vue"
2
+
3
+ import type { App } from 'vue'
4
+ FuTabs.install = (app: App): void => {
5
+ app.component(FuTabs.name, FuTabs)
6
+ }
7
+
8
+ export default FuTabs
@@ -0,0 +1,96 @@
1
+ import measurable from "@/mixins/measurable";
2
+ import {convertToUnit} from "@/tools/utils"
3
+
4
+ export default {
5
+ name: 'FuVirtualHorizontalScroll',
6
+ mixins: [measurable],
7
+ props: {
8
+ items: {
9
+ type: Array,
10
+ required: true
11
+ },
12
+ itemWidth: {
13
+ type: [Number, String],
14
+ required: true
15
+ },
16
+ buffer: {
17
+ type: [Number, String],
18
+ default: 1
19
+ }
20
+ },
21
+ data() {
22
+ return {
23
+ scrollLeft: 0,
24
+ first: 0,
25
+ last: 0,
26
+ }
27
+ },
28
+ watch: {
29
+ width: 'scroll',
30
+ itemWidth: 'scroll',
31
+ },
32
+ computed: {
33
+ intItemWidth() {
34
+ return parseInt(this.itemWidth, 10)
35
+ },
36
+ intBuffer() {
37
+ return parseInt(this.buffer, 10)
38
+ },
39
+ firstToRender({first, intBuffer}) {
40
+ return Math.max(0, first - intBuffer)
41
+ },
42
+ lastToRender({items, last, intBuffer}) {
43
+ return Math.min(items.length, last + intBuffer)
44
+ },
45
+ containerWidth({items, intItemWidth}) {
46
+ return items.length * intItemWidth
47
+ }
48
+ },
49
+ methods: {
50
+ createChild(item, index) {
51
+ index += this.firstToRender
52
+ const left = convertToUnit(index * this.intItemWidth)
53
+
54
+ let data = {
55
+ staticClass: 'fu-virtual-scroll__item',
56
+ style: {left},
57
+ key: index,
58
+ }
59
+ let children = this.$scopedSlots["default"]({index, item})
60
+
61
+ return this.$createElement('div', data, children)
62
+ },
63
+ getFirst() {
64
+ return Math.floor(this.scrollLeft / this.intItemWidth)
65
+ },
66
+ getLast() {
67
+ const width = parseInt(this.width || 0, 10) || this.$el.clientWidth
68
+ return this.first + Math.ceil(width / this.intItemWidth)
69
+ },
70
+ scroll() {
71
+ this.scrollLeft = this.$el.scrollLeft
72
+ this.first = this.getFirst()
73
+ this.last = this.getLast()
74
+ }
75
+ },
76
+ render(h) {
77
+ const children = this.items.slice(this.firstToRender, this.lastToRender,).map(this.createChild)
78
+
79
+ const content = h('div', {
80
+ staticClass: 'fu-virtual-scroll__container',
81
+ style: {
82
+ height: this.height || "100%",
83
+ width: convertToUnit(this.containerWidth),
84
+ },
85
+ }, children)
86
+
87
+ return h('div', {
88
+ staticClass: 'fu-virtual-scroll is-horizontal',
89
+ style: this.styles,
90
+ on: {scroll: this.scroll, ...this.$listeners},
91
+ }, [content])
92
+ },
93
+ mounted() {
94
+ this.last = this.getLast()
95
+ },
96
+ }
@@ -0,0 +1,15 @@
1
+ import FuVirtualVerticalScroll from "./FuVirtualVerticalScroll";
2
+ import FuVirtualHorizontalScroll from "./FuVirtualHorizontalScroll";
3
+
4
+ export default {
5
+ name: "FuVirtualScroll",
6
+ functional: true,
7
+ render(h, {props, data, children}) {
8
+ const {horizontal} = props
9
+ if (horizontal === undefined || horizontal === false) {
10
+ return h(FuVirtualVerticalScroll, data, children)
11
+ } else {
12
+ return h(FuVirtualHorizontalScroll, data, children)
13
+ }
14
+ }
15
+ }
@@ -0,0 +1,95 @@
1
+ import measurable from "@/mixins/measurable";
2
+ import {convertToUnit} from "@/tools/utils"
3
+
4
+ export default {
5
+ name: 'FuVirtualVerticalScroll',
6
+ mixins: [measurable],
7
+ props: {
8
+ items: {
9
+ type: Array,
10
+ required: true
11
+ },
12
+ itemHeight: {
13
+ type: [Number, String],
14
+ required: true
15
+ },
16
+ buffer: {
17
+ type: [Number, String],
18
+ default: 1
19
+ }
20
+ },
21
+ data() {
22
+ return {
23
+ scrollTop: 0,
24
+ first: 0,
25
+ last: 0,
26
+ }
27
+ },
28
+ watch: {
29
+ height: 'scroll',
30
+ itemHeight: 'scroll',
31
+ },
32
+ computed: {
33
+ intItemHeight() {
34
+ return parseInt(this.itemHeight, 10)
35
+ },
36
+ intBuffer() {
37
+ return parseInt(this.buffer, 10)
38
+ },
39
+ firstToRender({first, intBuffer}) {
40
+ return Math.max(0, first - intBuffer)
41
+ },
42
+ lastToRender({items, last, intBuffer}) {
43
+ return Math.min(items.length, last + intBuffer)
44
+ },
45
+ containerHeight({items, intItemHeight}) {
46
+ return items.length * intItemHeight
47
+ }
48
+ },
49
+ methods: {
50
+ createChild(item, index) {
51
+ index += this.firstToRender
52
+ const top = convertToUnit(index * this.intItemHeight)
53
+
54
+ let data = {
55
+ staticClass: 'fu-virtual-scroll__item',
56
+ style: {top},
57
+ key: index,
58
+ }
59
+ let children = this.$scopedSlots["default"]({index, item})
60
+
61
+ return this.$createElement('div', data, children)
62
+ },
63
+ getFirst() {
64
+ return Math.floor(this.scrollTop / this.intItemHeight)
65
+ },
66
+ getLast() {
67
+ const height = parseInt(this.height || 0, 10) || this.$el.clientHeight
68
+ return this.first + Math.ceil(height / this.intItemHeight)
69
+ },
70
+ scroll() {
71
+ this.scrollTop = this.$el.scrollTop
72
+ this.first = this.getFirst()
73
+ this.last = this.getLast()
74
+ }
75
+ },
76
+ render(h) {
77
+ const children = this.items.slice(this.firstToRender, this.lastToRender,).map(this.createChild)
78
+
79
+ const content = h('div', {
80
+ staticClass: 'fu-virtual-scroll__container',
81
+ style: {
82
+ height: convertToUnit(this.containerHeight),
83
+ },
84
+ }, children)
85
+
86
+ return h('div', {
87
+ staticClass: 'fu-virtual-scroll',
88
+ style: this.styles,
89
+ on: {scroll: this.scroll, ...this.$listeners},
90
+ }, [content])
91
+ },
92
+ mounted() {
93
+ this.last = this.getLast()
94
+ },
95
+ }
@@ -0,0 +1,10 @@
1
+ import FuVirtualScroll from "./FuVirtualScroll";
2
+ import locale from "@/locale";
3
+
4
+ FuVirtualScroll.install = function (Vue, opts = {}) {
5
+ locale.use(opts.locale)
6
+ locale.i18n(opts.i18n)
7
+ Vue.component(FuVirtualScroll.name, FuVirtualScroll)
8
+ }
9
+
10
+ export default FuVirtualScroll
@@ -0,0 +1,3 @@
1
+
2
+ export * from './use-global-config'
3
+ export * from './use-locale'
@@ -0,0 +1,32 @@
1
+ import { computed, getCurrentInstance, inject, ref } from 'vue'
2
+ // import { configProviderContextKey } from '@element-plus/tokens'
3
+ // import type { Ref } from 'vue'
4
+ // import type { ConfigProviderContext } from '@element-plus/tokens'
5
+
6
+ // this is meant to fix global methods like `ElMessage(opts)`, this way we can inject current locale
7
+ // into the component as default injection value.
8
+ // refer to: https://github.com/element-plus/element-plus/issues/2610#issuecomment-887965266
9
+ const globalConfig = ref()
10
+
11
+ // export function useGlobalConfig<
12
+ // K extends keyof ConfigProviderContext,
13
+ // D extends ConfigProviderContext[K]
14
+ // >(
15
+ // key: K,
16
+ // defaultValue?: D
17
+ // ): Ref<Exclude<ConfigProviderContext[K], undefined> | D>
18
+ // export function useGlobalConfig(): Ref<ConfigProviderContext>
19
+ export function useGlobalConfig(
20
+ key?: keyof any,
21
+ defaultValue = undefined
22
+ ) {
23
+ const config = getCurrentInstance()
24
+ ? inject( Symbol(), globalConfig)
25
+ : globalConfig
26
+ if (key) {
27
+ return computed(() => config.value?.[key] ?? defaultValue)
28
+ } else {
29
+ return config
30
+ }
31
+ }
32
+