@wishbone-media/spark 0.37.0 → 0.38.0
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": "@wishbone-media/spark",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.38.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.js",
|
|
@@ -65,6 +65,7 @@
|
|
|
65
65
|
"access": "public"
|
|
66
66
|
},
|
|
67
67
|
"dependencies": {
|
|
68
|
+
"@fancyapps/ui": "^6.1.13",
|
|
68
69
|
"@floating-ui/vue": "^1.1.11",
|
|
69
70
|
"@googlemaps/js-api-loader": "^2.0.2"
|
|
70
71
|
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div ref="containerRef">
|
|
3
|
+
<slot />
|
|
4
|
+
</div>
|
|
5
|
+
</template>
|
|
6
|
+
|
|
7
|
+
<script setup>
|
|
8
|
+
/**
|
|
9
|
+
* Vue 3 wrapper around Fancybox.
|
|
10
|
+
* Wraps a container element and binds Fancybox to all [data-fancybox] children.
|
|
11
|
+
* Handles lifecycle: bind on mount, rebind on update (for dynamic content), unbind on unmount.
|
|
12
|
+
*
|
|
13
|
+
* Usage:
|
|
14
|
+
* <SparkFancybox>
|
|
15
|
+
* <a href="full.jpg" data-fancybox="gallery" data-caption="Photo #1">
|
|
16
|
+
* <img src="thumb.jpg" />
|
|
17
|
+
* </a>
|
|
18
|
+
* </SparkFancybox>
|
|
19
|
+
*/
|
|
20
|
+
import { ref, onMounted, onUpdated, onUnmounted } from 'vue'
|
|
21
|
+
import { Fancybox } from '@fancyapps/ui/dist/fancybox/'
|
|
22
|
+
|
|
23
|
+
const props = defineProps({
|
|
24
|
+
/** Fancybox configuration options */
|
|
25
|
+
options: {
|
|
26
|
+
type: Object,
|
|
27
|
+
default: () => ({}),
|
|
28
|
+
},
|
|
29
|
+
/** CSS selector for bindable elements within the container */
|
|
30
|
+
selector: {
|
|
31
|
+
type: String,
|
|
32
|
+
default: '[data-fancybox]',
|
|
33
|
+
},
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
const containerRef = ref(null)
|
|
37
|
+
|
|
38
|
+
function bind() {
|
|
39
|
+
if (!containerRef.value) return
|
|
40
|
+
Fancybox.bind(containerRef.value, props.selector, { ...props.options })
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function unbind() {
|
|
44
|
+
if (!containerRef.value) return
|
|
45
|
+
Fancybox.unbind(containerRef.value)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
onMounted(() => bind())
|
|
49
|
+
|
|
50
|
+
onUpdated(() => {
|
|
51
|
+
unbind()
|
|
52
|
+
bind()
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
onUnmounted(() => {
|
|
56
|
+
unbind()
|
|
57
|
+
Fancybox.close()
|
|
58
|
+
})
|
|
59
|
+
</script>
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div>
|
|
3
3
|
<label v-if="label" class="block text-sm font-medium text-gray-700 mb-2">{{ label }}</label>
|
|
4
|
-
<
|
|
5
|
-
<a :href="modelValue"
|
|
4
|
+
<SparkFancybox v-if="modelValue" class="mb-2 relative inline-block">
|
|
5
|
+
<a :href="modelValue" data-fancybox="image-upload" :data-caption="label || ''">
|
|
6
6
|
<img
|
|
7
7
|
:src="modelValue"
|
|
8
8
|
:alt="label || 'Image preview'"
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
>
|
|
18
18
|
<font-awesome-icon :icon="Icons.farXmark" class="text-xs" />
|
|
19
19
|
</button>
|
|
20
|
-
</
|
|
20
|
+
</SparkFancybox>
|
|
21
21
|
<div
|
|
22
22
|
v-if="!modelValue"
|
|
23
23
|
class="relative rounded-md transition-colors"
|
|
@@ -51,6 +51,7 @@
|
|
|
51
51
|
import { ref, inject } from 'vue'
|
|
52
52
|
import { Icons } from '@/plugins/fontawesome'
|
|
53
53
|
import { sparkNotificationService } from '@/composables/sparkNotificationService'
|
|
54
|
+
import SparkFancybox from './SparkFancybox.vue'
|
|
54
55
|
|
|
55
56
|
const props = defineProps({
|
|
56
57
|
modelValue: {
|
package/src/components/index.js
CHANGED
|
@@ -8,6 +8,7 @@ export { default as SparkButton } from './SparkButton.vue'
|
|
|
8
8
|
export { default as SparkButtonGroup } from './SparkButtonGroup.vue'
|
|
9
9
|
export { default as SparkCard } from './SparkCard.vue'
|
|
10
10
|
export { default as SparkEntityBadge } from './SparkEntityBadge.vue'
|
|
11
|
+
export { default as SparkFancybox } from './SparkFancybox.vue'
|
|
11
12
|
export { default as SparkTooltip } from './SparkTooltip.vue'
|
|
12
13
|
export { default as SparkFileDragUpload } from './SparkFileDragUpload.vue'
|
|
13
14
|
export { default as SparkImageUpload } from './SparkImageUpload.vue'
|
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Spark Image Renderer
|
|
3
3
|
*
|
|
4
|
-
* Renders image thumbnails
|
|
4
|
+
* Renders image thumbnails with optional Fancybox lightbox support.
|
|
5
5
|
*
|
|
6
6
|
* Usage:
|
|
7
7
|
* {
|
|
8
8
|
* data: 'avatar',
|
|
9
9
|
* renderer: 'spark.image',
|
|
10
10
|
* rendererConfig: {
|
|
11
|
-
* size: 'md',
|
|
12
|
-
* rounded: true,
|
|
13
|
-
* alt: 'User avatar' // Alt text (or use row property name)
|
|
11
|
+
* size: 'md', // 'sm' | 'md' | 'lg'
|
|
12
|
+
* rounded: true, // true for circular, false for square
|
|
13
|
+
* alt: 'User avatar', // Alt text (or use row property name)
|
|
14
|
+
* lightbox: true, // Enable click-to-enlarge via Fancybox (requires SparkFancybox wrapper)
|
|
15
|
+
* group: 'gallery', // Fancybox gallery group name (default: 'table-images')
|
|
14
16
|
* }
|
|
15
17
|
* }
|
|
16
18
|
*/
|
|
@@ -37,6 +39,8 @@ export const imageRenderer = (sparkTable) => {
|
|
|
37
39
|
const size = config.size || 'md'
|
|
38
40
|
const sizeClass = sizes[size] || sizes.md
|
|
39
41
|
const rounded = config.rounded !== false // Default to true
|
|
42
|
+
const lightbox = config.lightbox || false
|
|
43
|
+
const group = config.group || 'table-images'
|
|
40
44
|
|
|
41
45
|
// Determine alt text
|
|
42
46
|
let alt = config.alt || ''
|
|
@@ -56,6 +60,17 @@ export const imageRenderer = (sparkTable) => {
|
|
|
56
60
|
img.classList.add('rounded')
|
|
57
61
|
}
|
|
58
62
|
|
|
59
|
-
|
|
63
|
+
if (lightbox) {
|
|
64
|
+
// Wrap in <a> with data-fancybox for lightbox support
|
|
65
|
+
const link = document.createElement('a')
|
|
66
|
+
link.href = value
|
|
67
|
+
link.setAttribute('data-fancybox', group)
|
|
68
|
+
if (alt) link.setAttribute('data-caption', alt)
|
|
69
|
+
img.classList.add('cursor-pointer', 'hover:opacity-80', 'transition-opacity')
|
|
70
|
+
link.appendChild(img)
|
|
71
|
+
td.appendChild(link)
|
|
72
|
+
} else {
|
|
73
|
+
td.appendChild(img)
|
|
74
|
+
}
|
|
60
75
|
}
|
|
61
76
|
}
|