@redseed/redseed-ui-vue3 2.1.0 → 2.2.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.
package/index.js CHANGED
@@ -4,6 +4,7 @@ export * from './src/components/Button'
4
4
  export * from './src/components/ButtonGroup'
5
5
  export * from './src/components/Card'
6
6
  export * from './src/components/DropdownMenu'
7
+ export * from './src/components/Empty'
7
8
  export * from './src/components/Form'
8
9
  export * from './src/components/FormField'
9
10
  export * from './src/components/Image'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@redseed/redseed-ui-vue3",
3
- "version": "2.1.0",
3
+ "version": "2.2.0",
4
4
  "description": "RedSeed UI Vue 3 components",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -0,0 +1,110 @@
1
+ <script setup>
2
+ import { ref, computed, onMounted, onUnmounted } from 'vue'
3
+ import ButtonPrimary from '../Button/ButtonPrimary.vue'
4
+ import ButtonSecondary from '../Button/ButtonSecondary.vue'
5
+ import ButtonTertiary from '../Button/ButtonTertiary.vue'
6
+ import BodyText from '../BodyText/BodyText.vue'
7
+ import { ExclamationCircleIcon } from '@heroicons/vue/24/outline'
8
+
9
+ const emit = defineEmits(['clickPrimaryAction', 'clickSecondaryAction', 'clickTertiaryAction'])
10
+
11
+ const emptyClass = computed(() => [
12
+ 'rsui-empty',
13
+ ])
14
+
15
+ const emptyElement = ref(null)
16
+
17
+ const isWide = ref(false)
18
+
19
+ function calculateWidth() {
20
+ if (!emptyElement.value) return
21
+
22
+ const width = emptyElement.value.offsetWidth
23
+
24
+ isWide.value = width >= 480
25
+ if (isWide.value) {
26
+ emptyElement.value.classList.add('rsui-empty--wide')
27
+ } else {
28
+ emptyElement.value.classList.remove('rsui-empty--wide')
29
+ }
30
+ }
31
+
32
+ onMounted(() => {
33
+ calculateWidth()
34
+ window.addEventListener('resize', calculateWidth)
35
+ })
36
+
37
+ onUnmounted(() => window.addEventListener('resize', calculateWidth))
38
+ </script>
39
+ <template>
40
+ <div v-if="$slots.title || $slots.default"
41
+ ref="emptyElement"
42
+ :class="emptyClass"
43
+ >
44
+ <div class="rsui-empty__image">
45
+ <slot name="image">
46
+ <ExclamationCircleIcon></ExclamationCircleIcon>
47
+ </slot>
48
+ </div>
49
+ <div v-if="$slots.title"
50
+ class="rsui-empty__title"
51
+ >
52
+ <slot name="title"></slot>
53
+ </div>
54
+ <BodyText v-if="$slots.default"
55
+ class="rsui-empty__description"
56
+ >
57
+ <slot></slot>
58
+ </BodyText>
59
+ <div v-if="$slots['primary-action-label'] || $slots['secondary-action-label'] || $slots['tertiary-action-label']"
60
+ class="rsui-empty__action"
61
+ >
62
+ <ButtonPrimary sm :full="!isWide"
63
+ v-if="$slots['primary-action-label']"
64
+ @click="$emit('clickPrimaryAction')"
65
+ >
66
+ <slot name="primary-action-label"></slot>
67
+ </ButtonPrimary>
68
+ <ButtonSecondary sm :full="!isWide"
69
+ v-if="$slots['secondary-action-label']"
70
+ @click="$emit('clickSecondaryAction')"
71
+ >
72
+ <slot name="secondary-action-label"></slot>
73
+ </ButtonSecondary>
74
+ <ButtonTertiary sm :full="!isWide"
75
+ v-if="$slots['tertiary-action-label']"
76
+ @click="$emit('clickTertiaryAction')"
77
+ >
78
+ <slot name="tertiary-action-label"></slot>
79
+ </ButtonTertiary>
80
+ </div>
81
+ </div>
82
+ </template>
83
+ <style lang="scss" scoped>
84
+ .rsui-empty {
85
+ @apply w-full flex flex-col items-center justify-center gap-5;
86
+ @apply px-3 py-4 rounded-md bg-white text-rsui-default;
87
+ &--wide {
88
+ .rsui-empty__image {
89
+ :deep(svg) {
90
+ @apply size-14;
91
+ }
92
+ }
93
+ }
94
+ &__image {
95
+ @apply w-full flex items-center justify-center;
96
+ :deep(svg) {
97
+ @apply size-11;
98
+ }
99
+ }
100
+ &__title {
101
+ @apply text-lg font-semibold text-center;
102
+ }
103
+ &__description {
104
+ @apply text-sm text-center *:mb-2;
105
+ }
106
+ &__action {
107
+ @apply w-full flex flex-wrap items-center justify-center gap-2;
108
+ }
109
+ }
110
+ </style>
@@ -0,0 +1,5 @@
1
+ import Empty from './Empty.vue'
2
+
3
+ export {
4
+ Empty,
5
+ }
@@ -1,6 +1,7 @@
1
1
  <script setup>
