@saasmakers/ui 0.1.35 → 0.1.37

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,141 @@
1
+ <script lang="ts" setup>
2
+ import type { BaseIcon } from '../../types/bases'
3
+ import { NuxtLinkLocale } from '#components'
4
+ import { getIcon } from '../../composables/useIcons'
5
+
6
+ const props = withDefaults(defineProps<BaseIcon>(), {
7
+ bold: false,
8
+ clickable: false,
9
+ color: undefined,
10
+ confirmation: false,
11
+ icon: undefined,
12
+ loading: false,
13
+ reverse: false,
14
+ size: 'base',
15
+ status: undefined,
16
+ text: '',
17
+ to: undefined,
18
+ truncate: false,
19
+ underline: false,
20
+ uppercase: true,
21
+ })
22
+
23
+ const emit = defineEmits<{
24
+ click: [event: MouseEvent]
25
+ confirm: [event: MouseEvent]
26
+ }>()
27
+
28
+ const confirming = ref(false)
29
+
30
+ const { t } = useI18n()
31
+
32
+ const statusIcon = computed((): string | undefined => {
33
+ switch (props.status) {
34
+ case 'error':
35
+ return getIcon('closeCircle')
36
+
37
+ case 'info':
38
+ return getIcon('infoCircle')
39
+
40
+ case 'success':
41
+ return getIcon('checkCircle')
42
+
43
+ case 'warning':
44
+ return getIcon('exclamationCircle')
45
+
46
+ default:
47
+ return undefined
48
+ }
49
+ })
50
+
51
+ const statusColor = computed((): BaseColor | undefined => {
52
+ if (props.status === 'error') {
53
+ return 'red'
54
+ }
55
+ else if (props.status === 'info') {
56
+ return 'indigo'
57
+ }
58
+ else if (props.status === 'success') {
59
+ return 'green'
60
+ }
61
+ else if (props.status === 'warning') {
62
+ return 'orange'
63
+ }
64
+ })
65
+
66
+ const finalIcon = computed(() => {
67
+ return statusIcon.value || props.icon
68
+ })
69
+
70
+ const finalColor = computed(() => {
71
+ return statusColor.value || props.color
72
+ })
73
+
74
+ function onClick(event: MouseEvent) {
75
+ if (props.confirmation) {
76
+ if (confirming.value) {
77
+ emit('confirm', event)
78
+ }
79
+ else {
80
+ setTimeout(() => (confirming.value = false), 3 * 1000)
81
+ }
82
+
83
+ confirming.value = !confirming.value
84
+ }
85
+ else {
86
+ emit('confirm', event)
87
+ }
88
+
89
+ emit('click', event)
90
+ }
91
+ </script>
92
+
93
+ <template>
94
+ <div
95
+ class="flex items-center"
96
+ :class="{
97
+ 'cursor-pointer hover:underline hover:text-gray-900 dark:hover:text-gray-100': clickable || to,
98
+ 'flex-row': !reverse,
99
+ 'flex-row-reverse': reverse,
100
+ }"
101
+ @click="onClick"
102
+ >
103
+ <component
104
+ :is="to ? NuxtLinkLocale : 'span'"
105
+ v-if="finalIcon && !loading"
106
+ class="flex items-center justify-center"
107
+ :class="{
108
+ 'text-gray-900 dark:text-gray-100': finalColor === 'black',
109
+ 'text-green-600 dark:text-green-400': finalColor === 'green',
110
+ 'text-gray-600 dark:text-gray-400': finalColor === 'gray',
111
+ 'text-indigo-600 dark:text-indigo-400': finalColor === 'indigo',
112
+ 'text-orange-600 dark:text-orange-400': finalColor === 'orange',
113
+ 'text-red-600 dark:text-red-400': finalColor === 'red',
114
+ 'text-gray-100 dark:text-gray-900': finalColor === 'white',
115
+ }"
116
+ :to="to"
117
+ >
118
+ <Icon :name="finalIcon" />
119
+ </component>
120
+
121
+ <BaseSpinner
122
+ v-else-if="loading"
123
+ :color="color"
124
+ :size="size"
125
+ />
126
+
127
+ <BaseText
128
+ v-if="text"
129
+ :bold="bold"
130
+ class="flex-1"
131
+ :has-margin="!!finalIcon || loading"
132
+ no-wrap
133
+ :reverse="reverse"
134
+ :size="size"
135
+ :text="confirming ? t('globals.confirm') : text"
136
+ :truncate="truncate"
137
+ :underline="underline"
138
+ :uppercase="uppercase"
139
+ />
140
+ </div>
141
+ </template>
@@ -0,0 +1,100 @@
1
+ <script lang="ts" setup>
2
+ import type { BaseSpinner } from '../../types/bases'
3
+
4
+ const props = withDefaults(defineProps<BaseSpinner>(), {
5
+ clickable: false,
6
+ color: 'black',
7
+ id: '',
8
+ reverse: false,
9
+ size: 'base',
10
+ text: '',
11
+ uppercase: true,
12
+ })
13
+
14
+ const emit = defineEmits<{
15
+ click: [event: MouseEvent, id: string]
16
+ }>()
17
+
18
+ function onClick(event: MouseEvent) {
19
+ emit('click', event, props.id)
20
+ }
21
+ </script>
22
+
23
+ <template>
24
+ <div
25
+ class="flex items-center"
26
+ :class="{
27
+ 'cursor-pointer': clickable,
28
+ 'flex-row': !reverse,
29
+ 'flex-row-reverse': reverse,
30
+ }"
31
+ @click="onClick"
32
+ >
33
+ <div
34
+ class="relative inline-block cursor-wait flex-initial"
35
+ :class="{
36
+ 'h-2 w-2': size === '3xs',
37
+ 'h-3 w-3': size === '2xs',
38
+ 'h-3.5 w-3.5': size === 'xs',
39
+ 'h-4 w-4': size === 'sm',
40
+ 'h-4.5 w-4.5': size === 'base',
41
+ 'h-5 w-5': size === 'lg',
42
+ 'h-6 w-6': size === 'xl',
43
+ 'h-8 w-8': size === '2xl',
44
+ 'h-10 w-10': size === '3xl',
45
+ 'h-12 w-12': size === '4xl',
46
+ }"
47
+ @click="onClick"
48
+ >
49
+ <div
50
+ v-for="wave in 2"
51
+ :key="wave"
52
+ class="base-spinner__wave absolute left-0 top-0 h-full w-full rounded-full opacity-75"
53
+ :class="{
54
+ 'base-spinner__wave--delayed': wave === 2,
55
+
56
+ 'bg-gray-900 dark:bg-gray-100': color === 'black' || !color,
57
+ 'bg-gray-700 dark:bg-gray-300': color === 'gray',
58
+ 'bg-green-700 dark:bg-green-300': color === 'green',
59
+ 'bg-indigo-700 dark:bg-indigo-300': color === 'indigo',
60
+ 'bg-orange-700 dark:bg-orange-300': color === 'orange',
61
+ 'bg-red-700 dark:bg-red-300': color === 'red',
62
+ 'bg-white dark:bg-gray-900': color === 'white',
63
+ }"
64
+ />
65
+ </div>
66
+
67
+ <BaseText
68
+ v-if="text"
69
+ class="flex-1"
70
+ has-margin
71
+ :reverse="reverse"
72
+ :size="size"
73
+ :text="text"
74
+ :uppercase="uppercase"
75
+ />
76
+ </div>
77
+ </template>
78
+
79
+ <style>
80
+ .base-spinner__wave {
81
+ animation: bounce 2s infinite linear;
82
+ }
83
+
84
+ .base-spinner__wave--delayed {
85
+ animation-delay: -1s;
86
+ }
87
+
88
+ @keyframes bounce {
89
+ 0%,
90
+ 100% {
91
+ -webkit-transform: scale(0);
92
+ transform: scale(0);
93
+ }
94
+
95
+ 50% {
96
+ -webkit-transform: scale(1);
97
+ transform: scale(1);
98
+ }
99
+ }
100
+ </style>
@@ -0,0 +1,21 @@
1
+ // Important: Only use icons from the following packs
2
+ // - Hugeicons (brands and social medias)
3
+ // -> https://icones.js.org/collection/hugeicons
4
+ // - Solar (general UI elements)
5
+ // -> https://icones.js.org/collection/solar
6
+ // Material Design Icons (brands)
7
+ // -> https://icones.js.org/collection/mdi
8
+ // Custom icons
9
+ // -> ./assets/icons
10
+
11
+ const icons = {
12
+ checkCircle: 'hugeicons:checkmark-circle-02',
13
+ closeCircle: 'hugeicons:cancel-circle',
14
+ default: 'hugeicons:help-circle',
15
+ exclamationCircle: 'hugeicons:alert-circle',
16
+ infoCircle: 'hugeicons:information-circle',
17
+ } as const
18
+
19
+ export function getIcon(attribute: keyof typeof icons) {
20
+ return icons[attribute] || icons.default
21
+ }
@@ -36,6 +36,33 @@ export type BaseDividerBorderStyle = 'dashed' | 'dotted' | 'solid'
36
36
 
