@indielayer/ui 1.14.5 → 1.15.1
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/docs/pages/component/avatar/usage.vue +1 -1
- package/docs/pages/component/input/usage.vue +22 -8
- package/docs/pages/component/table/selectable.vue +1 -1
- package/docs/pages/component/table/virtual.vue +2 -1
- package/docs/pages/component/tag/usage.vue +1 -1
- package/docs/pages/component/textarea/usage.vue +22 -8
- package/lib/components/avatar/Avatar.vue2.js +20 -19
- package/lib/components/avatar/theme/Avatar.base.theme.js +9 -12
- package/lib/components/datepicker/Datepicker.vue.js +1 -1
- package/lib/components/drawer/Drawer.vue.js +66 -60
- package/lib/components/input/Input.vue.d.ts +8 -0
- package/lib/components/input/Input.vue.js +84 -69
- package/lib/components/inputFooter/InputFooter.vue.d.ts +13 -2
- package/lib/components/inputFooter/InputFooter.vue.js +35 -19
- package/lib/components/inputFooter/theme/InputFooter.base.theme.js +3 -1
- package/lib/components/inputFooter/theme/InputFooter.carbon.theme.js +3 -1
- package/lib/components/popover/Popover.vue.d.ts +1 -1
- package/lib/components/select/Select.vue.d.ts +38 -10
- package/lib/components/select/Select.vue.js +210 -200
- package/lib/components/table/Table.vue.d.ts +55 -19
- package/lib/components/table/Table.vue.js +256 -214
- package/lib/components/table/TableCell.vue.d.ts +9 -0
- package/lib/components/table/TableCell.vue.js +45 -21
- package/lib/components/table/TableHeader.vue.js +14 -14
- package/lib/components/table/theme/TableCell.base.theme.js +3 -3
- package/lib/components/tag/Tag.vue.d.ts +3 -0
- package/lib/components/tag/Tag.vue.js +37 -35
- package/lib/components/textarea/Textarea.vue.d.ts +19 -3
- package/lib/components/textarea/Textarea.vue.js +102 -76
- package/lib/components/textarea/theme/Textarea.base.theme.js +2 -1
- package/lib/components/textarea/theme/Textarea.carbon.theme.js +2 -1
- package/lib/components/upload/Upload.vue.js +91 -86
- package/lib/index.js +1 -1
- package/lib/index.umd.js +4 -4
- package/lib/version.d.ts +1 -1
- package/lib/version.js +1 -1
- package/package.json +1 -1
- package/src/components/avatar/Avatar.vue +2 -2
- package/src/components/avatar/theme/Avatar.base.theme.ts +0 -5
- package/src/components/datepicker/Datepicker.vue +6 -1
- package/src/components/drawer/Drawer.vue +13 -2
- package/src/components/input/Input.vue +27 -2
- package/src/components/inputFooter/InputFooter.vue +35 -3
- package/src/components/inputFooter/theme/InputFooter.base.theme.ts +2 -0
- package/src/components/inputFooter/theme/InputFooter.carbon.theme.ts +2 -0
- package/src/components/select/Select.vue +21 -8
- package/src/components/table/Table.vue +170 -48
- package/src/components/table/TableCell.vue +23 -0
- package/src/components/table/TableHeader.vue +2 -2
- package/src/components/table/theme/TableCell.base.theme.ts +20 -11
- package/src/components/tag/Tag.vue +8 -3
- package/src/components/textarea/Textarea.vue +69 -30
- package/src/components/textarea/theme/Textarea.base.theme.ts +2 -0
- package/src/components/textarea/theme/Textarea.carbon.theme.ts +2 -0
- package/src/components/upload/Upload.vue +12 -2
- package/src/version.ts +1 -1
|
@@ -16,6 +16,9 @@ const tableCellProps = {
|
|
|
16
16
|
default: 'middle',
|
|
17
17
|
validator: (value: string) => validators.verticalAlign.includes(value as any),
|
|
18
18
|
},
|
|
19
|
+
to: [String, Object],
|
|
20
|
+
href: String,
|
|
21
|
+
target: String as PropType<'_blank' | '_self' | '_parent' | '_top'>,
|
|
19
22
|
}
|
|
20
23
|
|
|
21
24
|
export type TableCellTextAlign = typeof validators.textAlign[number]
|
|
@@ -44,6 +47,26 @@ const { styles, classes, className } = useTheme('TableCell', {}, props)
|
|
|
44
47
|
|
|
45
48
|
<template>
|
|
46
49
|
<td
|
|
50
|
+
v-if="to || href"
|
|
51
|
+
class="relative"
|
|
52
|
+
:class="className"
|
|
53
|
+
:style="[{ width: computedWidth, minWidth: computedWidth, maxWidth: computedWidth }]"
|
|
54
|
+
>
|
|
55
|
+
<component
|
|
56
|
+
:is="to ? 'router-link' : 'a'"
|
|
57
|
+
v-bind="href ? { href } : {}"
|
|
58
|
+
:target="target"
|
|
59
|
+
:to="to"
|
|
60
|
+
:style="styles"
|
|
61
|
+
:class="classes.wrapper"
|
|
62
|
+
>
|
|
63
|
+
<div :class="[truncate ? 'truncate' : '']">
|
|
64
|
+
<slot></slot>
|
|
65
|
+
</div>
|
|
66
|
+
</component>
|
|
67
|
+
</td>
|
|
68
|
+
<td
|
|
69
|
+
v-else
|
|
47
70
|
:style="[styles, { width: computedWidth, minWidth: computedWidth, maxWidth: computedWidth }]"
|
|
48
71
|
:class="[
|
|
49
72
|
'relative',
|
|
@@ -52,8 +52,8 @@ const { styles, classes, className } = useTheme('TableHeader', {}, props)
|
|
|
52
52
|
:class="[
|
|
53
53
|
classes.sortIcon,
|
|
54
54
|
textAlign === 'right' ? '-mr-4 -translate-x-4' : '-ml-4 translate-x-4',
|
|
55
|
-
[sort && [1, -1].includes(sort) ? '' : '
|
|
56
|
-
[sort !== -1 && sort !== 1 ? 'text-secondary-400 dark:text-secondary-500' : 'text-primary-
|
|
55
|
+
[sort && [1, -1].includes(sort) ? '' : 'group-hover/th:text-secondary-500 dark:group-hover/th:text-secondary-400'],
|
|
56
|
+
[sort !== -1 && sort !== 1 ? 'text-secondary-400 dark:text-secondary-500' : 'text-primary-500 dark:text-primary-400']
|
|
57
57
|
]"
|
|
58
58
|
width="24"
|
|
59
59
|
height="24"
|
|
@@ -7,17 +7,26 @@ const theme: TableCellTheme = {
|
|
|
7
7
|
|
|
8
8
|
c.push(props.dense ? 'h-9 py-0.5' : 'h-11 py-1')
|
|
9
9
|
|
|
10
|
-
if (props.
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
else
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
10
|
+
if (props.to || props.href) {
|
|
11
|
+
c.push('flex items-center')
|
|
12
|
+
|
|
13
|
+
if (props.textAlign === 'left') c.push('justify-start')
|
|
14
|
+
else if (props.textAlign === 'center') c.push('justify-center')
|
|
15
|
+
else if (props.textAlign === 'right') c.push('justify-end')
|
|
16
|
+
else if (props.textAlign === 'justify') c.push('justify-center')
|
|
17
|
+
} else {
|
|
18
|
+
if (props.textAlign === 'left') c.push('text-left')
|
|
19
|
+
else if (props.textAlign === 'center') c.push('text-center')
|
|
20
|
+
else if (props.textAlign === 'right') c.push('text-right')
|
|
21
|
+
else if (props.textAlign === 'justify') c.push('text-justify')
|
|
22
|
+
|
|
23
|
+
if (props.verticalAlign === 'baseline') c.push('align-baseline')
|
|
24
|
+
else if (props.verticalAlign === 'bottom') c.push('align-bottom')
|
|
25
|
+
else if (props.verticalAlign === 'middle') c.push('align-middle')
|
|
26
|
+
else if (props.verticalAlign === 'text-bottom') c.push('align-text-bottom')
|
|
27
|
+
else if (props.verticalAlign === 'text-top') c.push('align-text-top')
|
|
28
|
+
else if (props.verticalAlign === 'top') c.push('align-top')
|
|
29
|
+
}
|
|
21
30
|
|
|
22
31
|
if (props.truncate) c.push('truncate')
|
|
23
32
|
|
|
@@ -11,6 +11,7 @@ const tagProps = {
|
|
|
11
11
|
outlined: Boolean,
|
|
12
12
|
filled: Boolean,
|
|
13
13
|
disabled: Boolean,
|
|
14
|
+
to: [String, Object],
|
|
14
15
|
}
|
|
15
16
|
|
|
16
17
|
export type TagProps = ExtractPublicPropTypes<typeof tagProps>
|
|
@@ -27,7 +28,7 @@ export default {
|
|
|
27
28
|
</script>
|
|
28
29
|
|
|
29
30
|
<script setup lang="ts">
|
|
30
|
-
import { computed, type ExtractPublicPropTypes } from 'vue'
|
|
31
|
+
import { computed, useAttrs, type ExtractPublicPropTypes } from 'vue'
|
|
31
32
|
import { useColors } from '../../composables/useColors'
|
|
32
33
|
import { useCommon } from '../../composables/useCommon'
|
|
33
34
|
import { useTheme, type ThemeComponent } from '../../composables/useTheme'
|
|
@@ -48,12 +49,16 @@ const closeIconSize = computed(() => {
|
|
|
48
49
|
return 'sm'
|
|
49
50
|
})
|
|
50
51
|
|
|
52
|
+
const attrs = useAttrs()
|
|
53
|
+
const htmlTag = computed(() => (attrs.href ? 'a' : props.to ? 'router-link' : props.tag))
|
|
54
|
+
|
|
51
55
|
const { styles, classes, className } = useTheme('Tag', {}, props)
|
|
52
56
|
</script>
|
|
53
57
|
|
|
54
58
|
<template>
|
|
55
59
|
<component
|
|
56
|
-
:is="
|
|
60
|
+
:is="htmlTag"
|
|
61
|
+
:to="to"
|
|
57
62
|
class="text-[color:var(--x-tag-text)] dark:text-[color:var(--x-tag-dark-text)] border relative"
|
|
58
63
|
:style="styles"
|
|
59
64
|
:class="
|
|
@@ -84,7 +89,7 @@ const { styles, classes, className } = useTheme('Tag', {}, props)
|
|
|
84
89
|
:icon="closeIcon"
|
|
85
90
|
class="cursor-pointer transition-colors duration-150"
|
|
86
91
|
:class="[disabled ? 'text-secondary-400' : 'hover:text-secondary-500']"
|
|
87
|
-
@click="(e: Event) => !disabled && $emit('remove', e)"
|
|
92
|
+
@click.prevent="(e: Event) => !disabled && $emit('remove', e)"
|
|
88
93
|
/>
|
|
89
94
|
</div>
|
|
90
95
|
</span>
|
|
@@ -20,11 +20,13 @@ const textareaProps = {
|
|
|
20
20
|
preventEnter: Boolean,
|
|
21
21
|
block: Boolean,
|
|
22
22
|
resizable: Boolean,
|
|
23
|
+
showCounter: Boolean,
|
|
24
|
+
clearable: Boolean,
|
|
23
25
|
}
|
|
24
26
|
|
|
25
27
|
export type TextareaProps = ExtractPublicPropTypes<typeof textareaProps>
|
|
26
28
|
|
|
27
|
-
type InternalClasses = 'wrapper' | 'input'
|
|
29
|
+
type InternalClasses = 'wrapper' | 'input' | 'icon'
|
|
28
30
|
type InternalExtraData = { errorInternal: Ref<boolean>; }
|
|
29
31
|
|
|
30
32
|
export interface TextareaTheme extends ThemeComponent<TextareaProps, InternalClasses, InternalExtraData> {}
|
|
@@ -49,6 +51,8 @@ import { useInteractive } from '../../composables/useInteractive'
|
|
|
49
51
|
|
|
50
52
|
import XLabel from '../label/Label.vue'
|
|
51
53
|
import XInputFooter from '../inputFooter/InputFooter.vue'
|
|
54
|
+
import XIcon from '../icon/Icon.vue'
|
|
55
|
+
import { closeIcon } from '../../common/icons'
|
|
52
56
|
|
|
53
57
|
const props = defineProps(textareaProps)
|
|
54
58
|
|
|
@@ -107,6 +111,20 @@ const {
|
|
|
107
111
|
setError,
|
|
108
112
|
} = useInputtable(props, { focus, emit })
|
|
109
113
|
|
|
114
|
+
const currentLength = computed(() => {
|
|
115
|
+
const value = props.modelValue
|
|
116
|
+
|
|
117
|
+
return value ? String(value).length : 0
|
|
118
|
+
})
|
|
119
|
+
|
|
120
|
+
const showClearIcon = computed(() => props.clearable && props.modelValue !== '')
|
|
121
|
+
|
|
122
|
+
function isEmpty(value: typeof props.modelValue) {
|
|
123
|
+
if (typeof value === 'undefined' || value === null) return true
|
|
124
|
+
|
|
125
|
+
return false
|
|
126
|
+
}
|
|
127
|
+
|
|
110
128
|
const { styles, classes, className } = useTheme('Textarea', {}, props, { errorInternal })
|
|
111
129
|
|
|
112
130
|
defineExpose({ focus, blur, reset, validate, setError })
|
|
@@ -126,34 +144,55 @@ defineExpose({ focus, blur, reset, validate, setError })
|
|
|
126
144
|
]"
|
|
127
145
|
:tooltip="tooltip"
|
|
128
146
|
>
|
|
129
|
-
<
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
147
|
+
<div class="relative">
|
|
148
|
+
<slot name="prefix"></slot>
|
|
149
|
+
<textarea
|
|
150
|
+
:id="id"
|
|
151
|
+
ref="elRef"
|
|
152
|
+
class=""
|
|
153
|
+
:style="style"
|
|
154
|
+
:class="[
|
|
155
|
+
classes.input,
|
|
156
|
+
errorInternal
|
|
157
|
+
? 'border-error-500 dark:border-error-400 focus:outline-error-500'
|
|
158
|
+
: 'focus:outline-[color:var(--x-textarea-border)]',
|
|
159
|
+
]"
|
|
160
|
+
:disabled="disabled"
|
|
161
|
+
:max="max"
|
|
162
|
+
:maxlength="maxlength"
|
|
163
|
+
:min="min"
|
|
164
|
+
:dir="dir"
|
|
165
|
+
:rows="rows"
|
|
166
|
+
:minlength="minlength"
|
|
167
|
+
:name="name"
|
|
168
|
+
:placeholder="placeholder"
|
|
169
|
+
:readonly="readonly"
|
|
170
|
+
:value="isEmpty(modelValue) ? '' : String(modelValue)"
|
|
171
|
+
v-bind="dataAttrs"
|
|
172
|
+
v-on="inputListeners"
|
|
173
|
+
@keydown.enter="onEnter"
|
|
174
|
+
@input="onInput"
|
|
175
|
+
></textarea>
|
|
176
|
+
|
|
177
|
+
<slot name="suffix">
|
|
178
|
+
<x-icon
|
|
179
|
+
v-if="showClearIcon"
|
|
180
|
+
:size="size"
|
|
181
|
+
:icon="closeIcon"
|
|
182
|
+
class="right-2 cursor-pointer"
|
|
183
|
+
:class="classes.icon"
|
|
184
|
+
@click="reset()"
|
|
185
|
+
/>
|
|
186
|
+
</slot>
|
|
187
|
+
</div>
|
|
188
|
+
|
|
189
|
+
<x-input-footer
|
|
190
|
+
v-if="!hideFooterInternal"
|
|
191
|
+
:error="errorInternal"
|
|
192
|
+
:helper="helper"
|
|
193
|
+
:character-count="currentLength"
|
|
194
|
+
:max-characters="maxlength"
|
|
195
|
+
:show-counter="showCounter"
|
|
196
|
+
/>
|
|
158
197
|
</x-label>
|
|
159
198
|
</template>
|
|
@@ -52,7 +52,7 @@ export default {
|
|
|
52
52
|
</script>
|
|
53
53
|
|
|
54
54
|
<script setup lang="ts">
|
|
55
|
-
import { computed, ref, watch, type ExtractPublicPropTypes, type PropType } from 'vue'
|
|
55
|
+
import { computed, onBeforeUnmount, ref, watch, type ExtractPublicPropTypes, type PropType } from 'vue'
|
|
56
56
|
import { useDropZone } from '@vueuse/core'
|
|
57
57
|
import { useCommon } from '../../composables/useCommon'
|
|
58
58
|
import { useInteractive } from '../../composables/useInteractive'
|
|
@@ -187,10 +187,20 @@ function isImage(file: File) {
|
|
|
187
187
|
return file.type.startsWith('image') || imageExtensions.some((ext) => file.name.endsWith(ext))
|
|
188
188
|
}
|
|
189
189
|
|
|
190
|
+
const blobUrls: string[] = []
|
|
191
|
+
|
|
190
192
|
function getImagePreview(file: File) {
|
|
191
|
-
|
|
193
|
+
const url = URL.createObjectURL(file)
|
|
194
|
+
|
|
195
|
+
blobUrls.push(url)
|
|
196
|
+
|
|
197
|
+
return url
|
|
192
198
|
}
|
|
193
199
|
|
|
200
|
+
onBeforeUnmount(() => {
|
|
201
|
+
blobUrls.forEach((url) => URL.revokeObjectURL(url))
|
|
202
|
+
})
|
|
203
|
+
|
|
194
204
|
function calculateFileSize(size: number) {
|
|
195
205
|
if (size < 1024) return `${size} B`
|
|
196
206
|
if (size < 1024 * 1024) return `${(size / 1024).toFixed(2)} KB`
|
package/src/version.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export default '1.
|
|
1
|
+
export default '1.15.1'
|