@ithinkdt/ui 4.0.0-10 → 4.0.0-11

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ithinkdt/ui",
3
- "version": "4.0.0-10",
3
+ "version": "4.0.0-11",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "description": "iThinkDT UI",
@@ -63,7 +63,7 @@
63
63
  "sortablejs": "^1.15.6",
64
64
  "@types/sortablejs": "^1.15.8",
65
65
  "nanoid": "^5.1.6",
66
- "@ithinkdt/common": "^4.0.0-10"
66
+ "@ithinkdt/common": "^4.0.0-11"
67
67
  },
68
68
  "peerDependencies": {
69
69
  "@ithinkdt/page": ">=4.0",
@@ -88,12 +88,9 @@
88
88
  "vite": "npm:rolldown-vite@^7.1.16",
89
89
  "vue": "^3.5.22",
90
90
  "vue-router": "^4.5.1",
91
- "@ithinkdt/page": "^4.0.0-10"
91
+ "@ithinkdt/page": "^4.0.0-11"
92
92
  },
93
93
  "scripts": {
94
- "build": " vite build && cp -r ./_src/*.d.ts ./src",
95
- "prerelease": "cp -r ./src ./_src && pnpm run build",
96
- "release": "pnpm publish --no-git-checks",
97
- "postrelease": "rm -rf ./src && cp -r ./_src ./src && rm -rf ./_src"
94
+ "release": "pnpm publish --no-git-checks"
98
95
  }
99
96
  }
