@indielayer/ui 1.14.5 → 1.15.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 (56) hide show
  1. package/docs/pages/component/avatar/usage.vue +1 -1
  2. package/docs/pages/component/input/usage.vue +22 -8
  3. package/docs/pages/component/table/selectable.vue +1 -1
  4. package/docs/pages/component/table/virtual.vue +2 -1
  5. package/docs/pages/component/tag/usage.vue +1 -1
  6. package/docs/pages/component/textarea/usage.vue +22 -8
  7. package/lib/components/avatar/Avatar.vue2.js +20 -19
  8. package/lib/components/avatar/theme/Avatar.base.theme.js +9 -12
  9. package/lib/components/datepicker/Datepicker.vue.js +1 -1
  10. package/lib/components/drawer/Drawer.vue.js +66 -60
  11. package/lib/components/input/Input.vue.d.ts +8 -0
  12. package/lib/components/input/Input.vue.js +84 -69
  13. package/lib/components/inputFooter/InputFooter.vue.d.ts +13 -2
  14. package/lib/components/inputFooter/InputFooter.vue.js +35 -19
  15. package/lib/components/inputFooter/theme/InputFooter.base.theme.js +3 -1
  16. package/lib/components/inputFooter/theme/InputFooter.carbon.theme.js +3 -1
  17. package/lib/components/popover/Popover.vue.d.ts +1 -1
  18. package/lib/components/select/Select.vue.d.ts +38 -10
  19. package/lib/components/select/Select.vue.js +210 -200
  20. package/lib/components/table/Table.vue.d.ts +55 -19
  21. package/lib/components/table/Table.vue.js +256 -214
  22. package/lib/components/table/TableCell.vue.d.ts +9 -0
  23. package/lib/components/table/TableCell.vue.js +45 -21
  24. package/lib/components/table/TableHeader.vue.js +14 -14
  25. package/lib/components/table/theme/TableCell.base.theme.js +3 -3
  26. package/lib/components/tag/Tag.vue.d.ts +3 -0
  27. package/lib/components/tag/Tag.vue.js +37 -35
  28. package/lib/components/textarea/Textarea.vue.d.ts +19 -3
  29. package/lib/components/textarea/Textarea.vue.js +98 -76
  30. package/lib/components/textarea/theme/Textarea.base.theme.js +2 -1
  31. package/lib/components/textarea/theme/Textarea.carbon.theme.js +2 -1
  32. package/lib/components/upload/Upload.vue.js +91 -86
  33. package/lib/index.js +1 -1
  34. package/lib/index.umd.js +4 -4
  35. package/lib/version.d.ts +1 -1
  36. package/lib/version.js +1 -1
  37. package/package.json +1 -1
  38. package/src/components/avatar/Avatar.vue +2 -2
  39. package/src/components/avatar/theme/Avatar.base.theme.ts +0 -5
  40. package/src/components/datepicker/Datepicker.vue +6 -1
  41. package/src/components/drawer/Drawer.vue +13 -2
  42. package/src/components/input/Input.vue +27 -2
  43. package/src/components/inputFooter/InputFooter.vue +35 -3
  44. package/src/components/inputFooter/theme/InputFooter.base.theme.ts +2 -0
  45. package/src/components/inputFooter/theme/InputFooter.carbon.theme.ts +2 -0
  46. package/src/components/select/Select.vue +21 -8
  47. package/src/components/table/Table.vue +170 -48
  48. package/src/components/table/TableCell.vue +23 -0
  49. package/src/components/table/TableHeader.vue +2 -2
  50. package/src/components/table/theme/TableCell.base.theme.ts +20 -11
  51. package/src/components/tag/Tag.vue +8 -3
  52. package/src/components/textarea/Textarea.vue +63 -30
  53. package/src/components/textarea/theme/Textarea.base.theme.ts +2 -0
  54. package/src/components/textarea/theme/Textarea.carbon.theme.ts +2 -0
  55. package/src/components/upload/Upload.vue +12 -2
  56. 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) ? '' : 'invisible group-hover/th:visible'],
