sprintify-ui 0.0.81 → 0.0.83

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.
@@ -1,21 +1,20 @@
1
- import { Placement } from '@popperjs/core';
2
1
  import { PropType } from 'vue';
3
2
  declare const _default: {
4
3
  new (...args: any[]): {
5
4
  $: import("vue").ComponentInternalInstance;
6
5
  $data: {};
7
6
  $props: Partial<{
8
- placement: Placement;
9
- offset: [number, number];
7
+ padding: number;
8
+ placement: "bottom-start" | "bottom-end" | "top-start" | "top-end";
10
9
  animated: boolean;
11
10
  }> & Omit<Readonly<import("vue").ExtractPropTypes<{
12
11
  placement: {
13
- type: PropType<Placement>;
14
- default(): "bottom";
12
+ type: PropType<"bottom-start" | "bottom-end" | "top-start" | "top-end">;
13
+ default(): string;
15
14
  };
16
- offset: {
17
- default(): number[];
18
- type: PropType<[number, number]>;
15
+ padding: {
16
+ default: number;
17
+ type: NumberConstructor;
19
18
  };
20
19
  animated: {
21
20
  default: boolean;
@@ -24,7 +23,7 @@ declare const _default: {
24
23
  }>> & {
25
24
  onOpen?: ((...args: any[]) => any) | undefined;
26
25
  onClose?: ((...args: any[]) => any) | undefined;
27
- } & import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, "placement" | "offset" | "animated">;
26
+ } & import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, "padding" | "placement" | "animated">;
28
27
  $attrs: {
29
28
  [x: string]: unknown;
30
29
  };
@@ -40,12 +39,12 @@ declare const _default: {
40
39
  $el: any;
41
40
  $options: import("vue").ComponentOptionsBase<Readonly<import("vue").ExtractPropTypes<{
42
41
  placement: {
43
- type: PropType<Placement>;
44
- default(): "bottom";
42
+ type: PropType<"bottom-start" | "bottom-end" | "top-start" | "top-end">;
43
+ default(): string;
45
44
  };
46
- offset: {
47
- default(): number[];
48
- type: PropType<[number, number]>;
45
+ padding: {
46
+ default: number;
47
+ type: NumberConstructor;
49
48
  };
50
49
  animated: {
51
50
  default: boolean;
@@ -55,8 +54,8 @@ declare const _default: {
55
54
  onOpen?: ((...args: any[]) => any) | undefined;
56
55
  onClose?: ((...args: any[]) => any) | undefined;
57
56
  }, {}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, ("open" | "close")[], string, {
58
- placement: Placement;
59
- offset: [number, number];
57
+ padding: number;
58
+ placement: "bottom-start" | "bottom-end" | "top-start" | "top-end";
60
59
  animated: boolean;
61
60
  }, {}, string> & {
62
61
  beforeCreate?: ((() => void) | (() => void)[]) | undefined;
@@ -80,12 +79,12 @@ declare const _default: {
80
79
  $watch<T extends string | ((...args: any) => any)>(source: T, cb: T extends (...args: any) => infer R ? (args_0: R, args_1: R) => any : (...args: any) => any, options?: import("vue").WatchOptions<boolean> | undefined): import("vue").WatchStopHandle;
81
80
  } & Readonly<import("vue").ExtractPropTypes<{
82
81
  placement: {
83
- type: PropType<Placement>;
84
- default(): "bottom";
82
+ type: PropType<"bottom-start" | "bottom-end" | "top-start" | "top-end">;
83
+ default(): string;
85
84
  };
86
- offset: {
87
- default(): number[];
88
- type: PropType<[number, number]>;
85
+ padding: {
86
+ default: number;
87
+ type: NumberConstructor;
89
88
  };
90
89
  animated: {
91
90
  default: boolean;
@@ -100,12 +99,12 @@ declare const _default: {
100
99
  __isSuspense?: undefined;
101
100
  } & import("vue").ComponentOptionsBase<Readonly<import("vue").ExtractPropTypes<{
102
101
  placement: {
103
- type: PropType<Placement>;
104
- default(): "bottom";
102
+ type: PropType<"bottom-start" | "bottom-end" | "top-start" | "top-end">;
103
+ default(): string;
105
104
  };
106
- offset: {
107
- default(): number[];
108
- type: PropType<[number, number]>;
105
+ padding: {
106
+ default: number;
107
+ type: NumberConstructor;
109
108
  };
110
109
  animated: {
111
110
  default: boolean;
@@ -115,8 +114,8 @@ declare const _default: {
115
114
  onOpen?: ((...args: any[]) => any) | undefined;
116
115
  onClose?: ((...args: any[]) => any) | undefined;
117
116
  }, {}, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, ("open" | "close")[], "open" | "close", {
118
- placement: Placement;
119
- offset: [number, number];
117
+ padding: number;
118
+ placement: "bottom-start" | "bottom-end" | "top-start" | "top-end";
120
119
  animated: boolean;
121
120
  }, {}, string> & import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps & (new () => {
122
121
  $slots: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sprintify-ui",
3
- "version": "0.0.81",
3
+ "version": "0.0.83",
4
4
  "scripts": {
5
5
  "build": "rimraf dist && vue-tsc && vite build",
6
6
  "build-fast": "rimraf dist && vite build",
@@ -12,7 +12,6 @@
12
12
  "prepack": "npm run build"
13
13
  },
14
14
  "peerDependencies": {
15
- "@popperjs/core": "^2.11.6",
16
15
  "@tailwindcss/aspect-ratio": "^0.4.2",
17
16
  "@tailwindcss/forms": "^0.5.3",
18
17
  "@tailwindcss/line-clamp": "^0.4.2",
@@ -38,7 +37,6 @@
38
37
  "devDependencies": {
39
38
  "@babel/core": "^7.20.2",
40
39
  "@iconify/vue": "^4.0.0",
41
- "@popperjs/core": "^2.11.6",
42
40
  "@storybook/addon-actions": "^6.5.13",
43
41
  "@storybook/addon-essentials": "^6.5.13",
44
42
  "@storybook/addon-interactions": "^6.5.13",
@@ -6,9 +6,17 @@ import { options } from '../../.storybook/utils';
6
6
  export default {
7
7
  title: 'Components/BaseDropdown',
8
8
  component: BaseDropdown,
9
+ argTypes: {
10
+ placement: {
11
+ control: {
12
+ type: 'select',
13
+ options: ['top-start', 'top-end', 'bottom-start', 'bottom-end'],
14
+ },
15
+ },
16
+ },
9
17
  args: {
10
18
  placement: 'bottom-start',
11
- offset: [0, 8],
19
+ padding: 8,
12
20
  },
13
21
  };
14
22
 
@@ -18,18 +26,22 @@ const Template = (args) => ({
18
26
  return { args };
19
27
  },
20
28
  template: `
21
- <BaseDropdown v-bind="args">
22
- <template #button>
23
- <div class="btn btn-primary">Click me</div>
24
- </template>
25
- <template #dropdown>
26
- <div class="bg-white shadow py-1 px-1 rounded">
27
- <button type="button" class="block text-sm px-4 py-1.5">Item 1</button>
28
- <button type="button" class="block text-sm px-4 py-1.5">Item 2</button>
29
- <button type="button" class="block text-sm px-4 py-1.5">Item 3</button>
30
- </div>
31
- </template>
32
- </BaseDropdown>
29
+ <div style="height: 1000px; margin-top: 100px;">
30
+ <div style="height: 70px; overflow: hidden; position: relative; display: inline-block;">
31
+ <BaseDropdown v-bind="args">
32
+ <template #button>
33
+ <div class="btn btn-primary">Click me</div>
34
+ </template>
35
+ <template #dropdown>
36
+ <div class="bg-white shadow py-1 px-1 rounded">
37
+ <button type="button" class="block text-sm px-4 py-1.5">Item 1</button>
38
+ <button type="button" class="block text-sm px-4 py-1.5">Item 2</button>
39
+ <button type="button" class="block text-sm px-4 py-1.5">Item 3</button>
40
+ </div>
41
+ </template>
42
+ </BaseDropdown>
43
+ </div>
44
+ </div>
33
45
  `,
34
46
  });
35
47
 
@@ -97,6 +109,7 @@ export const WithAutocomplete = (args) => ({
97
109
  });
98
110
 
99
111
  WithAutocomplete.args = {
112
+ animated: true,
100
113
  placement: 'bottom-start',
101
- offset: [0, 3],
114
+ padding: 3,
102
115
  };
@@ -3,33 +3,35 @@
3
3
  <button ref="button" type="button" @click="toggle()">
4
4
  <slot name="button"></slot>
5
5
  </button>
6
- <div ref="dropdown" class="z-menu">
7
- <Transition
8
- :enter-active-class="
9
- animated ? 'duration-100 transition ease-out' : ''
10
- "
11
- enter-from-class="transform scale-90 opacity-0"
12
- enter-to-class="transform scale-100 opacity-100"
13
- :leave-active-class="animated ? 'duration-75 transition ease-in' : ''"
14
- leave-from-class="transform scale-100 opacity-100"
15
- leave-to-class="transform scale-90 opacity-0"
16
- >
17
- <div v-show="showDropdown" ref="dropdown" class="inline-block">
18
- <slot
19
- name="dropdown"
20
- :close="close"
21
- :open="open"
22
- :toggle="toggle"
23
- ></slot>
24
- </div>
25
- </Transition>
26
- </div>
6
+ <Teleport to="body">
7
+ <div ref="dropdown" class="z-menu" :style="dropdownStyles">
8
+ <Transition
9
+ :enter-active-class="
10
+ animated ? 'duration-100 transition ease-out' : ''
11
+ "
12
+ enter-from-class="transform scale-90 opacity-0"
13
+ enter-to-class="transform scale-100 opacity-100"
14
+ :leave-active-class="animated ? 'duration-75 transition ease-in' : ''"
15
+ leave-from-class="transform scale-100 opacity-100"
16
+ leave-to-class="transform scale-90 opacity-0"
17
+ >
18
+ <div v-show="showDropdown" class="inline-block" scroll-lock-target>
19
+ <slot
20
+ name="dropdown"
21
+ :close="close"
22
+ :open="open"
23
+ :toggle="toggle"
24
+ ></slot>
25
+ </div>
26
+ </Transition>
27
+ </div>
28
+ </Teleport>
27
29
  </div>
28
30
  </template>
29
31
 
30
32
  <script lang="ts" setup>
31
- import { bottom, createPopper, Placement } from '@popperjs/core';
32
- import { PropType } from 'vue';
33
+ import { PropType, StyleValue } from 'vue';
34
+ import { disableScroll, enableScroll } from '../utils';
33
35
 
34
36
  const button = ref<HTMLElement | null>(null);
35
37
  const dropdown = ref<HTMLElement | null>(null);
@@ -38,16 +40,16 @@ const showDropdown = ref(false);
38
40
 
39
41
  const props = defineProps({
40
42
  placement: {
41
- type: String as PropType<Placement>,
43
+ type: String as PropType<
44
+ 'bottom-start' | 'bottom-end' | 'top-start' | 'top-end'
45
+ >,
42
46
  default() {
43
- return bottom;
47
+ return 'bottom-start';
44
48
  },
45
49
  },
46
- offset: {
47
- default() {
48
- return [0, 8];
49
- },
50
- type: Array as unknown as PropType<[number, number]>,
50
+ padding: {
51
+ default: 8,
52
+ type: Number,
51
53
  },
52
54
  animated: {
53
55
  default: false,
@@ -55,23 +57,31 @@ const props = defineProps({
55
57
  },
56
58
  });
57
59
 
60
+ const buttonX = ref(0);
61
+ const buttonY = ref(0);
62
+ const buttonWidth = ref(0);
63
+ const buttonHeight = ref(0);
64
+
65
+ const dropdownWidth = ref(0);
66
+ const dropdownHeight = ref(0);
67
+
58
68
  const emit = defineEmits(['close', 'open']);
59
69
 
60
- onMounted(() => {
61
- if (button.value && dropdown.value) {
62
- createPopper(button.value, dropdown.value, {
63
- placement: props.placement,
64
- modifiers: [
65
- {
66
- name: 'offset',
67
- options: {
68
- offset: props.offset,
69
- },
70
- },
71
- ],
72
- });
70
+ function setBoundingBoxes() {
71
+ if (button.value) {
72
+ const { y, x, height, width } = button.value.getBoundingClientRect();
73
+ buttonX.value = x;
74
+ buttonY.value = y;
75
+ buttonWidth.value = width;
76
+ buttonHeight.value = height;
73
77
  }
74
- });
78
+
79
+ if (dropdown.value) {
80
+ const { height, width } = dropdown.value.getBoundingClientRect();
81
+ dropdownWidth.value = width;
82
+ dropdownHeight.value = height;
83
+ }
84
+ }
75
85
 
76
86
  function toggle() {
77
87
  if (showDropdown.value) {
@@ -83,13 +93,16 @@ function toggle() {
83
93
 
84
94
  function open() {
85
95
  activate();
96
+ setBoundingBoxes();
86
97
  showDropdown.value = true;
98
+ disableScroll(dropdown.value);
87
99
  emit('open');
88
100
  }
89
101
 
90
102
  function close() {
91
103
  deactivate();
92
104
  showDropdown.value = false;
105
+ enableScroll();
93
106
  emit('close');
94
107
  }
95
108
 
@@ -138,7 +151,37 @@ function onMouseDown(event: MouseEvent) {
138
151
  }
139
152
  }
140
153
 
154
+ const dropdownStyles = computed((): StyleValue => {
155
+ let top = buttonY.value;
156
+
157
+ if (props.placement == 'bottom-start' || props.placement == 'bottom-end') {
158
+ top += buttonHeight.value;
159
+ top += props.padding;
160
+ }
161
+
162
+ if (props.placement == 'top-start' || props.placement == 'top-end') {
163
+ top -= dropdownHeight.value;
164
+ top -= props.padding;
165
+ }
166
+
167
+ const styles = {
168
+ position: 'fixed',
169
+ top: `${top}px`,
170
+ } as any;
171
+
172
+ if (props.placement == 'bottom-end' || props.placement == 'top-end') {
173
+ styles.left = `${
174
+ buttonX.value + buttonWidth.value - dropdownWidth.value
175
+ }px`;
176
+ } else {
177
+ styles.left = `${buttonX.value}px`;
178
+ }
179
+
180
+ return styles as StyleValue;
181
+ });
182
+
141
183
  onBeforeUnmount(() => {
184
+ close();
142
185
  deactivate();
143
186
  });
144
187
  </script>