@pocketprep/ui-kit 3.5.28 → 3.5.30

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,7 +1,14 @@
1
1
  <script setup lang="ts">
2
2
  import { dark as vDark } from '../../directives'
3
+ import Icon from '../Icons/Icon.vue'
4
+
3
5
  defineProps<{
4
6
  isDarkMode?: boolean
7
+ showCloseButton?: boolean
8
+ }>()
9
+
10
+ const emit = defineEmits<{
11
+ 'close': []
5
12
  }>()
6
13
  </script>
7
14
 
@@ -10,6 +17,13 @@ defineProps<{
10
17
  <div v-dark="isDarkMode" class="info-message__content">
11
18
  <slot></slot>
12
19
  </div>
20
+ <Icon
21
+ v-if="showCloseButton"
22
+ v-dark="isDarkMode"
23
+ class="info-message__close-btn"
24
+ type="close"
25
+ @click="emit('close')"
26
+ />
13
27
  </div>
14
28
  </template>
15
29
 
@@ -18,11 +32,17 @@ defineProps<{
18
32
  @use '@/styles/colors' as *;
19
33
 
20
34
  .info-message {
35
+ position: relative;
21
36
  padding: 11px 16px;
22
37
  background-color: $barely-blue;
23
38
  border: 1px solid rgba($brand-blue, 0.4);
24
39
  border-radius: 6px;
25
40
 
41
+ &--dark {
42
+ background-color: rgba($brand-blue, 0.2);
43
+ border-color: rgba($baby-blue, 0.4);
44
+ }
45
+
26
46
  &__content {
27
47
  font-size: 15px;
28
48
  line-height: 20px;
@@ -33,9 +53,30 @@ defineProps<{
33
53
  }
34
54
  }
35
55
 
36
- &--dark {
37
- background-color: rgba($brand-blue, 0.2);
38
- border-color: rgba($baby-blue, 0.4);
56
+ &__close-btn {
57
+ position: absolute;
58
+ top: 10px;
59
+ right: 10px;
60
+ width: 20px;
61
+ height: 20px;
62
+ color: $steel;
63
+ cursor: pointer;
64
+
65
+ @media (hover: hover) {
66
+ &:hover {
67
+ color: $brand-blue;
68
+ }
69
+ }
70
+
71
+ &--dark {
72
+ color: rgba($white, 0.7);
73
+
74
+ @media (hover: hover) {
75
+ &:hover {
76
+ color: $banana-bread;
77
+ }
78
+ }
79
+ }
39
80
  }
40
81
  }
41
82
  </style>
@@ -9,7 +9,7 @@
9
9
  >
10
10
  <slot name="closeIcon">
11
11
  <Icon
12
- v-breakpoint:questionEl="breakpointsWithEl"
12
+ v-breakpoint="breakpointsWithEl"
13
13
  v-dark="isDarkMode"
14
14
  class="uikit-question__close-icon"
15
15
  role="button"
package/lib/directives.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { Directive, DirectiveBinding } from 'vue'
1
+ import { type Directive, type DirectiveBinding } from 'vue'
2
2
  import MediaBreakpoints from './pocketprep-export.module.scss'
3
3
  import { ResizeObserver as ResizeObserverPonyFill } from 'resize-observer'
4
4
 
@@ -107,92 +107,108 @@ export const fixed: Directive<HTMLElement> = {
107
107
  },
108
108
  }
109
109
 
110
- export const breakpoint: Directive<HTMLElement, {
110
+ const addBreakpointListeners = (el: HTMLElement, binding: DirectiveBinding<{
111
111
  breakpoints?: TBreakpoints
112
112
  containerEl?: HTMLElement | null
113
- } | undefined> = {
114
- beforeMount (el, binding) {
115
- if (!el.dataset.breakpointId) {
116
- binding.instance?.$nextTick(() => {
117
- const breakpointId = el.dataset.breakpointId || Math.floor(Math.random() * 1e8)
118
- el.dataset.breakpointId = String(breakpointId)
119
-
120
- // Set resize event listener
121
- const resizeEventListener = () => {
122
- updateBreakpointClasses(el, binding.value, getCustomContainer(binding))
123
- }
124
- eventListeners[breakpointId] = resizeEventListener
125
- window.addEventListener('resize', resizeEventListener)
126
-
127
- // Set mutation observer
128
- const mutationObserver = new MutationObserver(() => {
129
- updateBreakpointClasses(el, binding.value, getCustomContainer(binding))
130
- })
131
- mutationObservers[breakpointId] = mutationObserver
132
- mutationObserver.observe(el, { attributes: true })
133
-
134
- // Set resize observer
135
- const container = getCustomContainer(binding)
136
- if (container) {
137
- const resizeObserver = window.ResizeObserver
138
- ? new ResizeObserver(() => {
139
- updateBreakpointClasses(el, binding.value, getCustomContainer(binding))
140
- })
141
- : new ResizeObserverPonyFill(() => {
142
- updateBreakpointClasses(el, binding.value, getCustomContainer(binding))
143
- })
144
- resizeObservers[breakpointId] = resizeObserver
145
- resizeObserver.observe(container)
146
- } else {
147
- const resizeObserver = window.ResizeObserver
148
- ? new ResizeObserver(() => {
149
- updateBreakpointClasses(el, binding.value, getCustomContainer(binding))
150
- })
151
- : new ResizeObserverPonyFill(() => {
152
- updateBreakpointClasses(el, binding.value, getCustomContainer(binding))
153
- })
154
- resizeObservers[breakpointId] = resizeObserver
155
- resizeObserver.observe(el)
156
- }
113
+ } | undefined>) => {
114
+ const existingBreakpointId = el.dataset.breakpointId
115
+
116
+ // Remove existing listeners on the element if present
117
+ // This is essential to avoid performance issues (like when an element's container changes)
118
+ if (existingBreakpointId) {
119
+ removeBreakpointListeners(el)
120
+ }
121
+ const breakpointId = existingBreakpointId || Math.floor(Math.random() * 1e8)
122
+ el.dataset.breakpointId = String(breakpointId)
123
+
124
+ // Set resize event listener
125
+ const resizeEventListener = () => {
126
+ updateBreakpointClasses(el, binding.value, getCustomContainer(binding))
127
+ }
128
+ eventListeners[breakpointId] = resizeEventListener
129
+ window.addEventListener('resize', resizeEventListener)
130
+
131
+ // Set mutation observer
132
+ const mutationObserver = new MutationObserver(() => {
133
+ updateBreakpointClasses(el, binding.value, getCustomContainer(binding))
134
+ })
135
+ mutationObservers[breakpointId] = mutationObserver
136
+ mutationObserver.observe(el, { attributes: true })
137
+
138
+ // Set resize observer
139
+ const container = getCustomContainer(binding)
140
+ if (container) {
141
+ const resizeObserver = window.ResizeObserver
142
+ ? new ResizeObserver(() => {
143
+ updateBreakpointClasses(el, binding.value, getCustomContainer(binding))
144
+ })
145
+ : new ResizeObserverPonyFill(() => {
146
+ updateBreakpointClasses(el, binding.value, getCustomContainer(binding))
147
+ })
148
+ resizeObservers[breakpointId] = resizeObserver
149
+ resizeObserver.observe(container)
150
+ } else {
151
+ const resizeObserver = window.ResizeObserver
152
+ ? new ResizeObserver(() => {
153
+ updateBreakpointClasses(el, binding.value, getCustomContainer(binding))
154
+ })
155
+ : new ResizeObserverPonyFill(() => {
156
+ updateBreakpointClasses(el, binding.value, getCustomContainer(binding))
157
157
  })
158
+ resizeObservers[breakpointId] = resizeObserver
159
+ resizeObserver.observe(el)
160
+ }
161
+ }
162
+
163
+ const removeBreakpointListeners = (el: HTMLElement) => {
164
+ const breakpointId = el.dataset.breakpointId
165
+ if (breakpointId) {
166
+ // Remove event listener
167
+ const eventListener = eventListeners[breakpointId]
168
+ if (eventListener) {
169
+ window.removeEventListener('resize', eventListener)
170
+ delete eventListeners[breakpointId]
171
+ }
172
+
173
+ // Disconnect mutation observer
174
+ const mutationObserver = mutationObservers[breakpointId]
175
+ if (mutationObserver) {
176
+ mutationObserver.disconnect()
177
+ delete mutationObservers[breakpointId]
178
+ }
179
+
180
+ // Disconnect resize observer
181
+ const resizeObserver = resizeObservers[breakpointId]
182
+ if (resizeObserver) {
183
+ resizeObserver.disconnect()
184
+ delete resizeObservers[breakpointId]
158
185
  }
186
+
187
+ delete el.dataset.breakpointId
188
+ }
189
+ }
190
+
191
+ export const breakpoint: Directive<HTMLElement, {
192
+ breakpoints?: TBreakpoints
193
+ containerEl?: HTMLElement | null
194
+ } | undefined> = {
195
+ beforeMount: (el, binding) => {
196
+ addBreakpointListeners(el, binding)
159
197
  },
160
198
  mounted: (el, binding) => {
199
+ addBreakpointListeners(el, binding)
161
200
  binding.instance?.$nextTick(() => {
162
201
  updateBreakpointClasses(el, binding.value, getCustomContainer(binding))
163
202
  })
164
203
  },
165
204
  updated: (el, binding) => {
205
+ addBreakpointListeners(el, binding)
166
206
  binding.instance?.$nextTick(() => {
167
207
  updateBreakpointClasses(el, binding.value, getCustomContainer(binding))
168
208
  })
169
209
  },
170
210
  unmounted: (el) => {
171
- const breakpointId = el.dataset.breakpointId
172
- if (breakpointId) {
173
- // Remove event listener
174
- const eventListener = eventListeners[breakpointId]
175
- if (eventListener) {
176
- window.removeEventListener('resize', eventListener)
177
- delete eventListeners[breakpointId]
178
- }
179
-
180
- // Disconnect mutation observer
181
- const mutationObserver = mutationObservers[breakpointId]
182
- if (mutationObserver) {
183
- mutationObserver.disconnect()
184
- delete mutationObservers[breakpointId]
185
- }
186
-
187
- // Disconnect resize observer
188
- const resizeObserver = resizeObservers[breakpointId]
189
- if (resizeObserver) {
190
- resizeObserver.disconnect()
191
- delete resizeObservers[breakpointId]
192
- }
193
-
194
- delete el.dataset.breakpointId
195
- }
211
+ removeBreakpointListeners(el)
196
212
  },
197
213
  }
198
214
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pocketprep/ui-kit",
3
- "version": "3.5.28",
3
+ "version": "3.5.30",
4
4
  "description": "Pocket Prep UI Kit",
5
5
  "author": "pocketprep",
6
6
  "scripts": {