@@ -0,0 +1,128 @@
1
+ import { NCheckbox, NCheckboxGroup, NFlex } from 'ithinkdt-ui'
2
+ import { computed, defineComponent, ref, watch } from 'vue'
3
+
4
+ import { useI18n } from '../use-i18n.js'
5
+
6
+ export const NCheckboxes = defineComponent({
7
+ name: 'Checkboxes',
8
+ inheritAttrs: false,
9
+ props: {
10
+ options: {
11
+ type: Array,
12
+ default: () => [],
13
+ },
14
+ vertical: {
15
+ type: Boolean,
16
+ default: false,
17
+ },
18
+ default: {
19
+ type: [Boolean, String, Object],
20
+ default: false,
21
+ },
22
+ gap: {
23
+ type: [Number, String, Array],
24
+ default: undefined,
25
+ },
26
+ value: {
27
+ type: Array,
28
+ default: undefined,
29
+ },
30
+ labelPadding: {
31
+ type: String,
32
+ default: undefined,
33
+ },
34
+ labelField: {
35
+ type: String,
36
+ default: 'label',
37
+ },
38
+ valueField: {
39
+ type: String,
40
+ default: 'value',
41
+ },
42
+ disabledField: {
43
+ type: String,
44
+ default: 'disabled',
45
+ },
46
+ },
47
+ emits: {
48
+ 'update:value': () => true,
49
+ },
50
+
51
+ setup(props, { emit, attrs }) {
52
+ const { t } = useI18n()
53
+ const defaultLabel = computed(() => {
54
+ if (!props.default) return ''
55
+ if (props.default === true) return t('common.all')
56
+ if (typeof props.default === 'string') return props.default
57
+ return props.default?.[props.labelField] ?? t('common.all')
58
+ })
59
+ const checked = ref([])
60
+
61
+ watch(
62
+ () => props.value,
63
+ v => (checked.value = v),
64
+ { immediate: true },
65
+ )
66
+
67
+ const emitValue = (v) => {
68
+ emit('update:value', v)
69
+ }
70
+ const onAll = () => {
71
+ emitValue(
72
+ checked.value?.length === props.options.length ? [] : props.options.map(it => it[props.valueField]),
73
+ )
74
+ }
75
+ const indeterminate = computed(() => props.options.length > checked.value?.length && checked.value?.length > 0)
76
+
77
+ const style = computed(() => {
78
+ return {
79
+ '--n-label-padding': props.labelPadding,
80
+ }
81
+ })
82
+ return () => {
83
+ const group = (
84
+ <NCheckboxGroup {...attrs} value={checked.value} onUpdateValue={emitValue}>
85
+ <NFlex
86
+ size={props.gap ?? (props.vertical ? undefined : 'small')}
87
+ vertical={props.vertical}
88
+ style={!props.default && props.vertical ? { padding: '6px 0 0' } : {}}
89
+ >
90
+ {props.options?.map(op => (
91
+ <NCheckbox
92
+ value={op[props.valueField]}
93
+ disabled={op[props.disabledField]}
94
+ style={style.value}
95
+ >
96
+ {op[props.labelField]}
97
+ </NCheckbox>
98
+ ))}
99
+ </NFlex>
100
+ </NCheckboxGroup>
101
+ )
102
+
103
+ return props.default
104
+ ? (
105
+ <NFlex
106
+ size={props.gap ?? (props.vertical ? undefined : 'small')}
107
+ vertical={props.vertical}
108
+ style={props.vertical ? { padding: '6px 0 0' } : {}}
109
+ >
110
+ <span>
111
+ <NCheckbox
112
+ indeterminate={indeterminate.value}
113
+ checked={checked.value?.length > 0}
114
+ onUpdateChecked={onAll}
115
+ style={style.value}
116
+ >
117
+ {defaultLabel.value}
118
+ </NCheckbox>
119
+ </span>
120
+ {group}
121
+ </NFlex>
122
+ )
123
+ : (
124
+ group
125
+ )
126
+ }
127
+ },
128
+ })
@@ -0,0 +1,107 @@
1
+ import { NButton, NDropdown } from 'ithinkdt-ui'
2
+ import { computed, defineComponent } from 'vue'
3
+ import { VOverflow, VResizeObserver } from 'vueuc'
4
+
5
+ import { IMore } from './assets.jsx'
6
+
7
+ export const DataActions = /* @__PURE__ */ defineComponent({
8
+ name: 'DataActions',
9
+ props: {
10
+ options: {
11
+ type: Array,
12
+ default: () => [],
13
+ },
14
+ },
15
+ setup(props) {
16
+ const ofRef = ref()
17
+ let isFirstResize = true
18
+ const onResize = () => {
19
+ if (isFirstResize) {
20
+ isFirstResize = false
21
+ } else {
22
+ ofRef.value?.sync({
23
+ showAllItemsBeforeCalculate: true,
24
+ })
25
+ }
26
+ }
27
+ const counter = ref()
28
+ const getCounter = () => {
29
+ return counter.value
30
+ }
31
+ const ellipsisFromIndexRef = ref(-1)
32
+ const onUpdateCount = (count) => {
33
+ ellipsisFromIndexRef.value = props.options.length - count
34
+ }
35
+ const onUpdateOverflow = (overflow) => {
36
+ if (!overflow) {
37
+ ellipsisFromIndexRef.value = -1
38
+ }
39
+ }
40
+ const updateCounter = () => {}
41
+ const moreOptions = computed(() => {
42
+ if (ellipsisFromIndexRef.value === -1) return []
43
+ return props.options.slice(ellipsisFromIndexRef.value).map((act) => {
44
+ return {
45
+ ...act,
46
+ key: act.text,
47
+ }
48
+ })
49
+ })
50
+
51
+ const renderLabel = (act) => {
52
+ const color = act.color === 'danger'
53
+ ? 'error'
54
+ : ['default', 'tertiary', 'primary', 'info', 'success', 'warning', 'error'].includes(act.color)
55
+ ? act.color
56
+ : 'primary'
57
+ return (
58
+ <NButton type={color} text>
59
+ {act.text}
60
+ </NButton>
61
+ )
62
+ }
63
+
64
+ const onSelect = (key, act) => {
65
+ act.onClick?.()
66
+ }
67
+
68
+ return () => {
69
+ return (
70
+ <VResizeObserver onResize={onResize}>
71
+ <VOverflow
72
+ ref={ofRef}
73
+ getCounter={getCounter}
74
+ onUpdateCount={onUpdateCount}
75
+ onUpdateOverflow={onUpdateOverflow}
76
+ updateCounter={updateCounter}
77
+ style="width: 100%; display: flex; overflow: hidden; align-items: center; line-height: 1.25;"
78
+ >
79
+ { {
80
+ default: () => props.options.map((act) => {
81
+ const color = act.color === 'danger'
82
+ ? 'error'
83
+ : ['default', 'tertiary', 'primary', 'info', 'success', 'warning', 'error'].includes(act.color)
84
+ ? act.color
85
+ : 'primary'
86
+ return (
87
+ <span>
88
+ <NButton quaternary type={color} size="small" onClick={act.onClick}>
89
+ {act.text}
90
+ </NButton>
91
+ </span>
92
+ )
93
+ }),
94
+ counter: () => (
95
+ <span ref={counter}>
96
+ <NDropdown options={moreOptions.value} renderLabel={renderLabel} onSelect={onSelect}>
97
+ <NButton quaternary size="small"><IMore style="font-size: 14px; color: #888" /></NButton>
98
+ </NDropdown>
99
+ </span>
100
+ ),
101
+ }}
102
+ </VOverflow>
103
+ </VResizeObserver>
104
+ )
105
+ }
106
+ },
107
+ })
@@ -0,0 +1,172 @@
1
+ import { NButton, NCheckbox, NEllipsis, NFlex, NIcon, NPopover } from 'ithinkdt-ui'
2
+ import { Sortable } from 'sortablejs/modular/sortable.core.esm.js'
3
+ import { defineComponent, ref, toValue, watch, withDirectives } from 'vue'
4
+
5
+ import { vTooltip } from '../directives/tooltip.jsx'
6
+ import { useI18n } from '../use-i18n.js'
7
+
8
+ import { ICustom, IDrag, ILeft, IRight } from './assets.jsx'
9
+
10
+ const DataCustomItem = /* @__PURE__ */ defineComponent({
11
+ name: 'DataCustomRow',
12
+ props: {
13
+ label: [String, Function],
14
+ disabled: Boolean,
15
+ hidden: Boolean,
16
+ fixed: [Boolean, String],
17
+ },
18
+ emits: ['update-hidden', 'update-fixed'],
19
+ setup(props, { emit }) {
20
+ return () => {
21
+ return (
22
+ <NFlex align="center" wrap={false} size="small">
23
+ <NButton type="primary" text class="icon-drag">
24
+ <NIcon size="18">
25
+ <IDrag />
26
+ </NIcon>
27
+ </NButton>
28
+ <NCheckbox
29
+ checked={!props.hidden}
30
+ disabled={props.disabled}
31
+ onUpdateChecked={v => emit('update-hidden', !v)}
32
+ />
33
+ <NEllipsis style="flex: 1 1 auto">{toValue(props.label)}</NEllipsis>
34
+ <NButton
35
+ text
36
+ type={props.fixed === 'left' ? 'primary' : undefined}
37
+ onClick={() => emit('update-fixed', props.fixed === 'left' ? false : 'left')}
38
+ >
39
+ <NIcon>
40
+ <ILeft />
41
+ </NIcon>
42
+ </NButton>
43
+ <NButton
44
+ text
45
+ type={props.fixed === 'right' ? 'primary' : undefined}
46
+ onClick={() => emit('update-fixed', props.fixed === 'right' ? false : 'right')}
47
+ >
48
+ <NIcon>
49
+ <IRight />
50
+ </NIcon>
51
+ </NButton>
52
+ </NFlex>
53
+ )
54
+ }
55
+ },
56
+ })
57
+
58
+ export const DataCustom = /* @__PURE__ */ defineComponent({
59
+ name: 'DataCustom',
60
+ props: {
61
+ data: {
62
+ type: Array,
63
+ required: true,
64
+ },
65
+ keyField: {
66
+ type: String,
67
+ default: 'key',
68
+ },
69
+ labelField: {
70
+ type: String,
71
+ default: 'label',
72
+ },
73
+ fixedField: {
74
+ type: String,
75
+ default: 'fixed',
76
+ },
77
+ hiddenField: {
78
+ type: String,
79
+ default: 'hidden',
80
+ },
81
+ showFixed: {
82
+ type: Boolean,
83
+ default: false,
84
+ },
85
+ disabledField: {
86
+ type: String,
87
+ default: 'disabled',
88
+ },
89
+ visiblityField: {
90
+ type: String,
91
+ default: 'visiblity',
92
+ },
93
+ tooltip: [String, Object],
94
+ },
95
+ emits: {
96
+ custom: () => true,
97
+ },
98
+ setup(props, { emit }) {
99
+ const { t } = useI18n()
100
+
101
+ function emitCols(col, field, value) {
102
+ emit('custom', {
103
+ key: col.key,
104
+ [field]: value,
105
+ })
106
+ }
107
+
108
+ const ulRef = ref()
109
+
110
+ watch(ulRef, (inst) => {
111
+ if (!inst.$el) return
112
+ Sortable.create(inst.$el, {
113
+ animation: 150,
114
+ ghostClass: 'ghost',
115
+ handle: '.icon-drag',
116
+ filter: '.disabled',
117
+ onEnd(e) {
118
+ const orders = props.data.map(item => item[props.keyField])
119
+ const [curr] = orders.splice(e.oldIndex, 1)
120
+ orders.splice(e.newIndex, 0, curr)
121
+ emit('custom', orders)
122
+ },
123
+ })
124
+ })
125
+
126
+ return () => (
127
+ <NPopover
128
+ trigger="click"
129
+ scrollable
130
+ placement="left-start"
131
+ displayDirective="show"
132
+ style="max-height: 400px; width: 240px"
133
+ >
134
+ {{
135
+ trigger: () =>
136
+ withDirectives(
137
+ <NButton text>
138
+ <NIcon size="20">
139
+ <ICustom />
140
+ </NIcon>
141
+ </NButton>,
142
+ [[vTooltip, props.tooltip ?? t('common.page.custom.tooltip')]],
143
+ ),
144
+ default: () => (
145
+ <NFlex vertical>
146
+ <NFlex justify="space-between">
147
+ <div style="font-weight: bold">{props.tooltip ?? t('common.page.custom.tooltip') }</div>
148
+ <NButton text type="primary" size="small" onClick={() => emit('custom', true)}>
149
+ { t('common.page.custom.reset') }
150
+ </NButton>
151
+ </NFlex>
152
+ <NFlex ref={ulRef} vertical>
153
+ {props.data
154
+ .filter(item => item[props.visiblityField] !== false)
155
+ .map(item => (
156
+ <DataCustomItem
157
+ key={item[props.keyField]}
158
+ label={item[props.labelField]}
159
+ hidden={item[props.hiddenField]}
160
+ fixed={item[props.fixedField]}
161
+ onUpdateHidden={v => emitCols(item, 'hidden', v)}
162
+ onUpdateFixed={v => emitCols(item, 'fixed', v)}
163
+ />
164
+ ))}
165
+ </NFlex>
166
+ </NFlex>
167
+ ),
168
+ }}
169
+ </NPopover>
170
+ )
171
+ },
172
+ })
@@ -0,0 +1,113 @@
1
+ import { NButton, NFlex, formProps } from 'ithinkdt-ui'
2
+ import { defineComponent, reactive, ref } from 'vue'
3
+
4
+ import { pickProps } from '@ithinkdt/common/object'
5
+
6
+ import { useI18n } from '../use-i18n.js'
7
+
8
+ import { DataForm } from './DataForm.jsx'
9
+ import { IDown, IUp } from './assets.jsx'
10
+
11
+ export const DataFilter = /* @__PURE__ */ defineComponent({
12
+ name: 'DataFilter',
13
+ props: {
14
+ grid: {
15
+ type: Object,
16
+ default: () => ({}),
17
+ },
18
+ ...pickProps(formProps, 'disabled', 'model'),
19
+ labelWidth: { type: [String, Number], default: '5em' },
20
+ labelPlacement: { type: String, default: 'left' },
21
+ items: { type: Array, required: true },
22
+ loading: { type: Boolean, required: false, default: false },
23
+ filterOnReset: { type: Boolean, required: false, default: true },
24
+ filterText: { type: String, default: undefined },
25
+ resetText: { type: String, default: undefined },
26
+ customizable: { type: Boolean, required: false, default: true },
27
+ collapsible: { type: Boolean, required: false, default: true },
28
+ defaultCollapsed: { type: Boolean, required: false, default: true },
29
+ },
30
+ emits: ['filter', 'reset', 'custom', 'collapse'],
31
+ setup(props, { expose, emit }) {
32
+ const { t } = useI18n()
33
+
34
+ const onSubmit = (e) => {
35
+ emit('filter', props.model, e)
36
+ }
37
+ const onReset = (e) => {
38
+ emit('reset', e)
39
+ if (props.filterOnReset) {
40
+ emit('filter', props.model, e)
41
+ }
42
+ }
43
+ const collapsed = ref(props.defaultCollapsed)
44
+ const collapse = (collapsedValue) => {
45
+ collapsed.value = collapsedValue
46
+ }
47
+
48
+ expose({
49
+ collapse,
50
+ })
51
+
52
+ const action = reactive({
53
+ span: 6,
54
+ suffix: true,
55
+ })
56
+
57
+ return () => {
58
+ const { filterOnReset, filterText, resetText, customizable, defaultCollapsed, collapsible, grid, ...formProps } = props
59
+
60
+ return (
61
+ <DataForm
62
+ grid={
63
+ {
64
+ cols: '12 768:18 1280:24 1536:30',
65
+ yGap: 20,
66
+ xGap: 8,
67
+ ...grid,
68
+ collapsed: collapsed.value,
69
+ }
70
+ }
71
+ {...formProps}
72
+ showFeedback={false}
73
+ showAction={action}
74
+ onSubmit={onSubmit}
75
+ onReset={onReset}
76
+ >
77
+ {{
78
+ action: ({ cols, spans }) => {
79
+ action.suffix = cols < (spans + action.span)
80
+
81
+ return (
82
+ <NFlex justify={action.suffix ? 'end' : 'start'} align="center">
83
+ {action.suffix ? undefined : <span>&nbsp;&nbsp;&nbsp;&nbsp;</span>}
84
+ <NButton attrType="submit" type="primary" disabled={props.disabled} loading={props.loading}>
85
+ {filterText || t('common.page.filter.submitText') }
86
+ </NButton>
87
+ <NButton attrType="reset" disabled={props.disabled || props.loading}>
88
+ {resetText || t('common.page.form.resetText') }
89
+ </NButton>
90
+ {
91
+ collapsible && action.suffix
92
+ ? (
93
+ <NButton
94
+ text
95
+ type="primary"
96
+ iconPlacement="right"
97
+ renderIcon={collapsed.value ? IDown : IUp}
98
+ onClick={() => collapse(!collapsed.value)}
99
+ >
100
+ {collapsed.value ? t('common.page.filter.expand') : t('common.page.filter.collapse') }
101
+ </NButton>
102
+ )
103
+ : undefined
104
+ }
105
+ </NFlex>
106
+ )
107
+ },
108
+ }}
109
+ </DataForm>
110
+ )
111
+ }
112
+ },
113
+ })