@saasmakers/ui 2.0.62 → 2.0.64

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.
@@ -215,6 +215,7 @@ function resetTurnstile() {
215
215
  full-width
216
216
  :loading="forgettingPassword"
217
217
  reverse
218
+ :size="size"
218
219
  :text="{
219
220
  sm: t('buttons.forgotPassword.sm'),
220
221
  base: t('buttons.forgotPassword.base'),
@@ -141,14 +141,23 @@ function processGoogleCallback(event: MessageEvent) {
141
141
  <img
142
142
  v-if="provider === 'apple'"
143
143
  :alt="t('appleLogo')"
144
- class="mr-2.5 w-4.5 dark:invert"
144
+ class="dark:invert"
145
+ :class="{
146
+ 'mr-2 w-4': size === 'sm',
147
+ 'mr-2.5 w-4.5': size === 'base',
148
+ 'mr-2.5 w-5': size === 'lg',
149
+ }"
145
150
  src="/images/auth/AuthSocialConnect/apple.svg"
146
151
  >
147
152
 
148
153
  <img
149
154
  v-else-if="provider === 'google'"
150
155
  :alt="t('googleLogo')"
151
- class="mr-2.5 w-5"
156
+ :class="{
157
+ 'mr-2 w-4': size === 'sm',
158
+ 'mr-2.5 w-4.5': size === 'base',
159
+ 'mr-2.5 w-5': size === 'lg',
160
+ }"
152
161
  src="/images/auth/AuthSocialConnect/google.svg"
153
162
  >
154
163
  </BaseButton>