56
- [sort !== -1 && sort !== 1 ? 'text-secondary-400 dark:text-secondary-500' : 'text-primary-700 dark:text-primary-400']
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.textAlign === 'left') c.push('text-left')
11
- else if (props.textAlign === 'center') c.push('text-center')
12
- else if (props.textAlign === 'right') c.push('text-right')
13
- else if (props.textAlign === 'justify') c.push('text-justify')
14
-
15
- if (props.verticalAlign === 'baseline') c.push('align-baseline')
16
- else if (props.verticalAlign === 'bottom') c.push('align-bottom')
17
- else if (props.verticalAlign === 'middle') c.push('align-middle')
18
- else if (props.verticalAlign === 'text-bottom') c.push('align-text-bottom')
19
- else if (props.verticalAlign === 'text-top') c.push('align-text-top')
20
- else if (props.verticalAlign === 'top') c.push('align-top')
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="tag"
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,14 @@ 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
+
110
122
  const { styles, classes, className } = useTheme('Textarea', {}, props, { errorInternal })
111
123
 
112
124
  defineExpose({ focus, blur, reset, validate, setError })
@@ -126,34 +138,55 @@ defineExpose({ focus, blur, reset, validate, setError })
126
138
  ]"
127
139
  :tooltip="tooltip"
128
140
  >
129
- <textarea
130
- :id="id"
131
- ref="elRef"
132
- class=""
133
- :style="style"
134
- :class="[
135
- classes.input,
136
- errorInternal
137
- ? 'border-error-500 dark:border-error-400 focus:outline-error-500'
138
- : 'focus:outline-[color:var(--x-textarea-border)]',
139
- ]"
140
- :disabled="disabled"
141
- :max="max"
142
- :maxlength="maxlength"
143
- :min="min"
144
- :dir="dir"
145
- :rows="rows"
146
- :minlength="minlength"
147
- :name="name"
148
- :placeholder="placeholder"
149
- :readonly="readonly"
150
- :value="typeof modelValue !== 'undefined' ? String(modelValue) : ''"
151
- v-bind="dataAttrs"
152
- v-on="inputListeners"
153
- @keydown.enter="onEnter"
154
- @input="onInput"
155
- ></textarea>
156
-
157
- <x-input-footer v-if="!hideFooterInternal" :error="errorInternal" :helper="helper"/>
141
+ <div class="relative">
142
+ <slot name="prefix"></slot>
143
+ <textarea
144
+ :id="id"
145
+ ref="elRef"
146
+ class=""
147
+ :style="style"
148
+ :class="[
149
+ classes.input,
150
+ errorInternal
151
+ ? 'border-error-500 dark:border-error-400 focus:outline-error-500'
152
+ : 'focus:outline-[color:var(--x-textarea-border)]',
153
+ ]"
154
+ :disabled="disabled"
155
+ :max="max"
156
+ :maxlength="maxlength"
157
+ :min="min"
158
+ :dir="dir"
159
+ :rows="rows"
160
+ :minlength="minlength"
161
+ :name="name"
162
+ :placeholder="placeholder"
163
+ :readonly="readonly"
164
+ :value="typeof modelValue !== 'undefined' ? String(modelValue) : ''"
165
+ v-bind="dataAttrs"
166
+ v-on="inputListeners"
167
+ @keydown.enter="onEnter"
168
+ @input="onInput"
169
+ ></textarea>
170
+
171
+ <slot name="suffix">
172
+ <x-icon
173
+ v-if="showClearIcon"
174
+ :size="size"
175
+ :icon="closeIcon"
176
+ class="right-2 cursor-pointer"
177
+ :class="classes.icon"
178
+ @click="reset()"
179
+ />
180
+ </slot>
181
+ </div>
182
+
183
+ <x-input-footer
184
+ v-if="!hideFooterInternal"
185
+ :error="errorInternal"
186
+ :helper="helper"
187
+ :character-count="currentLength"
188
+ :max-characters="maxlength"
189
+ :show-counter="showCounter"
190
+ />
158
191
  </x-label>
159
192
  </template>
@@ -22,6 +22,8 @@ const theme: TextareaTheme = {
22
22
 
23
23
  return classes
24
24
  },
25
+
26
+ icon: 'text-secondary-600 dark:text-secondary-300 absolute my-auto inset-y-0',
25
27
  },
26
28
  }
27
29
 
@@ -23,6 +23,8 @@ const theme: TextareaTheme = {
23
23
 
24
24
  return classes
25
25
  },
26
+
27
+ icon: 'text-secondary-600 dark:text-secondary-300 absolute my-auto inset-y-0',
26
28
  },
27
29
  }
28
30
 
@@ -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
- return URL.createObjectURL(file)
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.14.5'
1
+ export default '1.15.0'