@bagelink/vue 0.0.724 → 0.0.728

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,5 +1,5 @@
1
1
  <script setup lang="ts">
2
- import { Btn, Icon } from '@bagelink/vue'
2
+ import { BglVideo, Btn, Icon } from '@bagelink/vue'
3
3
  import { watch } from 'vue'
4
4
  import type { LightboxItem } from './lightbox.types'
5
5
 
@@ -66,153 +66,134 @@ defineExpose({ open, close })
66
66
  </script>
67
67
 
68
68
  <template>
69
- <div
70
- v-if="isOpen"
71
- class="lightbox-overlay"
72
- @keydown.esc="close"
73
- @keydown.left="prev"
74
- @keydown.right="next"
75
- @click="close"
76
- >
77
- <div class="lightbox" @click.stop>
78
- <Btn flat class="close-button color-white" icon="close" @click="close" />
79
- <div class="lightbox-item">
80
- <template v-if="currentItem?.type === 'image'">
81
- <img :src="currentItem?.src" alt="Preview">
82
- </template>
83
- <template v-else-if="currentItem?.type === 'video'">
84
- <video controls autoplay>
85
- <source :src="currentItem?.src" type="video/mp4">
86
- <track kind="captions" src="#" srclang="en" label="English">
87
- </video>
88
- </template>
89
- <template v-else-if="currentItem?.type === 'pdf'">
90
- <embed
91
- :src="normalizeURL(currentItem?.src)"
92
- type="application/pdf"
93
- width="100%"
94
- height="1080"
95
- :title="currentItem?.name"
96
- >
97
- </template>
98
- <template v-else>
99
- <div class="file-info txt-white">
100
- <p>File: {{ currentItem?.name }}</p>
101
- <p>Type: {{ currentItem?.type }}</p>
102
- <a :href="currentItem?.src" target="_blank">Open file</a>
103
- </div>
104
- </template>
105
- </div>
106
- <div class="navigation">
107
- <Btn
108
- class="navigation-btn"
109
- icon="arrow_back"
110
- @click="prev"
111
- />
112
- <Btn
113
- class="navigation-btn"
114
- icon="arrow_forward"
115
- @click="next"
116
- />
117
- </div>
118
- <div v-if="group && group.length > 1" class="thumbnails">
119
- <template
120
- v-for="(item, index) in group"
121
- :key="index"
69
+ <transition name="fade">
70
+ <div
71
+ v-if="isOpen"
72
+ class="bgl-lightbox-overlay fixed w-100 h-100 flex justify-content-center z-999 inset mx-auto"
73
+ @keydown.esc="close"
74
+ @keydown.left="prev"
75
+ @keydown.right="next"
76
+ @click="close"
77
+ >
78
+ <div class="bgl-lightbox relative vw90 txt-center" @click.stop>
79
+ <Btn flat class="fixed top-1 end-1 color-white" icon="close" @click="close" />
80
+ <div class="bgl-lightbox-item">
81
+ <template v-if="currentItem?.type === 'image'">
82
+ <img :src="currentItem?.src" alt="Preview">
83
+ </template>
84
+ <template v-else-if="currentItem?.type === 'video'">
85
+ <BglVideo
86
+ :src="currentItem?.src"
87
+ autoplay
88
+ controls
89
+ />
90
+ </template>
91
+ <template v-else-if="currentItem?.type === 'pdf'">
92
+ <embed
93
+ :src="normalizeURL(currentItem?.src)"
94
+ type="application/pdf"
95
+ width="100%"
96
+ height="1080"
97
+ :title="currentItem?.name"
98
+ >
99
+ </template>
100
+ <template v-else>
101
+ <div class="file-info txt-white">
102
+ <p>File: {{ currentItem?.name }}</p>
103
+ <p>Type: {{ currentItem?.type }}</p>
104
+ <a :href="currentItem?.src" target="_blank">Open file</a>
105
+ </div>
106
+ </template>
107
+ </div>
108
+ <div v-if="group.length" class="navigation flex space-between w-100 absolute">
109
+ <Btn
110
+ class="navigation-btn oval user-select-none"
111
+ icon="arrow_back"
112
+ @click="prev"
113
+ />
114
+ <Btn
115
+ class="navigation-btn oval user-select-none"
116
+ icon="arrow_forward"
117
+ @click="next"
118
+ />
119
+ </div>
120
+ <div
121
+ v-if="group && group.length > 1"
122
+ class="flex justify-content-center mt-2 overflow
123
+ p-1 fixed bottom start end gap-1 m_justify-content-start"
122
124
  >