@@ -90,7 +90,7 @@ async function onClose(event: MouseEvent) {
90
90
  :color="buttonColor"
91
91
  :icon="getLayerIcon('closeCircle')"
92
92
  light
93
- size="xs"
93
+ size="sm"
94
94
  :text="t('closeThisMessage')"
95
95
  @click="onClose"
96
96
  />
@@ -37,6 +37,20 @@ const hasFixedSize = computed(() => {
37
37
  return props.shape === 'square' || props.shape === 'circle'
38
38
  })
39
39
 
40
+ const contentSize = computed((): BaseSize => {
41
+ switch (props.size) {
42
+ case 'lg': {
43
+ return 'base'
44
+ }
45
+ case 'sm': {
46
+ return 'xs'
47
+ }
48
+ default: {
49
+ return 'sm'
50
+ }
51
+ }
52
+ })
53
+
40
54
  function onClick(event: MouseEvent) {
41
55
  if (!props.loading) {
42
56
  if (props.confirmation) {
@@ -69,12 +83,9 @@ function onClick(event: MouseEvent) {
69
83
  'shadow-sm': !light,
70
84
  'rounded-lg': shape !== 'circle',
71
85
  'rounded-full': shape === 'circle',
72
- 'h-6 w-6': size === '2xs' && hasFixedSize,
73
- 'h-8 w-8': size === 'xs' && hasFixedSize && !confirming,
74
86
  'h-10 w-10': size === 'sm' && hasFixedSize && !confirming,
75
87
  'h-12 w-12': size === 'base' && hasFixedSize && !confirming,
76
88
  'h-14 w-14': size === 'lg' && hasFixedSize && !confirming,
77
- 'h-16 w-16': size === 'xl' && hasFixedSize && !confirming,
78
89
  'border-gray-900 dark:border-gray-100 bg-gray-900 dark:bg-gray-100 text-white dark:text-black': color === 'black' && !light,
79
90
  'hover:bg-black dark:hover:bg-white hover:text-white dark:hover:text-black': color === 'black' && !light && !disabled && !loading,
80
91
  'border-gray-900 dark:border-gray-100 text-gray-900 dark:text-gray-100': color === 'black' && light,
@@ -98,12 +109,9 @@ function onClick(event: MouseEvent) {
98
109
  'border-white dark:border-gray-900 text-white dark:text-black': color === 'white' && light,
99
110
  'hover:border-black dark:hover:border-white hover:text-black dark:hover:text-white': color !== 'white' && light && !disabled && !loading,
100
111
  'hover:bg-white dark:hover:bg-gray-900 hover:text-gray-800 dark:hover:text-gray-200': color === 'white' && light && !disabled && !loading,
101
- 'h-6 px-3': size === '2xs' && (!hasFixedSize || confirming),
102
- 'h-8 px-4': size === 'xs' && (!hasFixedSize || confirming),
103
112
  'h-10 px-5': size === 'sm' && (!hasFixedSize || confirming),
104
113
  'h-12 px-6': size === 'base' && (!hasFixedSize || confirming),
105
- 'h-13 px-6.5': size === 'lg' && (!hasFixedSize || confirming),
106
- 'h-14 px-7': size === 'xl' && (!hasFixedSize || confirming),
114
+ 'h-14 px-6.5': size === 'lg' && (!hasFixedSize || confirming),
107
115
  }"
108
116
  :disabled="disabled"
109
117
  :to="to"
@@ -121,7 +129,7 @@ function onClick(event: MouseEvent) {
121
129
  :color="iconColor"
122
130
  :icon="confirming ? undefined : icon"
123
131
  :reverse="reverse"
124
- :size="size"
132
+ :size="contentSize"
125
133
  :text="confirming ? t('confirm') : text"
126
134
  />
127
135
  </span>
@@ -130,7 +138,7 @@ function onClick(event: MouseEvent) {
130
138
  v-if="loading"
131
139
  class="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2"
132
140
  :color="!background ? 'black' : light ? color : color === 'white' ? 'indigo' : 'white'"
133
- :size="size"
141
+ :size="contentSize"
134
142
  />
135
143
  </component>
136
144
  </template>
@@ -6,6 +6,7 @@ const props = withDefaults(defineProps<BaseRing>(), {
6
6
  completed: 0,
7
7
  dashed: false,
8
8
  format: 'count',
9
+ revealLabelOnHover: false,
9
10
  size: 'base',
10
11
  total: 0,
11
12
  transitionColors: false,
@@ -18,7 +19,7 @@ const emit = defineEmits<{
18
19
  const sizes = {
19
20
  base: {
20
21
  inset: 1,
21
- size: 28,
22
+ size: 30,
22
23
  strokeWidth: 3,
23
24
  },
24
25
  lg: {
@@ -26,6 +27,11 @@ const sizes = {
26
27
  size: 36,
27
28
  strokeWidth: 4,
28
29
  },
30
+ sm: {
31
+ inset: 1,
32
+ size: 24,
33
+ strokeWidth: 2.5,
34
+ },
29
35
  } as const
30
36
 
31
37
  const geometry = computed(() => {
@@ -66,28 +72,6 @@ const centerLabel = computed(() => {
66
72
  return String(clampedCompleted.value)
67
73
  })
68
74
 
69
- const progressColor = computed(() => {
70
- const progressPercentage = percentage.value
71
-
72
- if (progressPercentage === 100) {
73
- return 'var(--indigo-800)'
74
- }
75
-
76
- if (progressPercentage >= 75) {
77
- return 'var(--indigo-700)'
78
- }
79
-
80
- if (progressPercentage >= 50) {
81
- return 'var(--indigo-500)'
82
- }
83
-
84
- if (progressPercentage >= 25) {
85
- return 'var(--indigo-400)'
86
- }
87
-
88
- return 'var(--indigo-300)'
89
- })
90
-
91
75
  // Visual gap (in viewBox units) between segments, widened for fewer steps.
92
76
  function gapForTotal(total: number) {
93
77
  if (total <= 4) {
@@ -164,7 +148,7 @@ function onClick(event: MouseEvent) {
164
148
  <template>
165
149
  <component
166
150
  :is="clickable ? 'button' : 'div'"
167
- class="inline-flex"
151
+ class="group inline-flex"
168
152
  :aria-expanded="expanded"
169
153
  :aria-label="label"
170
154
  :class="{ 'cursor-pointer': clickable }"
@@ -183,14 +167,17 @@ function onClick(event: MouseEvent) {
183
167
  v-for="(arc, index) in ringArcs"
184
168
  :key="index"
185
169
  :class="{
186
- 'stroke-gray-300 dark:stroke-gray-700': !arc.filled,
170
+ 'stroke-gray-200 dark:stroke-gray-800': !arc.filled,
171
+ 'stroke-indigo-400 dark:stroke-indigo-600': arc.filled && percentage < 25,
172
+ 'stroke-indigo-500 dark:stroke-indigo-500': arc.filled && percentage >= 25 && percentage < 50,
173
+ 'stroke-indigo-600 dark:stroke-indigo-400': arc.filled && percentage >= 50 && percentage < 75,
174
+ 'stroke-indigo-700 dark:stroke-indigo-300': arc.filled && percentage >= 75,
187
175
  'transition-[stroke] duration-150 motion-reduce:transition-none': transitionColors,
188
176
  }"
189
177
  :cx="geometry.center"
190
178
  :cy="geometry.center"
191
179
  fill="none"
192
180
  :r="geometry.radius"
193
- :stroke="arc.filled ? progressColor : undefined"
194
181
  :stroke-dasharray="arc.dashArray"
195
182
  :stroke-dashoffset="arc.dashOffset"
196
183
  stroke-linecap="butt"
@@ -202,8 +189,10 @@ function onClick(event: MouseEvent) {
202
189
  v-if="centerLabel"
203
190
  class="fill-gray-600 font-bold tabular-nums dark:fill-gray-400"
204
191
  :class="{
205
- 'text-2xs': size === 'base',
192
+ 'text-2xs': size === 'base' || size === 'sm',
206
193
  'text-3xs': size === 'lg',
194
+ 'opacity-0 transition-opacity duration-150 motion-reduce:transition-none group-hover:opacity-100 group-focus-visible:opacity-100': revealLabelOnHover && !expanded,
195
+ 'opacity-100': !revealLabelOnHover || expanded,
207
196
  }"
208
197
  dominant-baseline="central"
209
198
  text-anchor="middle"
@@ -67,7 +67,6 @@ function focus() {
67
67
  }
68
68
 
69
69
  function onFieldBlur(event: FocusEvent) {
70
- // iOS keyboard paste can update the DOM without firing `input` before blur
71
70
  syncModelValueFromTarget(event.target)
72
71
 
73
72
  if (props.trim) {
@@ -86,7 +85,6 @@ function onFieldInput(event: Event) {
86
85
  }
87
86
 
88
87
  function onFieldKeyDown(event: KeyboardEvent) {
89
- // iOS keyboard paste can update the DOM without firing `input` before keydown
90
88
  syncModelValueFromTarget(event.target)
91
89
 
92
90
  const value = (event.target as HTMLInputElement).value
@@ -136,24 +134,20 @@ function syncModelValueFromTarget(target: EventTarget | null) {
136
134
  return
137
135
  }
138
136
 
139
- modelValue.value = transformFieldValue(target.value)
140
- }
141
-
142
- function transformFieldValue(value: string) {
143
- let nextValue = value
137
+ let value = target.value
144
138
 
145
- if (props.type === 'number' && props.max && Number.parseInt(nextValue) > props.max) {
146
- nextValue = props.max.toString()
139
+ if (props.type === 'number' && props.max && Number.parseInt(value) > props.max) {
140
+ value = props.max.toString()
147
141
  }
148
142
 
149
143
  if (props.slugOnly) {
150
- nextValue = nextValue.toString().toLowerCase().replace(/[^a-z0-9_-]/g, '')
144
+ value = value.toString().toLowerCase().replace(/[^a-z0-9_-]/g, '')
151
145
  }
152
146
  else if (props.lowercaseOnly) {
153
- nextValue = nextValue.toString().toLowerCase()
147
+ value = value.toString().toLowerCase()
154
148
  }
155
149
 
156
- return nextValue
150
+ modelValue.value = value
157
151
  }
158
152
 
159
153
  defineExpose({
@@ -39,7 +39,6 @@ onMounted(() => {
39
39
  })
40
40
 
41
41
  function onFieldBlur(event: FocusEvent) {
42
- // iOS keyboard paste can update the DOM without syncing v-model before blur
43
42
  syncModelValueFromTarget(event.target)
44
43
  emit('blur', event, modelValue.value || '')
45
44
  }
@@ -71,12 +71,9 @@ export interface BaseButton {
71
71
  export type BaseButtonShape = 'circle' | 'default' | 'square'
72
72
 
73
73
  export type BaseButtonSize
74
- = | '2xs'
75
- | 'base'
74
+ = | 'base'
76
75
  | 'lg'
77
76
  | 'sm'
78
- | 'xl'
79
- | 'xs'
80
77
 
81
78
  export type BaseButtonType = 'button' | 'reset' | 'submit'
82
79
 
@@ -306,6 +303,7 @@ export interface BaseRing {
306
303
  expanded?: boolean
307
304
  format?: BaseRingFormat
308
305
  label?: string
306
+ revealLabelOnHover?: boolean
309
307
  size?: BaseRingSize
310
308
  total?: number
311
309
  transitionColors?: boolean
@@ -319,7 +317,7 @@ export interface BaseRingArc {
319
317
 
320
318
  export type BaseRingFormat = 'count' | 'none' | 'percent'
321
319
 
322
- export type BaseRingSize = 'base' | 'lg'
320
+ export type BaseRingSize = 'base' | 'lg' | 'sm'
323
321
 
324
322
  export interface BaseShortcut {
325
323
  active?: boolean
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@saasmakers/ui",
3
- "version": "2.0.62",
3
+ "version": "2.0.64",
4
4
  "private": false,
5
5
  "description": "Reusable Nuxt UI components for SaaS Makers projects",
6
6
  "license": "MIT",