2
2
  import { ref, computed } from 'vue'
3
3
  import ListControl from './ListControl.vue'
4
+ import Empty from '../Empty/Empty.vue'
4
5
 
5
6
  defineOptions({
6
7
  inheritAttrs: false,
@@ -17,13 +18,17 @@ const props = defineProps({
17
18
  },
18
19
  })
19
20
 
20
- const emit = defineEmits(['change'])
21
+ const emit = defineEmits(['change', 'clickEmptyAction'])
21
22
 
22
23
  const controlApplied = ref(false)
23
24
 
24
25
  const showControl = computed(() => props.control && (controlApplied.value || props.totalItems > 0))
25
26
 
26
- const showEmptyMessage = computed(() => !props.totalItems)
27
+ const showEmptyMessage = computed(() => !props.totalItems && !controlApplied.value)
28
+
29
+ const showNotFoundMessage = computed(() => !props.totalItems && controlApplied.value)
30
+
31
+ const showItems = computed(() => props.totalItems > 0)
27
32
 
28
33
  function controlChanged(event) {
29
34
  controlApplied.value = true
@@ -46,7 +51,7 @@ function controlChanged(event) {
46
51
  <slot name="sort-desc-label"></slot>
47
52
  </template>
48
53
  </ListControl>
49
- <div v-if="!showEmptyMessage"
54
+ <div v-if="showItems"
50
55
  class="rsui-list__items"
51
56
  >
52
57
  <slot></slot>
@@ -54,7 +59,26 @@ function controlChanged(event) {
54
59
  <div v-if="showEmptyMessage"
55
60
  class="rsui-list__empty"
56
61
  >
57
- <slot name="empty">No items found.</slot>
62
+ <Empty @clickPrimaryAction="$emit('clickEmptyAction')">
63
+ <template #image>
64
+ <slot name="empty-image"></slot>
65
+ </template>
66
+ <template #title v-if="$slots['empty-title']">
67
+ <slot name="empty-title"></slot>
68
+ </template>
69
+ <template #primary-action-label v-if="$slots['empty-action-label']">
70
+ <slot name="empty-action-label"></slot>
71
+ </template>
72
+
73
+ <slot name="empty-description">It looks like there's nothing here yet.</slot>
74
+ </Empty>
75
+ </div>
76
+ <div v-if="showNotFoundMessage"
77
+ class="rsui-list__empty"
78
+ >
79
+ <Empty>
80
+ <slot name="filter-empty-description">No items meet your filter criteria.</slot>
81
+ </Empty>
58
82
  </div>
59
83
  </div>
60
84
  </template>