123
- <img
124
- v-if="item.type === 'image'"
125
- class="thumbnail"
126
- :src="item.src"
127
- alt=""
128
- @click="selectItem(index)"
125
+ <template
126
+ v-for="(item, index) in group"
127
+ :key="index"
129
128
  >
130
- <Icon
131
- v-else
132
- class="thumbnail"
133
- icon="description"
134
- @click="selectItem(index)"
135
- />
136
- </template>
129
+ <img
130
+ v-if="item.type === 'image'"
131
+ class="thumbnail object-fit-cover hover
132
+ opacity-5 round flex bg-white justify-content-center align-items-center flex-shrink-0"
133
+ :src="item.src"
134
+ alt=""
135
+ :class="{ active: currentIndex === index }"
136
+ @click="selectItem(index)"
137
+ >
138
+ <Icon
139
+ v-else
140
+ class="thumbnail object-fit-cover hover
141
+ opacity-5 round flex bg-white justify-content-center align-items-center flex-shrink-0"
142
+ icon="description"
143
+ :class="{ active: currentIndex === index }"
144
+ @click="selectItem(index)"
145
+ />
146
+ </template>
147
+ </div>
137
148
  </div>
138
149
  </div>
139
- </div>
150
+ </transition>
140
151
  </template>
141
152
 
142
153
  <style scoped>
