@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.
@@ -0,0 +1,264 @@
1
+ import { debouncedWatch, useCurrentElement, useElementSize } from '@vueuse/core'
2
+ import { NButton, NFlex, NForm, NFormItem, NGi, NGrid, NIcon, NText, NTooltip, formProps } from 'ithinkdt-ui'
3
+ import { defineComponent, ref, toRaw, toValue } from 'vue'
4
+
5
+ import { pickProps } from '@ithinkdt/common/object'
6
+
7
+ import { useI18n } from '../use-i18n.js'
8
+
9
+ import { ICheck, IHelp } from './assets.jsx'
10
+
11
+ export const DataForm = /* @__PURE__ */ defineComponent({
12
+ name: 'DataForm',
13
+ props: {
14
+ grid: {
15
+ type: Object,
16
+ default: () => ({}),
17
+ },
18
+ ...pickProps(formProps, 'disabled', 'model', 'labelWidth', 'labelAlign', 'showFeedback', 'size'),
19
+ readonly: { type: Boolean, required: false, default: undefined },
20
+ items: { type: Array, required: true },
21
+ validation: { type: Object, default: () => ({}) },
22
+ loading: Boolean,
23
+ showColon: Boolean,
24
+ actionAlign: { type: String, default: 'start' },
25
+ showAction: { type: [Boolean, Object], default: undefined },
26
+ submitText: { type: [String, Number, Object], default: undefined },
27
+ resetText: { type: [String, Number, Object], default: undefined },
28
+ cancelText: { type: [String, Number, Object], default: undefined },
29
+ showSubmitBtn: { type: Boolean, required: false, default: true },
30
+ showResetBtn: { type: Boolean, required: false, default: true },
31
+ showCancelBtn: { type: Boolean, required: false, default: false },
32
+ submitDisabled: Boolean,
33
+ succeeded: Boolean,
34
+ successText: { type: [String, Number, Object], default: undefined },
35
+ tooltipPlacement: { type: String, default: 'bottom' },
36
+ requireMarkPlacement: { type: String, default: 'left' },
37
+ labelPlacement: { type: String, default: 'left' },
38
+ },
39
+ emits: ['submit', 'reset', 'cancel'],
40
+ setup(props, { emit, slots }) {
41
+ const { t } = useI18n()
42
+
43
+ const onSubmit = (e) => {
44
+ e?.preventDefault?.()
45
+ emit('submit', { ...toRaw(props.model) }, e)
46
+ }
47
+
48
+ const onReset = (e) => {
49
+ e?.preventDefault?.()
50
+ emit('reset')
51
+ }
52
+
53
+ const onCancel = (e) => {
54
+ e?.preventDefault?.()
55
+ emit('cancel')
56
+ }
57
+
58
+ const gridRef = ref()
59
+
60
+ const cols = ref()
61
+ const { width } = useElementSize(useCurrentElement())
62
+ debouncedWatch([gridRef, width], () => {
63
+ cols.value = undefined
64
+ setTimeout(() => {
65
+ cols.value = gridRef.value?.responsiveCols || undefined
66
+ }, 30)
67
+ }, { immediate: true, debounce: 100 })
68
+
69
+ return () => {
70
+ const { items, loading, validation, showColon, showAction, actionAlign, submitText, submitDisabled, resetText, tooltipPlacement, showFeedback: _showFeedback,
71
+ labelWidth = '7.2em', labelAlign = props.labelPlacement === 'top' ? 'left' : 'right', grid, succeeded, successText = submitText, ...formProps } = props
72
+
73
+ const showFeedback = !props.readonly && _showFeedback !== false
74
+ return (
75
+ <NForm
76
+ labelWidth={labelWidth}
77
+ labelAlign={labelAlign}
78
+ onReset={onReset}
79
+ onSubmit={onSubmit}
80
+ showFeedback={showFeedback}
81
+ {...formProps}
82
+ >
83
+ <NGrid
84
+ ref={gridRef}
85
+ itemResponsive
86
+ {...grid}
87
+ yGap={showFeedback ? 0 : (grid?.yGap ?? 24)}
88
+ >
89
+ {{ default: () => {
90
+ let spans = 0
91
+ return (
92
+ <>
93
+ {
94
+ items.map(({
95
+ hidden, name, render, label, showColon, span = 6, rowSpan, offset = 0, tooltip, tooltipPlacement = props.tooltipPlacement,
96
+ validationStatus = validation[name]?.errors?.some(it => it !== undefined)
97
+ ? 'error'
98
+ : (validation[name]?.warnings?.some(it => it !== undefined)
99
+ ? 'warnings'
100
+ : (validation[name] ? 'success' : undefined)),
101
+ readonly = props.readonly,
102
+ showRequireMark = !readonly,
103
+ showTooltipWhenReadonly = false,
104
+ ...itemProps
105
+ }) => {
106
+ if (hidden) return
107
+ spans += span
108
+ let content
109
+ if (name[0] === '$') {
110
+ content = render({})
111
+ } else {
112
+ content = (
113
+ <NFormItem
114
+ path={name}
115
+ validationStatus={validationStatus}
116
+ showRequireMark={itemProps.required && showRequireMark}
117
+ {...itemProps}
118
+ >
119
+ {{
120
+ label: () => (
121
+ <NText depth={props.readonly ? 3 : 2} style="display: inline-flex; align-items: flex-start; gap: 1px">
122
+ <span>{toValue(label)}</span>
123
+ {tooltipPlacement === 'icon'
124
+ ? (
125
+ <NTooltip>
126
+ {{
127
+ default: () => toValue(tooltip),
128
+ trigger: () => (
129
+ <NButton
130
+ text
131
+ style="font-size: 1.25em; opacity: 0.8"
132
+ >
133
+ <NIcon>
134
+ <IHelp />
135
+ </NIcon>
136
+ </NButton>
137
+ ),
138
+ }}
139
+ </NTooltip>
140
+ )
141
+ : undefined}
142
+ {props.showColon && showColon !== false
143
+ ? <span style="place-self: center">:</span>
144
+ : undefined}
145
+ </NText>
146
+ ),
147
+ default: () => {
148
+ const vnode = (
149
+ <div style="width: 100%; font-size: calc(1rem - 2px); min-height: 32px; display: flex; align-items: center">
150
+ {render({ disabled: props.disabled, size: props.size, readonly: props.readonly })}
151
+ </div>
152
+ )
153
+ const showTooltip = tooltip && tooltipPlacement === 'bottom' && (!props.readonly || showTooltipWhenReadonly)
154
+
155
+ return showTooltip
156
+ ? (
157
+ <div
158
+ style="width: 100%; display: flex; flex-direction: column"
159
+ >
160
+ {vnode}
161
+ <NText depth={3} style="font-size: calc(1rem - 3px); margin-top: 6px">{toValue(tooltip)}</NText>
162
+ </div>
163
+ )
164
+ : vnode
165
+ },
166
+ feedback: () => {
167
+ return validation[name]?.errors[0] ?? validation[name]?.warnings[0]
168
+ },
169
+ }}
170
+ </NFormItem>
171
+ )
172
+ }
173
+
174
+ if (props.grid === false) {
175
+ return content
176
+ }
177
+
178
+ return (
179
+ <NGi
180
+ key={name}
181
+ offset={offset}
182
+ span={span}
183
+ style={rowSpan ? { gridRowEnd: `span ${rowSpan}` } : undefined}
184
+ >
185
+ {content}
186
+ </NGi>
187
+ )
188
+ })
189
+ }
190
+
191
+ { showAction === false || (props.readonly === true && !slots.action)
192
+ ? undefined
193
+ : (
194
+ <NGi
195
+ key="action"
196
+ span={Number.MAX_SAFE_INTEGER}
197
+ {
198
+ ...(typeof props.showAction === 'object' ? props.showAction : {})
199
+ }
200
+ >
201
+ {{
202
+ default: ({ overflow }) => {
203
+ if (slots.action) return slots.action({ cols: cols.value, spans, overflow })
204
+
205
+ return (
206
+ <NFormItem
207
+ label={props.actionAlign === 'start' ? ' ' : undefined}
208
+ showLabel={props.labelPlacement !== 'top'}
209
+ style="padding-top: 16px"
210
+ >
211
+ <NFlex justify={props.actionAlign} align="center">
212
+ {
213
+ props.showSubmitBtn === false
214
+ ? undefined
215
+ : (
216
+ <NButton attrType="submit" type={succeeded ? 'success' : 'primary'} disabled={succeeded || props.disabled || props.submitDisabled || loading} loading={loading}>
217
+ {{
218
+ default: () => (succeeded ? successText : submitText) || t('common.page.form.submitText'),
219
+ icon: () => succeeded ? <NIcon><ICheck /></NIcon> : undefined,
220
+ }}
221
+ </NButton>
222
+ )
223
+ }
224
+ {
225
+ props.showResetBtn === false
226
+ ? undefined
227
+ : (
228
+ <NButton
229
+ attrType="reset"
230
+ disabled={props.disabled || loading}
231
+ type={props.showCancelBtn ? 'primary' : 'default'}
232
+ secondary={props.showCancelBtn}
233
+ >
234
+ {props.resetText || t('common.page.form.resetText') }
235
+ </NButton>
236
+ )
237
+ }
238
+ {
239
+ props.showCancelBtn === false
240
+ ? undefined
241
+ : (
242
+ <NButton attrType="button" disabled={props.disabled || loading} onClick={onCancel}>
243
+ {props.cancelText || t('common.page.form.cancelText') }
244
+ </NButton>
245
+ )
246
+ }
247
+ </NFlex>
248
+ </NFormItem>
249
+ )
250
+ },
251
+ }}
252
+ </NGi>
253
+ )}
254
+
255
+ </>
256
+ )
257
+ } }}
258
+
259
+ </NGrid>
260
+ </NForm>
261
+ )
262
+ }
263
+ },
264
+ })
@@ -0,0 +1,121 @@
1
+ import { NButton, NIcon, NInput } from 'ithinkdt-ui'
2
+ import { defineComponent, toRef, toValue, watch } from 'vue'
3
+
4
+ import { useFormModal } from '@ithinkdt/page'
5
+
6
+ import { useI18n } from '../use-i18n.js'
7
+
8
+ import { ILanguage } from './assets.jsx'
9
+
10
+ export function useLocaleEdit(title, onSubmit, defaultRows = 1) {
11
+ const { t } = useI18n()
12
+
13
+ const readonly = ref(false)
14
+ let supports = []
15
+ const { open, reinit } = useFormModal({
16
+ title,
17
+ showColon: true,
18
+ submitText: t('common.confirm.defaultOk'),
19
+ items: ({ it }) => {
20
+ return supports.map((s) => {
21
+ return it(s.value, s.label, 'input', {
22
+ span: 24,
23
+ required: s.required,
24
+ inputProps: {
25
+ readonly,
26
+ clearable: true,
27
+ type: 'textarea',
28
+ showCount: true,
29
+ autosize: {
30
+ minRows: unref(defaultRows),
31
+ maxRows: Math.max(unref(defaultRows), 5),
32
+ },
33
+ },
34
+ })
35
+ })
36
+ },
37
+ onSubmit,
38
+ })
39
+
40
+ return {
41
+ open: (data, readonly0 = false) => {
42
+ readonly.value = readonly0
43
+ return open(data)
44
+ },
45
+ setSupports: (supports0) => {
46
+ supports = supports0
47
+ reinit()
48
+ },
49
+ }
50
+ }
51
+
52
+ export const DataLocaleInput = /* @__PURE__ */ defineComponent({
53
+ name: 'DataLocaleInput',
54
+ props: {
55
+ label: [String, Object, Function, Number, Boolean],
56
+ modelValue: Object,
57
+ supports: { type: Array, default: () => [] },
58
+ disabled: { type: Boolean, default: undefined },
59
+ defaultLang: { type: String, default: 'zh-CN' },
60
+ showLang: { type: String, default: undefined },
61
+ defaultRows: { type: Number, default: 1 },
62
+ },
63
+ emits: ['update:modelValue', 'updateModelValue'],
64
+ setup(props, { emit }) {
65
+ const onUpdateValue = (value) => {
66
+ value = {
67
+ ...props.modelValue,
68
+ [props.showLang ?? props.defaultLang]: value,
69
+ }
70
+ emit('update:modelValue', value)
71
+ emit('updateModelValue', value)
72
+ }
73
+
74
+ const { open, setSupports } = useLocaleEdit(
75
+ computed(() => toValue(props.label)),
76
+ (data) => {
77
+ emit('update:modelValue', data)
78
+ emit('updateModelValue', data)
79
+ },
80
+ toRef(props, 'defaultRows'),
81
+ )
82
+
83
+ watch(() => props.supports, setSupports, { immediate: true })
84
+
85
+ const slots = {
86
+ suffix: () => (
87
+ <NButton
88
+ quaternary
89
+ onClick={() => open(props.modelValue, props.disabled)}
90
+ style="--n-padding: 0 8px"
91
+ >
92
+ <NIcon size="20" depth="3">
93
+ <ILanguage />
94
+ </NIcon>
95
+ </NButton>
96
+ ),
97
+ }
98
+ const themeOverrides = {
99
+ '--n-padding-right': '0',
100
+ }
101
+
102
+ return () => {
103
+ return (
104
+ <NInput
105
+ value={
106
+ props.modelValue?.[props.showLang ?? props.defaultLang]
107
+ ?? props.modelValue?.[props.defaultLang]
108
+ }
109
+ onUpdateValue={onUpdateValue}
110
+ disabled={props.disabled}
111
+ clearable
112
+ style={themeOverrides}
113
+ type={props.defaultRows > 1 ? 'textarea' : 'text'}
114
+ rows={props.defaultRows}
115
+ >
116
+ {slots}
117
+ </NInput>
118
+ )
119
+ }
120
+ },
121
+ })
@@ -0,0 +1,62 @@
1
+ import { NPagination } from 'ithinkdt-ui'
2
+ import { defineComponent } from 'vue'
3
+
4
+ import { useI18n } from '../use-i18n.js'
5
+
6
+ export const DataPagination = /* @__PURE__ */ defineComponent({
7
+ name: 'DataPagination',
8
+ props: {
9
+ total: {
10
+ type: Number,
11
+ default: 0,
12
+ },
13
+ currentPage: {
14
+ type: Number,
15
+ },
16
+ pageSize: {
17
+ type: Number,
18
+ },
19
+ page: {
20
+ type: Object,
21
+ },
22
+ pageSizes: {
23
+ type: Array,
24
+ default: () => [10, 20, 30, 50],
25
+ },
26
+ },
27
+ emits: {
28
+ change: () => true,
29
+ },
30
+ setup(props, { emit }) {
31
+ const { t } = useI18n()
32
+
33
+ const onUpdatePage = page => emit('change', {
34
+ pageSize: props.pageSize ?? props.page?.pageSize ?? 0,
35
+ currentPage: page,
36
+ })
37
+ const onUpdatePageSize = pageSize => emit('change', {
38
+ pageSize,
39
+ currentPage: props.currentPage ?? props.page?.currentPage ?? 0,
40
+ })
41
+ return () => {
42
+ return (
43
+ <NPagination
44
+ page={props.currentPage ?? props.page?.currentPage}
45
+ itemCount={props.total}
46
+ pageSize={props.pageSize ?? props.page?.pageSize}
47
+ onUpdatePage={onUpdatePage}
48
+ onUpdatePageSize={onUpdatePageSize}
49
+ pageSizes={props.pageSizes}
50
+ showQuickJumper
51
+ showSizePicker
52
+ style="justify-content: flex-end"
53
+ >
54
+ {{
55
+ prefix: () => t('common.page.pagination.prefix', { total: props.total }),
56
+ suffix: () => t('common.page.pagination.suffix'),
57
+ }}
58
+ </NPagination>
59
+ )
60
+ }
61
+ },
62
+ })
@@ -0,0 +1,57 @@
1
+ import { NButton, NFlex } from 'ithinkdt-ui'
2
+ import { defineComponent } from 'vue'
3
+
4
+ import { useI18n } from '../use-i18n.js'
5
+
6
+ export const DataSelection = /* @__PURE__ */ defineComponent({
7
+ name: 'DataSelection',
8
+ props: {
9
+ modelValue: {
10
+ type: String,
11
+ required: true,
12
+ },
13
+ count: {
14
+ type: Number,
15
+ default: 0,
16
+ },
17
+ },
18
+ emits: {
19
+ 'update:modelValue': () => true,
20
+ 'clear': () => true,
21
+ },
22
+ setup(props, { emit }) {
23
+ const { t } = useI18n()
24
+
25
+ return () => {
26
+ if (props.modelValue !== 'selection' && props.count === 0) return <div />
27
+
28
+ return (
29
+ <div>
30
+ <NFlex align="center" wrap-item={false}>
31
+ <span>
32
+ {t('common.page.selection.countText', { count: props.count }) }
33
+ </span>
34
+ <NButton
35
+ text
36
+ type="primary"
37
+ onClick={() => {
38
+ emit('update:modelValue', props.modelValue === 'all' ? 'selection' : 'all')
39
+ }}
40
+ >
41
+ {props.modelValue === 'all' ? t('common.page.selection.view') : t('common.page.selection.back') }
42
+ </NButton>
43
+ <NButton
44
+ text
45
+ onClick={() => {
46
+ emit('clear')
47
+ emit('update:modelValue', 'all')
48
+ }}
49
+ >
50
+ {t('common.page.selection.clear') }
51
+ </NButton>
52
+ </NFlex>
53
+ </div>
54
+ )
55
+ }
56
+ },
57
+ })