v-uixy 1.8.0 → 1.8.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "v-uixy",
3
- "version": "1.8.0",
3
+ "version": "1.8.1",
4
4
  "private": false,
5
5
  "author": {
6
6
  "name": "Alan Haber",
@@ -13,10 +13,12 @@
13
13
  @click.self="handleClick"
14
14
  >
15
15
  <motion.div
16
+ class="flex w-full justify-center"
16
17
  :initial="{ scale: 0.8 }"
17
18
  :animate="{ scale: 1 }"
18
19
  :exit="{ scale: 0.8 }"
19
20
  :transition="{ duration: 0.15, ease: 'easeInOut' }"
21
+ @click.self="handleClick"
20
22
  >
21
23
  <slot />
22
24
  </motion.div>
@@ -40,7 +42,7 @@
40
42
  const open = defineModel<boolean>();
41
43
 
42
44
  const handleClick = () => {
43
- if (props.persistent) return;
45
+ if (props.persistent || props.loading) return;
44
46
 
45
47
  open.value = false;
46
48
  };
@@ -1,7 +1,7 @@
1
1
  import styles from "~/utils/styles";
2
2
 
3
3
  const modalStyles = styles(
4
- "fixed left-0 top-0 z-20 flex size-full items-center justify-center bg-white/5 backdrop-blur-[2px] dark:bg-gray-900/5"
4
+ "fixed left-0 top-0 z-[60] flex size-full items-center justify-center bg-white/5 backdrop-blur-[2px] dark:bg-gray-900/5"
5
5
  );
6
6
 
7
7
  export { modalStyles };
@@ -1,3 +1,4 @@
1
1
  export interface UixyModalProps {
2
2
  persistent?: boolean;
3
+ loading?: boolean;
3
4
  }
@@ -39,6 +39,7 @@
39
39
 
40
40
  const { active, handleOpen, handleLeave, styles, refElement } = usePosition({
41
41
  direction: props.direction ?? "bottom",
42
+ align: props.align ?? "center",
42
43
  });
43
44
 
44
45
  const handleClickOutside = (e: MouseEvent) => {
@@ -1,5 +1,6 @@
1
1
  export interface UixyPopoverProps {
2
2
  direction?: "top" | "bottom";
3
+ align?: "center" | "start";
3
4
  closeOnClick?: boolean;
4
5
  group?: string;
5
6
  }
@@ -14,6 +14,7 @@
14
14
  type="button"
15
15
  role="tab"
16
16
  :aria-selected="model === option.value"
17
+ :aria-label="option.ariaLabel"
17
18
  :disabled="props.disabled || option.disabled"
18
19
  :class="
19
20
  segmentStyles({
@@ -5,6 +5,7 @@ export interface UixySegmentedOption {
5
5
  value: string | number;
6
6
  icon?: IconName;
7
7
  disabled?: boolean;
8
+ ariaLabel?: string;
8
9
  }
9
10
 
10
11
  export interface UixySegmentedControlProps {
@@ -1,9 +1,11 @@
1
1
  import { ref, computed, watch, onBeforeUnmount, nextTick, type Ref } from "vue";
2
2
 
3
3
  type Direction = "top" | "bottom";
4
+ type Align = "center" | "start";
4
5
 
5
6
  interface UsePositionOptions {
6
7
  direction?: Direction;
8
+ align?: Align;
7
9
  }
8
10
 
9
11
  const GAP = 6;
@@ -17,7 +19,10 @@ function hasFixedParent(el: HTMLElement | null): boolean {
17
19
  return false;
18
20
  }
19
21
 
20
- export function usePosition({ direction = "bottom" }: UsePositionOptions) {
22
+ export function usePosition({
23
+ direction = "bottom",
24
+ align = "center",
25
+ }: UsePositionOptions) {
21
26
  const refElement = ref<HTMLElement>();
22
27
 
23
28
  const active = ref(false);
@@ -26,7 +31,7 @@ export function usePosition({ direction = "bottom" }: UsePositionOptions) {
26
31
  const baseStyles = computed(() => ({
27
32
  position: hasFixedParent(target.value) ? "fixed" : "absolute",
28
33
  width: "max-content",
29
- zIndex: 20,
34
+ zIndex: 70,
30
35
  }));
31
36
 
32
37
  const styles = ref<Record<string, string | number>>({
@@ -65,7 +70,10 @@ export function usePosition({ direction = "bottom" }: UsePositionOptions) {
65
70
  ? targetRect.top - tooltipRect.height - GAP + scrollY
66
71
  : targetRect.bottom + GAP + scrollY;
67
72
 
68
- let left = targetRect.left + targetRect.width / 2 - tooltipRect.width / 2;
73
+ let left =
74
+ align === "start"
75
+ ? targetRect.left
76
+ : targetRect.left + targetRect.width / 2 - tooltipRect.width / 2;
69
77
  const newStyles: Record<string, string | number> = {
70
78
  ...baseStyles.value,
71
79
  top,
@@ -87,13 +95,31 @@ export function usePosition({ direction = "bottom" }: UsePositionOptions) {
87
95
  };
88
96
  };
89
97
 
98
+ let resizeObserver: ResizeObserver | null = null;
99
+
100
+ const observeResize = () => {
101
+ if (typeof ResizeObserver === "undefined") return;
102
+ resizeObserver = new ResizeObserver(() => {
103
+ void updatePosition();
104
+ });
105
+ if (target.value) resizeObserver.observe(target.value);
106
+ if (refElement.value) resizeObserver.observe(refElement.value);
107
+ };
108
+
109
+ const unobserveResize = () => {
110
+ resizeObserver?.disconnect();
111
+ resizeObserver = null;
112
+ };
113
+
90
114
  watch(
91
- [active, () => direction],
115
+ [active, () => direction, () => align],
92
116
  ([isActive]) => {
93
117
  if (isActive) {
94
118
  updatePosition();
119
+ observeResize();
95
120
  window.addEventListener("resize", updatePosition);
96
121
  } else {
122
+ unobserveResize();
97
123
  window.removeEventListener("resize", updatePosition);
98
124
  }
99
125
  },
@@ -101,6 +127,7 @@ export function usePosition({ direction = "bottom" }: UsePositionOptions) {
101
127
  );
102
128
 
103
129
  onBeforeUnmount(() => {
130
+ unobserveResize();
104
131
  window.removeEventListener("resize", updatePosition);
105
132
  });
106
133