@fiscozen/composables 0.1.5 → 0.1.7

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": "@fiscozen/composables",
3
- "version": "0.1.5",
3
+ "version": "0.1.7",
4
4
  "description": "Design System utility composables",
5
5
  "main": "src/index.ts",
6
6
  "type": "module",
@@ -9,7 +9,7 @@ const props = withDefaults(defineProps<FzFloatingProps>(), {
9
9
  })
10
10
 
11
11
  const opener = ref(null)
12
- const content = ref<HTMLElement|null>(null)
12
+ const content = ref<HTMLElement | null>(null)
13
13
 
14
14
  const slots = useSlots()
15
15
 
@@ -38,11 +38,11 @@ watch(
38
38
  () => props.isOpen,
39
39
  (newVal) => {
40
40
  if (!newVal || !content.value) {
41
- return;
41
+ return
42
42
  }
43
- content.value.style.top = '0px';
44
- content.value.style.left = '0px';
45
- content.value.style.transform = 'none';
43
+ content.value.style.top = '0px'
44
+ content.value.style.left = '0px'
45
+ content.value.style.transform = 'none'
46
46
  floating.setPosition()
47
47
  }
48
48
  )
@@ -55,8 +55,8 @@ watch(
55
55
  </div>
56
56
  <div
57
57
  ref="content"
58
- v-show="!$slots.opener || ($slots.opener && isOpen)"
59
- class="bg-core-white absolute p-4 z-10"
58
+ v-show="$slots.default && (!$slots.opener || ($slots.opener && isOpen))"
59
+ class="bg-core-white fixed p-4 z-10"
60
60
  :class="contentClass"
61
61
  >
62
62
  <slot :isOpen :floating></slot>
@@ -1 +1,3 @@
1
1
  export * from './useFloating'
2
+ export * from './useMediaQuery'
3
+ export * from './useBreakpoints'
@@ -0,0 +1,17 @@
1
+ import { useMediaQuery } from './useMediaQuery'
2
+
3
+ function useBreakpoints<T extends string>(breakpoints: Record<T, `${number}px`>) {
4
+ return {
5
+ isGreater(breakpoint: T) {
6
+ return useMediaQuery(`(min-width: ${breakpoints[breakpoint]})`)
7
+ },
8
+ isSmaller(breakpoint: T) {
9
+ return useMediaQuery(`(max-width: ${breakpoints[breakpoint]})`)
10
+ },
11
+ isInBetween(min: T, max: T) {
12
+ return useMediaQuery(`(min-width: ${breakpoints[min]}) and (max-width: ${breakpoints[max]})`)
13
+ }
14
+ }
15
+ }
16
+
17
+ export { useBreakpoints }
@@ -5,10 +5,10 @@ import { calcRealPos, getHighestAvailableSpacePos } from '../utils'
5
5
  export const useFloating = (
6
6
  args: FzUseFloatingArgs
7
7
  ): {
8
- float: FzRect;
9
- rect: Ref<DOMRect | null>;
10
- floatObserver: Ref<IntersectionObserver>;
11
- setPosition: () => Promise<void>;
8
+ float: FzRect
9
+ rect: Ref<DOMRect | null>
10
+ floatObserver: Ref<IntersectionObserver>
11
+ setPosition: () => Promise<void>
12
12
  } => {
13
13
  const safeElementDomRef = ref<HTMLElement | null>(null)
14
14
  const safeContainerDomRef = ref<HTMLElement | null>(null)
@@ -31,224 +31,225 @@ export const useFloating = (
31
31
 
32
32
  const floatObserver = ref(new IntersectionObserver(handleIntersect, options))
33
33
 
34
- const setPosition = () => nextTick(() => {
35
- safeElementDomRef.value =
36
- typeof args.element.domRef.value === 'string'
37
- ? document.querySelector(args.element.domRef.value)
38
- : args.element.domRef.value
39
- if (!args.container) {
40
- safeContainerDomRef.value = document.body
41
- } else {
42
- safeContainerDomRef.value =
43
- typeof args.container.domRef.value === 'string'
44
- ? document.querySelector(args.container.domRef.value)
45
- : args.container.domRef.value
46
- safeContainerDomRef.value ??= document.body
47
- }
34
+ const setPosition = () =>
35
+ nextTick(() => {
36
+ safeElementDomRef.value =
37
+ typeof args.element.domRef.value === 'string'
38
+ ? document.querySelector(args.element.domRef.value)
39
+ : args.element.domRef.value
40
+ if (!args.container) {
41
+ safeContainerDomRef.value = document.body
42
+ } else {
43
+ safeContainerDomRef.value =
44
+ typeof args.container.domRef.value === 'string'
45
+ ? document.querySelector(args.container.domRef.value)
46
+ : args.container.domRef.value
47
+ safeContainerDomRef.value ??= document.body
48
+ }
48
49
 
49
- if (!safeElementDomRef.value) {
50
- throw new Error('missing reference element for floating behavior')
51
- }
50
+ if (!safeElementDomRef.value) {
51
+ throw new Error('missing reference element for floating behavior')
52
+ }
52
53
 
53
- if (args.opener) {
54
- safeOpenerDomRef.value =
55
- typeof args.opener.domRef.value === 'string'
56
- ? document.querySelector(args.opener.domRef.value)
57
- : args.opener.domRef.value
58
- }
54
+ if (args.opener) {
55
+ safeOpenerDomRef.value =
56
+ typeof args.opener.domRef.value === 'string'
57
+ ? document.querySelector(args.opener.domRef.value)
58
+ : args.opener.domRef.value
59
+ }
59
60
 
60
- rect.value = safeElementDomRef.value.getBoundingClientRect()
61
- const openerRect = safeOpenerDomRef.value?.getBoundingClientRect()
62
- const containerRect = safeContainerDomRef.value.getBoundingClientRect()
61
+ rect.value = safeElementDomRef.value.getBoundingClientRect()
62
+ const openerRect = safeOpenerDomRef.value?.getBoundingClientRect()
63
+ const containerRect = safeContainerDomRef.value.getBoundingClientRect()
63
64
 
64
- // multiple observer calls on same target do not cause multiple registrations
65
- floatObserver.value.observe(safeElementDomRef.value)
66
- floatObserver.value.observe(safeContainerDomRef.value)
65
+ // multiple observer calls on same target do not cause multiple registrations
66
+ floatObserver.value.observe(safeElementDomRef.value)
67
+ floatObserver.value.observe(safeContainerDomRef.value)
67
68
 
68
- let position: FzFloatingPosition = args.position ? args.position.value : 'auto'
69
+ let position: FzFloatingPosition = args.position ? args.position.value : 'auto'
69
70
 
70
- let translateY = 0
71
- let translateX = 0
71
+ let translateY = 0
72
+ let translateX = 0
72
73
 
73
- if (args.opener && safeOpenerDomRef.value && openerRect) {
74
- switch (position) {
75
- case 'auto':
76
- position = getHighestAvailableSpacePos(
77
- safeContainerDomRef.value,
78
- safeElementDomRef.value,
79
- safeOpenerDomRef.value
80
- )
81
- break
82
- case 'auto-start':
83
- position = getHighestAvailableSpacePos(
84
- safeContainerDomRef.value,
85
- safeElementDomRef.value,
86
- safeOpenerDomRef.value,
87
- 'start'
88
- )
89
- break
90
- case 'auto-end':
91
- position = getHighestAvailableSpacePos(
92
- safeContainerDomRef.value,
93
- safeElementDomRef.value,
94
- safeOpenerDomRef.value,
95
- 'end'
96
- )
97
- break
98
- default:
99
- break
74
+ if (args.opener && safeOpenerDomRef.value && openerRect) {
75
+ switch (position) {
76
+ case 'auto':
77
+ position = getHighestAvailableSpacePos(
78
+ safeContainerDomRef.value,
79
+ safeElementDomRef.value,
80
+ safeOpenerDomRef.value
81
+ )
82
+ break
83
+ case 'auto-start':
84
+ position = getHighestAvailableSpacePos(
85
+ safeContainerDomRef.value,
86
+ safeElementDomRef.value,
87
+ safeOpenerDomRef.value,
88
+ 'start'
89
+ )
90
+ break
91
+ case 'auto-end':
92
+ position = getHighestAvailableSpacePos(
93
+ safeContainerDomRef.value,
94
+ safeElementDomRef.value,
95
+ safeOpenerDomRef.value,
96
+ 'end'
97
+ )
98
+ break
99
+ default:
100
+ break
101
+ }
102
+ switch (position) {
103
+ case 'bottom':
104
+ float.position.y = openerRect.bottom
105
+ float.position.x = openerRect.left + openerRect.width / 2
106
+ translateX = -50
107
+ translateY = 0
108
+ break
109
+ case 'bottom-start':
110
+ float.position.y = openerRect.bottom
111
+ float.position.x = openerRect.left
112
+ translateX = 0
113
+ translateY = 0
114
+ break
115
+ case 'bottom-end':
116
+ float.position.y = openerRect.bottom
117
+ float.position.x = openerRect.right
118
+ translateX = -100
119
+ translateY = 0
120
+ break
121
+ case 'left-start':
122
+ float.position.y = openerRect.top
123
+ float.position.x = openerRect.left
124
+ translateX = -100
125
+ translateY = 0
126
+ break
127
+ case 'left':
128
+ float.position.y = openerRect.top + openerRect.height / 2
129
+ float.position.x = openerRect.left
130
+ translateY = -50
131
+ translateX = -100
132
+ break
133
+ case 'left-end':
134
+ float.position.y = openerRect.bottom
135
+ float.position.x = openerRect.left
136
+ translateY = -100
137
+ translateX = -100
138
+ break
139
+ case 'top-start':
140
+ float.position.y = openerRect.top
141
+ float.position.x = openerRect.left
142
+ translateY = -100
143
+ translateX = 0
144
+ break
145
+ case 'top':
146
+ float.position.y = openerRect.top
147
+ float.position.x = openerRect.left + openerRect.width / 2
148
+ translateX = -50
149
+ translateY = -100
150
+ break
151
+ case 'top-end':
152
+ float.position.y = openerRect.top
153
+ float.position.x = openerRect.right
154
+ translateX = -100
155
+ translateY = -100
156
+ break
157
+ case 'right-start':
158
+ float.position.y = openerRect.top
159
+ float.position.x = openerRect.right
160
+ translateX = 0
161
+ translateY = 0
162
+ break
163
+ case 'right':
164
+ float.position.y = openerRect.top + openerRect.height / 2
165
+ float.position.x = openerRect.right
166
+ translateY = -50
167
+ translateX = 0
168
+ break
169
+ case 'right-end':
170
+ float.position.y = openerRect.bottom
171
+ float.position.x = openerRect.right
172
+ translateY = -100
173
+ translateX = 0
174
+ break
175
+ default:
176
+ break
177
+ }
178
+ } else {
179
+ switch (position) {
180
+ case 'bottom':
181
+ float.position.y = containerRect.bottom - rect.value.height
182
+ float.position.x = containerRect.left + containerRect.width / 2
183
+ translateX = -50
184
+ break
185
+ case 'left-end':
186
+ case 'bottom-start':
187
+ float.position.y = containerRect.bottom - rect.value.height
188
+ float.position.x = containerRect.left
189
+ break
190
+ case 'right-end':
191
+ case 'bottom-end':
192
+ float.position.y = containerRect.bottom - rect.value.height
193
+ float.position.x = containerRect.right - rect.value.width
194
+ break
195
+ case 'left':
196
+ float.position.y = containerRect.top + (containerRect.height - rect.value.height) / 2
197
+ float.position.x = containerRect.left
198
+ break
199
+ case 'top-start':
200
+ case 'left-start':
201
+ float.position.y = containerRect.top
202
+ float.position.x = containerRect.left
203
+ break
204
+ case 'top':
205
+ float.position.y = containerRect.top
206
+ float.position.x = containerRect.left + (containerRect.width - rect.value.width) / 2
207
+ break
208
+ case 'top-end':
209
+ case 'right-start':
210
+ float.position.y = containerRect.top
211
+ float.position.x = containerRect.right - rect.value.width
212
+ case 'right':
213
+ float.position.y = containerRect.top + (containerRect.height - rect.value.height) / 2
214
+ float.position.x = containerRect.right - rect.value.width
215
+ break
216
+ default:
217
+ break
218
+ }
100
219
  }
101
- switch (position) {
102
- case 'bottom':
103
- float.position.y = openerRect.bottom
104
- float.position.x = openerRect.left + openerRect.width / 2
105
- translateX = -50
106
- translateY = 0
107
- break
108
- case 'bottom-start':
109
- float.position.y = openerRect.bottom
110
- float.position.x = openerRect.left
111
- translateX = 0
112
- translateY = 0
113
- break
114
- case 'bottom-end':
115
- float.position.y = openerRect.bottom
116
- float.position.x = openerRect.right
117
- translateX = -100
118
- translateY = 0
119
- break
120
- case 'left-start':
121
- float.position.y = openerRect.top
122
- float.position.x = openerRect.left
123
- translateX = -100
124
- translateY = 0
125
- break
126
- case 'left':
127
- float.position.y = openerRect.top + openerRect.height / 2
128
- float.position.x = openerRect.left
129
- translateY = -50
130
- translateX = -100
131
- break
132
- case 'left-end':
133
- float.position.y = openerRect.bottom
134
- float.position.x = openerRect.left
135
- translateY = -100
136
- translateX = -100
137
- break
138
- case 'top-start':
139
- float.position.y = openerRect.top
140
- float.position.x = openerRect.left
141
- translateY = -100
142
- translateX = 0
143
- break
144
- case 'top':
145
- float.position.y = openerRect.top
146
- float.position.x = openerRect.left + openerRect.width / 2
147
- translateX = -50
148
- translateY = -100
149
- break
150
- case 'top-end':
151
- float.position.y = openerRect.top
152
- float.position.x = openerRect.right
153
- translateX = -100
154
- translateY = -100
155
- break
156
- case 'right-start':
157
- float.position.y = openerRect.top
158
- float.position.x = openerRect.right
159
- translateX = 0
160
- translateY = 0
161
- break
162
- case 'right':
163
- float.position.y = openerRect.top + openerRect.height / 2
164
- float.position.x = openerRect.right
165
- translateY = -50
166
- translateX = 0
167
- break
168
- case 'right-end':
169
- float.position.y = openerRect.bottom
170
- float.position.x = openerRect.right
171
- translateY = -100
172
- translateX = 0
173
- break
174
- default:
175
- break
176
- }
177
- } else {
178
- switch (position) {
179
- case 'bottom':
180
- float.position.y = containerRect.bottom - rect.value.height
181
- float.position.x = containerRect.left + containerRect.width / 2
182
- translateX = -50
183
- break
184
- case 'left-end':
185
- case 'bottom-start':
186
- float.position.y = containerRect.bottom - rect.value.height
187
- float.position.x = containerRect.left
188
- break
189
- case 'right-end':
190
- case 'bottom-end':
191
- float.position.y = containerRect.bottom - rect.value.height
192
- float.position.x = containerRect.right - rect.value.width
193
- break
194
- case 'left':
195
- float.position.y = containerRect.top + (containerRect.height - rect.value.height) / 2
196
- float.position.x = containerRect.left
197
- break
198
- case 'top-start':
199
- case 'left-start':
200
- float.position.y = containerRect.top
201
- float.position.x = containerRect.left
202
- break
203
- case 'top':
204
- float.position.y = containerRect.top
205
- float.position.x = containerRect.left + (containerRect.width - rect.value.width) / 2
206
- break
207
- case 'top-end':
208
- case 'right-start':
209
- float.position.y = containerRect.top
210
- float.position.x = containerRect.right - rect.value.width
211
- case 'right':
212
- float.position.y = containerRect.top + (containerRect.height - rect.value.height) / 2
213
- float.position.x = containerRect.right - rect.value.width
214
- break
215
- default:
216
- break
217
- }
218
- }
219
220
 
220
- const realPos = calcRealPos(rect.value, float.position, translateX, translateY)
221
+ const realPos = calcRealPos(rect.value, float.position, translateX, translateY)
221
222
 
222
- float.position.x = realPos.x;
223
- float.position.y = realPos.y;
223
+ float.position.x = realPos.x
224
+ float.position.y = realPos.y
224
225
 
225
- if (realPos.x < containerRect.left) {
226
- float.position.x = containerRect.left;
227
- translateX = 0
228
- }
226
+ if (realPos.x < containerRect.left) {
227
+ float.position.x = containerRect.left
228
+ translateX = 0
229
+ }
229
230
 
230
- if ((realPos.x + rect.value.width) > containerRect.right) {
231
- float.position.x = containerRect.right - rect.value.width;
232
- translateX = 0
233
- }
234
-
235
- if (realPos.y < containerRect.top) {
236
- float.position.y = containerRect.top;
237
- translateY = 0
238
- }
231
+ if (realPos.x + rect.value.width > containerRect.right) {
232
+ float.position.x = containerRect.right - rect.value.width
233
+ translateX = 0
234
+ }
239
235
 
240
- if ((realPos.y + rect.value.height) > containerRect.bottom) {
241
- float.position.y = containerRect.bottom - rect.value.height;
242
- translateY = 0
243
- }
236
+ if (realPos.y < containerRect.top) {
237
+ float.position.y = containerRect.top
238
+ translateY = 0
239
+ }
244
240
 
245
- safeElementDomRef.value.style.top = `${float.position.y}px`
246
- safeElementDomRef.value.style.left = `${float.position.x}px`
247
- safeElementDomRef.value.style.position = 'fixed'
248
- safeElementDomRef.value.style.display = 'flex'
241
+ if (realPos.y + rect.value.height > containerRect.bottom) {
242
+ float.position.y = containerRect.bottom - rect.value.height
243
+ translateY = 0
244
+ }
249
245
 
250
- rect.value = safeElementDomRef.value.getBoundingClientRect()
251
- })
246
+ safeElementDomRef.value.style.top = `${float.position.y}px`
247
+ safeElementDomRef.value.style.left = `${float.position.x}px`
248
+ safeElementDomRef.value.style.position = 'fixed'
249
+ safeElementDomRef.value.style.display = 'flex'
250
+
251
+ rect.value = safeElementDomRef.value.getBoundingClientRect()
252
+ })
252
253
 
253
254
  onUnmounted(() => {
254
255
  floatObserver.value.disconnect()
@@ -0,0 +1,22 @@
1
+ import { Ref, onMounted, onUnmounted, ref } from 'vue'
2
+
3
+ function useMediaQuery(mediaQuery: string): Ref<boolean> {
4
+ const mediaQueryList = window.matchMedia(mediaQuery)
5
+ const matches = ref(mediaQueryList.matches)
6
+
7
+ function handleChange(event: MediaQueryListEvent) {
8
+ matches.value = event.matches
9
+ }
10
+
11
+ onMounted(() => {
12
+ mediaQueryList.addEventListener('change', handleChange)
13
+ })
14
+
15
+ onUnmounted(() => {
16
+ mediaQueryList.removeEventListener('change', handleChange)
17
+ })
18
+
19
+ return matches
20
+ }
21
+
22
+ export { useMediaQuery }
@@ -20,10 +20,14 @@ export const getHighestAvailableSpacePos = (
20
20
  const elRect = el.getBoundingClientRect()
21
21
  const openerRect = opener.getBoundingClientRect()
22
22
 
23
- const spaceLeftNormalized = (openerRect.left - containerRect.left - elRect.width) / containerRect.width
24
- const spaceRightNormalized = (containerRect.right - openerRect.right - elRect.width) / containerRect.width
25
- const spaceTopNormalized = (openerRect.top - containerRect.top - elRect.height) / containerRect.height
26
- const spaceBottomNormalized = (containerRect.bottom - openerRect.bottom - elRect.height) / containerRect.height
23
+ const spaceLeftNormalized =
24
+ (openerRect.left - containerRect.left - elRect.width) / containerRect.width
25
+ const spaceRightNormalized =
26
+ (containerRect.right - openerRect.right - elRect.width) / containerRect.width
27
+ const spaceTopNormalized =
28
+ (openerRect.top - containerRect.top - elRect.height) / containerRect.height
29
+ const spaceBottomNormalized =
30
+ (containerRect.bottom - openerRect.bottom - elRect.height) / containerRect.height
27
31
 
28
32
  const positionList = [
29
33
  {
@@ -67,10 +71,14 @@ export const getHighestAvailableSpacePos = (
67
71
  return positionRes
68
72
  }
69
73
 
70
-
71
- export const calcRealPos = (rect: DOMRect, pos: FzAbsolutePosition, translateX: number, translateY: number): FzAbsolutePosition => {
74
+ export const calcRealPos = (
75
+ rect: DOMRect,
76
+ pos: FzAbsolutePosition,
77
+ translateX: number,
78
+ translateY: number
79
+ ): FzAbsolutePosition => {
72
80
  return {
73
- x: pos.x + (rect.width * translateX)/100,
74
- y: pos.y + (rect.height * translateY)/100,
81
+ x: pos.x + (rect.width * translateX) / 100,
82
+ y: pos.y + (rect.height * translateY) / 100
75
83
  }
76
- }
84
+ }