37
37
  export type BaseDividerSize = 'base' | 'sm'
38
38
 
39
+ export interface BaseIcon {
40
+ bold?: boolean
41
+ clickable?: boolean
42
+ color?: BaseColor
43
+ confirmation?: boolean
44
+ icon?: string
45
+ loading?: boolean
46
+ reverse?: boolean
47
+ size?: BaseSize
48
+ status?: BaseStatus
49
+ text?: BaseTextText
50
+ to?: RouteLocationRaw
51
+ truncate?: boolean
52
+ underline?: boolean
53
+ uppercase?: boolean
54
+ }
55
+
56
+ export interface BaseSpinner {
57
+ clickable?: boolean
58
+ color?: BaseColor
59
+ id?: string
60
+ reverse?: boolean
61
+ size?: BaseSize
62
+ text?: BaseTextText
63
+ uppercase?: boolean
64
+ }
65
+
39
66
  export interface BaseText {
40
67
  background?: BaseTextBackground
41
68
  bold?: boolean
@@ -13,6 +13,8 @@ declare global {
13
13
  type BaseDivider = Bases.BaseDivider
14
14
  type BaseDividerBorderStyle = Bases.BaseDividerBorderStyle
15
15
  type BaseDividerSize = Bases.BaseDividerSize
16
+ type BaseSpinner = Bases.BaseSpinner
17
+ type BaseIcon = Bases.BaseIcon
16
18
  type BaseText = Bases.BaseText
17
19
  type BaseTextBackground = Bases.BaseTextBackground
18
20
  type BaseTextText = Bases.BaseTextText
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@saasmakers/ui",
3
3
  "type": "module",
4
- "version": "0.1.35",
4
+ "version": "0.1.37",
5
5
  "private": false,
6
6
  "description": "Reusable Nuxt UI components for SaaS Makers projects",
7
7
  "license": "MIT",