@saasmakers/ui 2.0.19 → 2.0.21

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.
@@ -76,7 +76,7 @@ async function onSocialConnectSuccess(payload: AuthSocialConnectSuccess) {
76
76
  <template>
77
77
  <div
78
78
  class="flex flex-col items-center"
79
- :class="{ 'rounded-lg bg-gray-100 dark:bg-gray-900 border shadow-sm border-gray-200 dark:border-gray-800 p-6 sm:p-10': hasBox }"
79
+ :class="{ 'base-box bg-gray-100 dark:bg-gray-900 p-6 sm:p-10': hasBox }"
80
80
  >
81
81
  <div class="w-full flex flex-col gap-6 sm:w-96">
82
82
  <BaseAlert
@@ -23,7 +23,7 @@ defineSlots<{
23
23
  'bg-gray-100 dark:bg-gray-900': background === 'gray',
24
24
  'bg-white dark:bg-gray-900': background === 'white',
25
25
  'border-black dark:border-white': borderColor === 'black',
26
- 'border-gray-200 dark:border-gray-800': borderColor === 'gray',
26
+ 'base-border': borderColor === 'gray',
27
27
  }"
28
28
  >
29
29
  <BaseText
@@ -56,11 +56,11 @@ function onClick(event: MouseEvent) {
56
56
  'cursor-default': !isClickable,
57
57
  'cursor-pointer': isClickable,
58
58
  'opacity-50': disabled,
59
- 'border border-gray-200 dark:border-gray-800 bg-white dark:bg-gray-900 shadow-sm p-1.5 pr-2.5': hasBackground && size === 'base' && orientation === 'horizontal',
60
- 'border border-gray-200 dark:border-gray-800 bg-white dark:bg-gray-900 shadow-sm p-2.5 pr-4': hasBackground && size === 'lg' && orientation === 'horizontal',
61
- 'border border-gray-200 dark:border-gray-800 bg-white dark:bg-gray-900 shadow-sm p-3': hasBackground && size === 'base' && orientation === 'vertical',
62
- 'border border-gray-200 dark:border-gray-800 bg-white dark:bg-gray-900 shadow-sm p-4': hasBackground && size === 'lg' && orientation === 'vertical',
63
- 'hover:border-gray-300 dark:hover:border-gray-700': hasBackground && isClickable,
59
+ 'base-surface p-1.5 pr-2.5': hasBackground && size === 'base' && orientation === 'horizontal',
60
+ 'base-surface p-2.5 pr-4': hasBackground && size === 'lg' && orientation === 'horizontal',
61
+ 'base-surface p-3': hasBackground && size === 'base' && orientation === 'vertical',
62
+ 'base-surface p-4': hasBackground && size === 'lg' && orientation === 'vertical',
63
+ 'base-border-hover': hasBackground && isClickable,
64
64
  'rounded-xl': hasBackground,
65
65
  'relative': orientation === 'vertical',
66
66
  }"
@@ -83,7 +83,7 @@ function onClick(event: MouseEvent) {
83
83
  :class="{
84
84
  'border shadow-inner': !avatar && !image,
85
85
  'rounded-lg': !avatar && !image,
86
- 'border-gray-200 dark:border-gray-800 bg-gray-100 dark:bg-gray-900': !avatar && !image,
86
+ 'base-border bg-gray-100 dark:bg-gray-900': !avatar && !image,
87
87
  'mr-2': orientation === 'horizontal' && size === 'base',
88
88
  'mr-3': orientation === 'horizontal' && size === 'lg',
89
89
  'mb-2': orientation === 'vertical' && size === 'base',
@@ -34,11 +34,11 @@ function onKeyDown(event: KeyboardEvent) {
34
34
  <span
35
35
  class="flex items-center justify-center transition"
36
36
  :class="{
37
- 'border border-gray-200 dark:border-gray-800': hasBox,
37
+ 'border base-border': hasBox,
38
38
  'bg-gray-100 dark:bg-gray-900 shadow-inner': hasBox && background === 'gray',
39
39
  'bg-white dark:bg-gray-900 shadow-sm': hasBox && background === 'white',
40
40
  'cursor-pointer hover:border-gray-400 dark:hover:border-gray-600': clickable && (!hasBox || background === 'gray'),
41
- 'cursor-pointer hover:border-gray-300 focus-visible:border-gray-400 dark:hover:border-gray-700 dark:focus-visible:border-gray-600': clickable && hasBox && background === 'white',
41
+ 'cursor-pointer base-border-interactive-focus-visible': clickable && hasBox && background === 'white',
42
42
  'rounded': ['xs'].includes(size) && hasBox,
43
43
  'rounded-md': ['sm', 'base'].includes(size) && hasBox,
44
44
  'rounded-lg': ['lg', 'xl'].includes(size) && hasBox,
@@ -17,7 +17,7 @@ defineSlots<{
17
17
  <template>
18
18
  <div
19
19
  class="flex flex-col items-center bg-gray-100 text-center text-gray-900 dark:bg-gray-900 dark:text-gray-100"
20
- :class="{ 'rounded-lg border border-gray-200 dark:border-gray-800 p-6 sm:p-10': bordered }"
20
+ :class="{ 'base-border rounded-lg border p-6 sm:p-10': bordered }"
21
21
  >
22
22
  <div
23
23
  v-if="$slots.image"
@@ -81,11 +81,11 @@ function onOpenFilePicker() {
81
81
  'field-disabled': disabled,
82
82
  'pointer-events-none opacity-50': disabled,
83
83
  'pointer-events-none': loading,
84
- 'hover:border-gray-300 focus:border-gray-400 dark:hover:border-gray-700 dark:focus:border-gray-600': border === 'full' && !disabled && !loading,
84
+ 'base-border-interactive': border === 'full' && !disabled && !loading,
85
85
  'bg-gray-100 dark:bg-gray-900': background === 'gray',
86
86
  'bg-white dark:bg-gray-900': background === 'white',
87
- 'rounded-lg border border-gray-200 shadow-sm dark:border-gray-800': border === 'full',
88
- 'border-b border-gray-200 dark:border-gray-800': border === 'bottom',
87
+ 'base-box': border === 'full',
88
+ 'base-border-b': border === 'bottom',
89
89
  'border-0': border === 'none',
90
90
  'text-xs h-10': size === 'sm',
91
91
  'text-sm h-12': size === 'base',
@@ -18,23 +18,6 @@ withDefaults(defineProps<Omit<FieldCheckbox, 'modelValue'>>(), {
18
18
 
19
19
  const id = useId()
20
20
  const modelValue = defineModel<FieldCheckbox['modelValue']>({ default: false })
21
- const isAnimatingCheck = ref(false)
22
-
23
- watch(modelValue, (value) => {
24
- if (!value) {
25
- isAnimatingCheck.value = false
26
- }
27
- })
28
-
29
- function onChange(event: Event) {
30
- isAnimatingCheck.value = (event.target as HTMLInputElement).checked
31
- }
32
-
33
- function onCheckAnimationEnd(event: AnimationEvent) {
34
- if (event.animationName.startsWith('pop-in')) {
35
- isAnimatingCheck.value = false
36
- }
37
- }
38
21
  </script>
39
22
 
40
23
  <template>
@@ -43,7 +26,10 @@ function onCheckAnimationEnd(event: AnimationEvent) {
43
26
  :class="{ 'w-full': fullWidth }"
44
27
  @click.stop
45
28
  >
46
- <div class="group flex flex-1 items-center">
29
+ <div
30
+ class="flex flex-1 items-center"
31
+ :class="{ group: !!label }"
32
+ >
47
33
  <label
48
34
  v-if="!loading"
49
35
  class="relative flex items-center justify-center flex-initial"
@@ -59,31 +45,27 @@ function onCheckAnimationEnd(event: AnimationEvent) {
59
45
  :class="{ 'field-disabled': disabled }"
60
46
  :disabled="disabled"
61
47
  type="checkbox"
62
- @change="onChange"
63
48
  >
64
49
 
65
50
  <span
66
51
  aria-hidden="true"
67
52
  class="flex items-center justify-center border-2 rounded-full transition-[background-color,border-color] duration-200 ease-out"
68
53
  :class="{
69
- 'animate-pop-in motion-reduce:animate-none': isAnimatingCheck,
70
54
  'border-transparent bg-indigo-600 dark:bg-indigo-400': modelValue,
71
- 'border-gray-300 dark:border-gray-600': !modelValue,
72
- 'group-hover:border-gray-400 dark:group-hover:border-gray-500': !disabled && !modelValue,
55
+ 'base-border': !modelValue,
56
+ 'base-border-group-hover': !disabled && !modelValue,
73
57
  'group-hover:bg-indigo-700 dark:group-hover:bg-indigo-300': !disabled && modelValue,
74
58
  'h-4 w-4': size === 'sm',
75
59
  'h-4.5 w-4.5': size === 'base',
76
60
  'h-5 w-5': size === 'lg',
77
61
  'peer-focus-visible:ring-2 peer-focus-visible:ring-indigo-500/40 peer-focus-visible:ring-offset-2 peer-focus-visible:outline-none': !disabled,
78
62
  }"
79
- @animationend="onCheckAnimationEnd"
80
63
  >
81
64
  <Icon
82
65
  v-if="modelValue"
83
66
  :name="getLayerIcon('check')"
84
67
  class="shrink-0 text-white"
85
68
  :class="{
86
- 'animate-fade-in': isAnimatingCheck,
87
69
  'size-2.5': size === 'sm',
88
70
  'size-3': size === 'base',
89
71
  'size-3.5': size === 'lg',
@@ -55,7 +55,7 @@ function onEmojiClick(event: MouseEvent, emoji?: string) {
55
55
 
56
56
  <template>
57
57
  <div
58
- class="border border-gray-200 rounded-lg p-4 shadow-sm dark:border-gray-800"
58
+ class="base-box p-4"
59
59
  :class="{ 'field-disabled': disabled }"
60
60
  >
61
61
  <FieldInput
@@ -190,11 +190,11 @@ defineExpose({ blur, focus })
190
190
  'text-right': alignment === 'right',
191
191
  'bg-gray-100 dark:bg-gray-900': background === 'gray',
192
192
  'bg-white dark:bg-gray-900': background === 'white',
193
- 'border shadow-sm border-gray-200 dark:border-gray-800': border === 'full',
193
+ 'base-box': border === 'full',
194
194
  'pl-3 pr-10': border === 'full' && type === 'password',
195
195
  'px-3': border === 'full' && type !== 'password',
196
- 'hover:border-gray-300 focus:border-gray-400 dark:hover:border-gray-700 dark:focus:border-gray-600': border === 'full' && !disabled,
197
- 'border-b border-gray-200 dark:border-gray-800': border === 'bottom',
196
+ 'base-border-interactive': border === 'full' && !disabled,
197
+ 'base-border-b': border === 'bottom',
198
198
  'pl-10 pr-16': border === 'bottom' && type === 'password',
199
199
  'px-10': border === 'bottom' && type !== 'password',
200
200
  'border-0 p-0': border === 'none' && type !== 'password',
@@ -214,12 +214,12 @@ function selectOption(event: MouseEvent, value: string) {
214
214
  <div
215
215
  class="group flex items-center rounded-lg bg-white outline-none dark:bg-gray-900"
216
216
  :class="{
217
- 'border shadow-sm border-gray-200 dark:border-gray-800': border === 'full',
218
- 'border-b border-gray-200 dark:border-gray-800': border === 'bottom',
217
+ 'base-box': border === 'full',
218
+ 'base-border-b': border === 'bottom',
219
219
  'border-0': border === 'none',
220
- 'border-gray-400 dark:border-gray-600': opened,
221
- 'hover:border-gray-300 dark:hover:border-gray-700': !opened && !disabled,
222
- 'focus-visible:border-gray-400 dark:focus-visible:border-gray-600': !disabled,
220
+ 'base-border-active': opened,
221
+ 'base-border-hover': !opened && !disabled,
222
+ 'base-border-interactive-focus-visible': !disabled,
223
223
  'px-3': padding,
224
224
  'text-xs h-10': size === 'sm',
225
225
  'text-sm h-12': size === 'base',
@@ -276,7 +276,7 @@ function selectOption(event: MouseEvent, value: string) {
276
276
  :initial="fadeIn.initial"
277
277
  >
278
278
  <div
279
- class="options min-w-xs overflow-y-auto border border-gray-400 rounded-lg bg-white text-gray-600 font-medium dark:border-gray-600 dark:bg-gray-900 dark:text-gray-400"
279
+ class="options base-border-active min-w-xs overflow-y-auto border rounded-lg bg-white text-gray-600 font-medium dark:bg-gray-900 dark:text-gray-400"
280
280
  :class="{
281
281
  'md:min-w-xl p-1 pb-0': computedColumns.length >= 2,
282
282
  'mt-8': size === 'sm' && !padding && direction === 'bottom',
@@ -293,7 +293,7 @@ function selectOption(event: MouseEvent, value: string) {
293
293
  >
294
294
  <div
295
295
  v-if="searchable"
296
- class="sticky top-0 z-10 border-b border-gray-200 bg-white dark:border-gray-800 dark:bg-gray-900"
296
+ class="base-border-b sticky top-0 z-10 bg-white dark:bg-gray-900"
297
297
  @click.stop
298
298
  >
299
299
  <FieldInput
@@ -311,7 +311,7 @@ function selectOption(event: MouseEvent, value: string) {
311
311
 
312
312
  <div
313
313
  v-if="searchable && searchQueryCleaned && !firstFilteredOption"
314
- class="flex justify-center border-b border-gray-200 p-3 dark:border-gray-800"
314
+ class="base-border-b flex justify-center p-3"
315
315
  >
316
316
  <BaseIcon
317
317
  class="pointer-events-none"
@@ -337,7 +337,7 @@ function selectOption(event: MouseEvent, value: string) {
337
337
  :key="option.value"
338
338
  class="flex cursor-pointer items-center outline-none"
339
339
  :class="{
340
- 'border-b border-gray-200 dark:border-gray-800 p-3 hover:bg-gray-100 dark:hover:bg-gray-800 last:border-b-0': computedColumns.length < 2,
340
+ 'base-border-b p-3 hover:bg-gray-100 dark:hover:bg-gray-800 last:border-b-0': computedColumns.length < 2,
341
341
  'px-2 py-1 hover:bg-gray-100 dark:hover:bg-gray-800 last:mb-2': computedColumns.length >= 2,
342
342
  'font-medium underline': option.value === selectedOption?.value,
343
343
  'text-gray-900 dark:text-gray-100': option.value === selectedOption?.value,
@@ -78,8 +78,8 @@ function onFieldClick(event: MouseEvent) {
78
78
  'resize-none': !resize,
79
79
  'bg-gray-100 dark:bg-gray-900': background === 'gray',
80
80
  'bg-white dark:bg-gray-900': background === 'white',
81
- 'border shadow-sm border-gray-200 dark:border-gray-800': border,
82
- 'hover:border-gray-300 dark:hover:border-gray-700 focus:border-gray-400 dark:focus:border-gray-600': border && !disabled,
81
+ 'base-box': border,
82
+ 'base-border-interactive': border && !disabled,
83
83
  'border-0': !border,
84
84
  'text-xs': size === 'sm',
85
85
  'text-sm': size === 'base',
@@ -55,10 +55,10 @@ function onFieldBlur(event: FocusEvent) {
55
55
  />
56
56
 
57
57
  <div
58
- class="flex cursor-pointer items-center gap-2 overflow-hidden border border-gray-200 rounded-lg px-3 font-normal dark:border-gray-800"
58
+ class="base-box flex cursor-pointer items-center gap-2 overflow-hidden px-3 font-normal"
59
59
  :class="{
60
60
  'field-disabled': disabled,
61
- 'focus-within:border-gray-400 hover:border-gray-300 dark:focus-within:border-gray-600 dark:hover:border-gray-700': !disabled,
61
+ 'base-border-interactive-focus-within': !disabled,
62
62
  'bg-gray-100 dark:bg-gray-900': background === 'gray',
63
63
  'bg-white dark:bg-gray-900': background === 'white',
64
64
  'text-xs h-10': size === 'sm',
@@ -63,12 +63,6 @@ function onHeaderPointerDown(event: PointerEvent) {
63
63
  handle.setPointerCapture(event.pointerId)
64
64
  }
65
65
 
66
- function onPanelAfterEnter(element: Element) {
67
- // Drop the identity transform after the open animation so nested SortableJS
68
- // fallbacks on iOS resolve viewport coordinates instead of a transformed ancestor.
69
- element.classList.remove('translate-y-0')
70
- }
71
-
72
66
  function onPanelTransitionEnd(event: TransitionEvent) {
73
67
  if (event.propertyName !== 'transform' || !drag.closing) {
74
68
  return
@@ -215,7 +209,6 @@ watch(visible, (isVisible) => {
215
209
  leave-active-class="transition-transform duration-300 ease motion-reduce:transition-none motion-reduce:duration-0"
216
210
  leave-from-class="translate-y-0"
217
211
  leave-to-class="translate-y-full motion-reduce:translate-y-0"
218
- @after-enter="onPanelAfterEnter"
219
212
  @after-leave="onAfterLeave"
220
213
  >
221
214
  <div
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@saasmakers/ui",
3
- "version": "2.0.19",
3
+ "version": "2.0.21",
4
4
  "private": false,
5
5
  "description": "Reusable Nuxt UI components for SaaS Makers projects",
6
6
  "license": "MIT",
package/uno.config.ts CHANGED
@@ -26,6 +26,16 @@ export const rules: [string, Record<string, string>][] = [
26
26
 
27
27
  export const shortcuts: Record<string, string> = {
28
28
  'app-text': 'font-bold leading-relaxed tracking-tight uppercase',
29
+ 'base-border': 'border-gray-200 dark:border-gray-800',
30
+ 'base-border-active': 'border-gray-400 dark:border-gray-600',
31
+ 'base-border-b': 'border-b border-gray-200 dark:border-gray-800',
32
+ 'base-border-group-hover': 'group-hover:border-gray-300 dark:group-hover:border-gray-700',
33
+ 'base-border-hover': 'hover:border-gray-300 dark:hover:border-gray-700',
34
+ 'base-border-interactive': 'hover:border-gray-300 focus:border-gray-400 dark:hover:border-gray-700 dark:focus:border-gray-600',
35
+ 'base-border-interactive-focus-visible': 'hover:border-gray-300 focus-visible:border-gray-400 dark:hover:border-gray-700 dark:focus-visible:border-gray-600',
36
+ 'base-border-interactive-focus-within': 'hover:border-gray-300 focus-within:border-gray-400 dark:hover:border-gray-700 dark:focus-within:border-gray-600',
37
+ 'base-box': 'border shadow-sm base-border rounded-lg',
38
+ 'base-surface': 'border base-border bg-white dark:bg-gray-900 shadow-sm',
29
39
  'field-disabled': 'opacity-50 cursor-not-allowed',
30
40
  'scroll-y-stable': 'overflow-y-auto [scrollbar-gutter:stable]',
31
41
  }
@@ -33,30 +43,22 @@ export const shortcuts: Record<string, string> = {
33
43
  export const theme = {
34
44
  animation: {
35
45
  keyframes: {
36
- 'fade-in': '{0%,25%{opacity:0}100%{opacity:1}}',
37
46
  'fade-pulse': '{0%,100%{opacity:0.25}50%{opacity:1}}',
38
- 'pop-in': '{from{transform:scale(0.8)}to{transform:scale(1)}}',
39
47
  'scale-pulse': '{0%,100%{transform:scale(0)}50%{transform:scale(1)}}',
40
48
  },
41
49
 
42
50
  durations: {
43
- 'fade-in': '200ms',
44
51
  'fade-pulse': '1s',
45
- 'pop-in': '250ms',
46
52
  'scale-pulse': '2s',
47
53
  },
48
54
 
49
55
  timingFns: {
50
- 'fade-in': 'ease-out',
51
56
  'fade-pulse': 'ease-in-out',
52
- 'pop-in': 'cubic-bezier(0.34,1.56,0.64,1)',
53
57
  'scale-pulse': 'linear',
54
58
  },
55
59
 
56
60
  counts: {
57
- 'fade-in': '1',
58
61
  'fade-pulse': 'infinite',
59
- 'pop-in': '1',
60
62
  'scale-pulse': 'infinite',
61
63
  },
62
64
  },