@saasmakers/ui 2.0.22 → 2.0.23

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.
@@ -77,7 +77,6 @@ function onClick(event: MouseEvent) {
77
77
  />
78
78
 
79
79
  <BaseText
80
- bold
81
80
  class="tracking-tight uppercase"
82
81
  :size="size === 'lg' ? 'xs' : '2xs'"
83
82
  :text="confirming ? t('confirm') : text"
@@ -1,8 +1,6 @@
1
1
  <script lang="ts" setup>
2
2
  import { NuxtLinkLocale } from '#components'
3
- import type { BaseButton, BaseButtonShape } from '../../types/bases'
4
-
5
- const fixedSizeButtonShapes = ['square', 'circle'] satisfies BaseButtonShape[]
3
+ import type { BaseButton } from '../../types/bases'
6
4
 
7
5
  const props = withDefaults(defineProps<BaseButton>(), {
8
6
  background: true,
@@ -36,7 +34,7 @@ const confirming = ref(false)
36
34
  const { t } = useI18n()
37
35
 
38
36
  const hasFixedSize = computed(() => {
39
- return fixedSizeButtonShapes.includes(props.shape)
37
+ return props.shape === 'square' || props.shape === 'circle'
40
38
  })
41
39
 
42
40
  function onClick(event: MouseEvent) {
@@ -128,7 +128,7 @@ function onOpenFilePicker() {
128
128
 
129
129
  <BaseText
130
130
  class="min-w-0 flex-1 text-gray-900 dark:text-gray-100"
131
- :size="({ base: 'sm', lg: 'base', sm: 'xs', xs: '2xs' } as const)[size]"
131
+ :size="({ base: 'sm', lg: 'base', sm: 'xs' } as const)[size]"
132
132
  :text="loading ? t('actionLoading') : (action || t('action'))"
133
133
  />
134
134
  </div>
@@ -166,7 +166,6 @@ defineExpose({ blur, focus })
166
166
  <div
167
167
  class="flex items-center"
168
168
  :class="{
169
- 'h-8': size === 'xs',
170
169
  'h-10': size === 'sm',
171
170
  'h-12': size === 'base',
172
171
  'h-14': size === 'lg',
@@ -200,7 +199,6 @@ defineExpose({ blur, focus })
200
199
  'px-10': border === 'bottom' && type !== 'password',
201
200
  'border-0 p-0': border === 'none' && type !== 'password',
202
201
  'border-0 pr-9': border === 'none' && type === 'password',
203
- 'text-2xs': size === 'xs',
204
202
  'text-xs': size === 'sm',
205
203
  'text-sm': size === 'base',
206
204
  'text-base': size === 'lg',
@@ -27,10 +27,10 @@ const textSize = computed<BaseSize>(() => {
27
27
  switch (props.size) {
28
28
  case 'lg':
29
29
  return 'base'
30
+ case 'base':
31
+ return 'sm'
30
32
  case 'sm':
31
33
  return 'xs'
32
- case 'xs':
33
- return '2xs'
34
34
  default:
35
35
  return 'sm'
36
36
  }
@@ -71,11 +71,9 @@ function onKeyDown(event: KeyboardEvent) {
71
71
  'text-gray-500 dark:text-gray-500 line-through': lineThrough,
72
72
  'hover:text-black dark:hover:text-white': isClickable && !lineThrough,
73
73
  'w-0 truncate': truncate,
74
- 'mb-1.5': size === 'xs' && hasMarginBottom,
75
74
  'mb-2': size === 'sm' && hasMarginBottom,
76
75
  'mb-2.5': size === 'base' && hasMarginBottom,
77
76
  'mb-3': size === 'lg' && hasMarginBottom,
78
- 'ml-1': size === 'xs' && hasMarginLeft,
79
77
  'ml-1.5': size === 'sm' && hasMarginLeft,
80
78
  'ml-2': size === 'base' && hasMarginLeft,
81
79
  'ml-2.5': size === 'lg' && hasMarginLeft,
@@ -14,7 +14,7 @@ const dragMoveThreshold = 8
14
14
  const visible = defineModel<boolean>({ default: false })
15
15
  const contentRef = ref<HTMLElement>()
16
16
  const panelRef = ref<HTMLElement>()
17
- const { release: onAfterLeave } = useDialog(visible, panelRef, { ignoreClass: 'layout-bottom-sheet' })
17
+ const { release: onAfterLeave } = useDialog(visible, panelRef)
18
18
 
19
19
  const drag = reactive({
20
20
  closing: false,
@@ -1,17 +1,10 @@
1
- interface UseDialogOptions {
2
- ignoreClass: string
3
- }
4
-
5
1
  export default function useDialog(
6
2
  visible: Ref<boolean>,
7
3
  panelRef: Ref<HTMLElement | undefined>,
8
- options: UseDialogOptions,
9
4
  ) {
10
5
  const focusableSelector = 'a[href], button:not([disabled]), textarea:not([disabled]), input:not([disabled]), select:not([disabled]), [tabindex]:not([tabindex="-1"])'
11
- const fixedElementPadding = new Map<HTMLElement, string>()
12
6
 
13
- let savedBodyOverflow = ''
14
- let savedBodyPaddingRight = ''
7
+ let savedRootOverflow = ''
15
8
 
16
9
  function getFocusableElements(container: HTMLElement) {
17
10
  return Array.from(container.querySelectorAll<HTMLElement>(focusableSelector))
@@ -20,39 +13,12 @@ export default function useDialog(
20
13
  })
21
14
  }
22
15
 
16
+ // Rely on the global `scrollbar-gutter: stable` (html/body) to keep the gutter
17
+ // reserved while the scroll container is locked, so no manual padding
18
+ // compensation is needed and no horizontal layout shift occurs.
23
19
  function lockBodyScroll() {
24
- const scrollbarWidth = window.innerWidth - document.documentElement.clientWidth
25
-
26
- savedBodyOverflow = document.body.style.overflow
27
- savedBodyPaddingRight = document.body.style.paddingRight
28
- document.body.style.overflow = 'hidden'
29
-
30
- if (scrollbarWidth > 0) {
31
- document.body.style.paddingRight = `${scrollbarWidth}px`
32
-
33
- for (const element of document.querySelectorAll('body *')) {
34
- if (!(element instanceof HTMLElement)) {
35
- continue
36
- }
37
-
38
- // Skip the dialog's own teleported elements so they are not padded.
39
- if (element.classList.contains(options.ignoreClass)) {
40
- continue
41
- }
42
-
43
- const { position } = getComputedStyle(element)
44
-
45
- if (position !== 'fixed' && position !== 'sticky') {
46
- continue
47
- }
48
-
49
- fixedElementPadding.set(element, element.style.paddingRight)
50
-
51
- const currentPadding = Number.parseFloat(getComputedStyle(element).paddingRight) || 0
52
-
53
- element.style.paddingRight = `${currentPadding + scrollbarWidth}px`
54
- }
55
- }
20
+ savedRootOverflow = document.documentElement.style.overflow
21
+ document.documentElement.style.overflow = 'hidden'
56
22
  }
57
23
 
58
24
  function onFocusTrap(event: KeyboardEvent) {
@@ -90,14 +56,7 @@ export default function useDialog(
90
56
  }
91
57
 
92
58
  function unlockBodyScroll() {
93
- document.body.style.overflow = savedBodyOverflow
94
- document.body.style.paddingRight = savedBodyPaddingRight
95
-
96
- for (const [element, paddingRight] of fixedElementPadding) {
97
- element.style.paddingRight = paddingRight
98
- }
99
-
100
- fixedElementPadding.clear()
59
+ document.documentElement.style.overflow = savedRootOverflow
101
60
  }
102
61
 
103
62
  // Restores scroll lock and focus trap once the leave transition has finished.
@@ -155,7 +155,7 @@ export interface FieldSelectOption {
155
155
  value: string
156
156
  }
157
157
 
158
- export type FieldSize = 'base' | 'lg' | 'sm' | 'xs'
158
+ export type FieldSize = 'base' | 'lg' | 'sm'
159
159
 
160
160
  export type FieldStatus
161
161
  = | 'default'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@saasmakers/ui",
3
- "version": "2.0.22",
3
+ "version": "2.0.23",
4
4
  "private": false,
5
5
  "description": "Reusable Nuxt UI components for SaaS Makers projects",
6
6
  "license": "MIT",