143
- .lightbox-overlay {
144
- position: fixed;
145
- top: 0;
146
- left: 0;
147
- width: 100%;
148
- height: 100%;
154
+ .bgl-lightbox-overlay {
149
155
  background: rgba(0, 0, 0, 0.8);
150
- display: flex;
151
- justify-content: center;
152
- align-items: center;
153
- z-index: 1000;
154
156
  }
155
157
 
156
- .lightbox {
157
- position: relative;
158
+ .bgl-lightbox {
158
159
  max-height: 90%;
159
- width: 90vw;
160
- text-align: center;
161
160
  }
162
161
 
163
- .close-button {
164
- position: fixed;
165
- top: 1rem;
166
- inset-inline-end: 1rem;
162
+ .bgl-lightbox-item{
163
+ animation: 500ms ease bgl-lightbox-load;
167
164
  }
165
+ @keyframes bgl-lightbox-load {
166
+ from {
167
+ scale:0.7;
168
+ }
168
169
 
169
- .lightbox-item * {
170
+ to {
171
+ scale:1;
172
+
173
+ }
174
+ }
175
+
176
+ .bgl-lightbox-item * {
170
177
  max-width: 90%;
171
178
  max-height: calc(80vh - 90px);
172
179
  border-radius: 3px;
180
+ margin: auto;
181
+ animation: 200ms ease bgl-lightbox-load;
173
182
  }
174
183
 
175
184
  .navigation {
176
- display: flex;
177
- justify-content: space-between;
178
- width: 100%;
179
- position: absolute;
180
185
  top: 50%;
181
186
  transform: translateY(-50%);
182
187
  }
183
188
 
184
189
  .navigation-btn {
185
- user-select: none;
186
190
  width: var(--input-height);
187
191
  height: var(--input-height);
188
- border-radius: 100%;
189
- }
190
-
191
- .thumbnails {
192
- display: flex;
193
- justify-content: center;
194
- margin-top: 10px;
195
- overflow: auto;
196
- padding: 1rem;
197
- position: fixed;
198
- bottom: 0;
199
- left: 0;
200
- right: 0;
201
192
  }
202
193
 
203
194
  .thumbnail {
204
195
  height: 50px;
205
196
  width: 50px;
206
- object-fit: cover;
207
- margin: 0 5px;
208
- cursor: pointer;
209
- opacity: 0.5;
210
- border-radius: 3px;
211
- transition: all 200ms ease;
212
- background-color: white;
213
- display: flex;
214
- justify-content: center;
215
- align-items: center;
216
197
  }
217
198
  .thumbnail:hover {
218
199
  opacity: 1;
@@ -1,4 +1,4 @@
1
- import type { App, DirectiveBinding } from 'vue'
1
+ import type { App, Directive, DirectiveBinding } from 'vue'
2
2
  import { createApp } from 'vue'
3
3
  import { IMAGE_FORMATS_REGEXP, VIDEO_FORMATS_REGEXP } from '@bagelink/vue'
4
4
  import Lightbox from './Lightbox.vue'
@@ -6,42 +6,37 @@ import type { LightboxItem } from './lightbox.types'
6
6
 
7
7
  type OpenFunction = (item: LightboxItem, groupItems?: LightboxItem[]) => void
8
8
  const groups: Record<string, LightboxItem[]> = {}
9
- const lightboxDirective = {
10
- mounted(el: HTMLElement, binding: DirectiveBinding) {
11
- const lightboxInstance = createLightboxInstance()
12
- if (!lightboxInstance || !lightboxInstance.open) return
13
- if (binding.value.group) {
14
- if (!groups[binding.value.group]) groups[binding.value.group] = []
15
- groups[binding.value.group].push({
16
- src: binding.value.src || binding.value,
17
- type: binding.value.type || determineFileType(binding.value.src || binding.value),
18
- name: binding.value.name || ''
19
- })
9
+ const lightboxDirective: Directive = {
10
+ mounted(el: HTMLElement, binding) {
11
+ el.classList.add('hover')
12
+ let { group, src, type, name, thumbnail } = binding.value || {}
13
+ src = src || binding.value || el.getAttribute('src') || ''
14
+ type = type || determineFileType(src)
15
+ const item: LightboxItem = { src, type, name, thumbnail }
16
+ if (group) {
17
+ if (!groups[group]) groups[group] = []
18
+ groups[group].push(item)
20
19
  }
21
- el.addEventListener('click', () => {
22
- const group = binding.value.group || null
23
- const item: LightboxItem = {
24
- src: binding.value.src || binding.value,
25
- type: binding.value.type || determineFileType(binding.value.src || binding.value),
26
- name: binding.value.name || '',
27
- thumbnail: binding.value.thumbnail || '',
28
- }
20
+ el.addEventListener('click', (e) => {
21
+ e.stopPropagation()
29
22
  const lightboxInstance = createLightboxInstance()
30
23
  if (!lightboxInstance || !lightboxInstance.open) return
31
- if (binding.value.group) {
32
- if (!groups[binding.value.group]) groups[binding.value.group] = []
33
- groups[binding.value.group].push(item)
34
- }
35
24
  const open = lightboxInstance.open as OpenFunction
36
25
  open(item, groups[group])
37
26
  })
38
27
  },
28
+ unmounted(el: HTMLElement, binding) {
29
+ // TODO: remove click event handler
30
+ }
39
31
  }
40
32
 
33
+ const youtubeRegex = /youtube\.com|youtu\.be/
34
+ const vimeoRegex = /vimeo\.com/
35
+
41
36
  function determineFileType(url: string): string {
42
37
  const extension = url.split('.').pop()?.toLowerCase() || ''
43
38
  if (IMAGE_FORMATS_REGEXP.test(extension)) return 'image'
44
- if (VIDEO_FORMATS_REGEXP.test(extension)) return 'video'
39
+ if (VIDEO_FORMATS_REGEXP.test(extension) || youtubeRegex.test(url) || vimeoRegex.test(url)) return 'video'
45
40
  if (['pdf'].includes(extension)) return 'pdf'
46
41
  return 'unknown'
47
42
  }
@@ -34,6 +34,24 @@
34
34
  height: fit-content;
35
35
  }
36
36
 
37
+ .is-active .modal {
38
+ animation: 200ms ease bgl-modal-animation;
39
+
40
+ }
41
+
42
+ @keyframes bgl-modal-animation {
43
+ from {
44
+ scale: 0.7;
45
+ transform: translateY(2rem);
46
+ }
47
+
48
+ to {
49
+ scale: 1;
50
+ transform: translateY(0);
51
+
52
+ }
53
+ }
54
+
37
55
  .small-modal .modal {
38
56
  max-width: 300px;
39
57
  text-align: center;