@stachelock/ui 0.5.1 → 0.5.3
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/dist/{ProfileHeaderAvatar.vue_vue_type_script_setup_true_lang-DkABeWJt.js → ProfileHeaderAvatar.vue_vue_type_script_setup_true_lang-CKCoHD1o.js} +27 -31
- package/dist/ProfileHeaderAvatar.vue_vue_type_script_setup_true_lang-CKCoHD1o.js.map +1 -0
- package/dist/components/CloudinaryImage.js +35 -38
- package/dist/components/CloudinaryImage.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/layouts/ProfileHeaderAvatar.js +1 -1
- package/dist/style.css +1 -1
- package/dist/ui.css +1 -1
- package/package.json +1 -1
- package/dist/ProfileHeaderAvatar.vue_vue_type_script_setup_true_lang-DkABeWJt.js.map +0 -1
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { defineComponent as
|
|
2
|
-
import
|
|
3
|
-
const
|
|
4
|
-
key:
|
|
1
|
+
import { defineComponent as B, ref as m, computed as o, onMounted as I, onBeforeUnmount as U, createElementBlock as n, openBlock as a, createElementVNode as r, createVNode as j, createCommentVNode as u, normalizeStyle as v, normalizeClass as k, renderSlot as f, createBlock as R, toDisplayString as c, Transition as S, withCtx as M } from "vue";
|
|
2
|
+
import P from "./components/CloudinaryImage.js";
|
|
3
|
+
const T = { class: "sl-relative sl-flex sl-items-center sl-gap-3" }, V = ["aria-expanded"], O = {
|
|
4
|
+
key: 1,
|
|
5
5
|
class: "sl-w-full sl-h-full sl-inline-flex sl-items-center sl-justify-center sl-bg-stachelock-200 dark:sl-bg-stachelock-700"
|
|
6
6
|
}, A = { class: "sl-p-4 sl-border-b sl-border-gray-200 dark:sl-border-slate-700" }, D = { class: "sl-text-sm sl-font-medium sl-text-gray-900 dark:sl-text-white" }, H = { class: "sl-text-xs sl-text-gray-500 dark:sl-text-slate-400" }, K = {
|
|
7
7
|
key: 0,
|
|
8
8
|
class: "sl-py-1"
|
|
9
|
-
}, J = /* @__PURE__ */
|
|
9
|
+
}, J = /* @__PURE__ */ B({
|
|
10
10
|
__name: "ProfileHeaderAvatar",
|
|
11
11
|
props: {
|
|
12
12
|
userName: {},
|
|
@@ -22,62 +22,58 @@ const P = { class: "sl-relative sl-flex sl-items-center sl-gap-3" }, T = ["aria-
|
|
|
22
22
|
},
|
|
23
23
|
emits: ["logout", "menu-toggle"],
|
|
24
24
|
setup(e, { expose: y, emit: b }) {
|
|
25
|
-
const s = e, d = b, l = m(!1), x = m(null), p = m(null), w =
|
|
25
|
+
const s = e, d = b, l = m(!1), x = m(null), p = m(null), w = o(() => !!s.imagePublicId || !!s.imageUrl), C = o(() => s.userName ? s.userName.split(" ").map((t) => t[0]).join("").toUpperCase().slice(0, 2) : "U"), z = o(() => `hover:sl-ring-2 hover:${s.ringColorClass}`), E = o(() => `sl-ring-2 ${s.ringColorClass}`), L = o(() => s.size < 32 ? "sl-text-xs" : s.size < 48 ? "sl-text-sm" : "sl-text-base"), N = o(() => ({
|
|
26
26
|
top: s.menuTop,
|
|
27
27
|
right: s.menuRight
|
|
28
28
|
})), g = () => {
|
|
29
29
|
l.value = !l.value, d("menu-toggle", l.value);
|
|
30
30
|
}, i = () => {
|
|
31
31
|
l.value && (l.value = !1, d("menu-toggle", !1));
|
|
32
|
-
},
|
|
32
|
+
}, $ = () => {
|
|
33
33
|
i(), d("logout");
|
|
34
34
|
}, h = (t) => {
|
|
35
35
|
t.key === "Escape" && i();
|
|
36
36
|
};
|
|
37
|
-
return
|
|
37
|
+
return I(() => {
|
|
38
38
|
document.addEventListener("keydown", h);
|
|
39
|
-
}),
|
|
39
|
+
}), U(() => {
|
|
40
40
|
document.removeEventListener("keydown", h);
|
|
41
41
|
}), y({
|
|
42
42
|
toggleMenu: g,
|
|
43
43
|
closeMenu: i,
|
|
44
44
|
isMenuOpen: l
|
|
45
|
-
}), (t, q) => (a(),
|
|
45
|
+
}), (t, q) => (a(), n("div", T, [
|
|
46
46
|
r("button", {
|
|
47
47
|
ref_key: "avatarButton",
|
|
48
48
|
ref: x,
|
|
49
49
|
type: "button",
|
|
50
50
|
onClick: g,
|
|
51
51
|
class: k(["sl-relative sl-inline-flex sl-items-center sl-justify-center sl-rounded-full sl-overflow-hidden sl-transition-all sl-flex-shrink-0 focus:sl-outline-none", [
|
|
52
|
-
|
|
53
|
-
{ [
|
|
52
|
+
z.value,
|
|
53
|
+
{ [E.value]: l.value }
|
|
54
54
|
]]),
|
|
55
55
|
style: v({ width: `${e.size}px`, height: `${e.size}px` }),
|
|
56
56
|
"aria-expanded": l.value,
|
|
57
57
|
"aria-haspopup": "true"
|
|
58
58
|
}, [
|
|
59
59
|
f(t.$slots, "avatar", {}, () => [
|
|
60
|
-
|
|
60
|
+
w.value ? (a(), R(P, {
|
|
61
61
|
key: 0,
|
|
62
|
+
src: e.imageUrl,
|
|
62
63
|
"public-id": e.imagePublicId,
|
|
63
64
|
alt: e.userName,
|
|
64
65
|
width: e.size,
|
|
65
66
|
height: e.size,
|
|
66
67
|
"custom-classes": { image: { "sl-w-full sl-h-full sl-object-cover sl-object-center": !0 } },
|
|
67
68
|
skeleton: "user"
|
|
68
|
-
}, null, 8, ["public-id", "alt", "width", "height"])) :
|
|
69
|
-
key: 1,
|
|
70
|
-
src: e.imageUrl,
|
|
71
|
-
alt: e.userName,
|
|
72
|
-
class: "sl-w-full sl-h-full sl-object-cover sl-object-center"
|
|
73
|
-
}, null, 8, V)) : (a(), o("div", O, [
|
|
69
|
+
}, null, 8, ["src", "public-id", "alt", "width", "height"])) : (a(), n("div", O, [
|
|
74
70
|
r("span", {
|
|
75
|
-
class: k(["sl-font-semibold sl-text-stachelock-700 dark:sl-text-stachelock-200",
|
|
76
|
-
}, c(
|
|
71
|
+
class: k(["sl-font-semibold sl-text-stachelock-700 dark:sl-text-stachelock-200", L.value])
|
|
72
|
+
}, c(C.value), 3)
|
|
77
73
|
]))
|
|
78
74
|
])
|
|
79
|
-
], 14,
|
|
80
|
-
|
|
75
|
+
], 14, V),
|
|
76
|
+
j(S, {
|
|
81
77
|
"enter-active-class": "sl-transition sl-ease-out sl-duration-100",
|
|
82
78
|
"enter-from-class": "sl-transform sl-opacity-0 sl-scale-95",
|
|
83
79
|
"enter-to-class": "sl-transform sl-opacity-100 sl-scale-100",
|
|
@@ -85,13 +81,13 @@ const P = { class: "sl-relative sl-flex sl-items-center sl-gap-3" }, T = ["aria-
|
|
|
85
81
|
"leave-from-class": "sl-transform sl-opacity-100 sl-scale-100",
|
|
86
82
|
"leave-to-class": "sl-transform sl-opacity-0 sl-scale-95"
|
|
87
83
|
}, {
|
|
88
|
-
default:
|
|
89
|
-
l.value ? (a(),
|
|
84
|
+
default: M(() => [
|
|
85
|
+
l.value ? (a(), n("div", {
|
|
90
86
|
key: 0,
|
|
91
87
|
ref_key: "menuRef",
|
|
92
88
|
ref: p,
|
|
93
89
|
class: "sl-absolute sl-bg-white dark:sl-bg-slate-800 sl-rounded-lg sl-shadow-lg sl-border sl-border-gray-200 dark:sl-border-slate-700 sl-z-50 sl-min-w-max sl-overflow-hidden",
|
|
94
|
-
style: v(
|
|
90
|
+
style: v(N.value),
|
|
95
91
|
role: "menu",
|
|
96
92
|
"aria-orientation": "vertical"
|
|
97
93
|
}, [
|
|
@@ -101,13 +97,13 @@ const P = { class: "sl-relative sl-flex sl-items-center sl-gap-3" }, T = ["aria-
|
|
|
101
97
|
r("p", H, c(e.userEmail), 1)
|
|
102
98
|
])
|
|
103
99
|
]),
|
|
104
|
-
t.$slots["menu-items"] ? (a(),
|
|
100
|
+
t.$slots["menu-items"] ? (a(), n("div", K, [
|
|
105
101
|
f(t.$slots, "menu-items")
|
|
106
102
|
])) : u("", !0),
|
|
107
|
-
e.showLogout ? (a(),
|
|
103
|
+
e.showLogout ? (a(), n("button", {
|
|
108
104
|
key: 1,
|
|
109
105
|
type: "button",
|
|
110
|
-
onClick:
|
|
106
|
+
onClick: $,
|
|
111
107
|
class: "sl-w-full sl-text-left sl-px-4 sl-py-2 sl-text-sm sl-text-red-600 dark:sl-text-red-400 hover:sl-bg-red-50 dark:hover:sl-bg-red-900/20 sl-transition-colors",
|
|
112
108
|
role: "menuitem"
|
|
113
109
|
}, c(e.logoutLabel), 1)) : u("", !0)
|
|
@@ -115,7 +111,7 @@ const P = { class: "sl-relative sl-flex sl-items-center sl-gap-3" }, T = ["aria-
|
|
|
115
111
|
]),
|
|
116
112
|
_: 3
|
|
117
113
|
}),
|
|
118
|
-
l.value ? (a(),
|
|
114
|
+
l.value ? (a(), n("div", {
|
|
119
115
|
key: 0,
|
|
120
116
|
class: "sl-fixed sl-inset-0 sl-z-40",
|
|
121
117
|
onClick: i,
|
|
@@ -127,4 +123,4 @@ const P = { class: "sl-relative sl-flex sl-items-center sl-gap-3" }, T = ["aria-
|
|
|
127
123
|
export {
|
|
128
124
|
J as _
|
|
129
125
|
};
|
|
130
|
-
//# sourceMappingURL=ProfileHeaderAvatar.vue_vue_type_script_setup_true_lang-
|
|
126
|
+
//# sourceMappingURL=ProfileHeaderAvatar.vue_vue_type_script_setup_true_lang-CKCoHD1o.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ProfileHeaderAvatar.vue_vue_type_script_setup_true_lang-CKCoHD1o.js","sources":["../src/components/layouts/ProfileHeaderAvatar.vue"],"sourcesContent":["<!--\n @component ProfileHeaderAvatar\n @description User avatar with dropdown menu for profile actions.\n \n A flexible user avatar component that displays a profile image (via Cloudinary)\n or initials fallback, with an expandable dropdown menu showing user info and actions.\n \n @props\n - userName (string): Display name of the user\n - userEmail (string): Email address of the user\n - imagePublicId (string, optional): Cloudinary public_id for profile image\n - imageUrl (string, optional): Direct URL for profile image (fallback if no publicId)\n - showLogout (boolean): Show logout button in dropdown (default: true)\n - logoutLabel (string): Label for logout button (default: 'Log Out')\n - size (number): Avatar size in pixels (default: 40)\n - ringColor (string): Tailwind ring color class for hover/active state\n - menuPosition (object): Position overrides for dropdown menu\n \n @emits\n - logout: Emitted when logout button is clicked\n - menu-toggle: Emitted when menu is opened/closed with boolean state\n \n @slots\n - menu-header: Custom header content in dropdown (replaces default name/email)\n - menu-items: Additional menu items between user info and logout\n - avatar: Custom avatar content (replaces default image/initials)\n \n @example\n <ProfileHeaderAvatar\n user-name=\"John Doe\"\n user-email=\"john@example.com\"\n image-public-id=\"users/john-doe-avatar\"\n @logout=\"handleLogout\"\n />\n-->\n<template>\n <div class=\"sl-relative sl-flex sl-items-center sl-gap-3\">\n <!-- User Avatar Button -->\n <button \n ref=\"avatarButton\"\n type=\"button\"\n @click=\"toggleMenu\"\n class=\"sl-relative sl-inline-flex sl-items-center sl-justify-center sl-rounded-full sl-overflow-hidden sl-transition-all sl-flex-shrink-0 focus:sl-outline-none\"\n :class=\"[\n ringClasses,\n { [activeRingClass]: isMenuOpen }\n ]\"\n :style=\"{ width: `${size}px`, height: `${size}px` }\"\n :aria-expanded=\"isMenuOpen\"\n aria-haspopup=\"true\"\n >\n <slot name=\"avatar\">\n <!-- Cloudinary image if public_id or URL available -->\n <CloudinaryImage \n v-if=\"hasImage\" \n :src=\"imageUrl\"\n :public-id=\"imagePublicId\" \n :alt=\"userName\" \n :width=\"size\"\n :height=\"size\" \n :custom-classes=\"{ image: { 'sl-w-full sl-h-full sl-object-cover sl-object-center': true } }\" \n skeleton=\"user\" \n />\n <!-- Initials fallback -->\n <div \n v-else \n class=\"sl-w-full sl-h-full sl-inline-flex sl-items-center sl-justify-center sl-bg-stachelock-200 dark:sl-bg-stachelock-700\"\n >\n <span \n class=\"sl-font-semibold sl-text-stachelock-700 dark:sl-text-stachelock-200\"\n :class=\"initialsTextSize\"\n >\n {{ computedInitials }}\n </span>\n </div>\n </slot>\n </button>\n\n <!-- Dropdown Menu -->\n <Transition\n enter-active-class=\"sl-transition sl-ease-out sl-duration-100\"\n enter-from-class=\"sl-transform sl-opacity-0 sl-scale-95\"\n enter-to-class=\"sl-transform sl-opacity-100 sl-scale-100\"\n leave-active-class=\"sl-transition sl-ease-in sl-duration-75\"\n leave-from-class=\"sl-transform sl-opacity-100 sl-scale-100\"\n leave-to-class=\"sl-transform sl-opacity-0 sl-scale-95\"\n >\n <div \n v-if=\"isMenuOpen\"\n ref=\"menuRef\"\n class=\"sl-absolute sl-bg-white dark:sl-bg-slate-800 sl-rounded-lg sl-shadow-lg sl-border sl-border-gray-200 dark:sl-border-slate-700 sl-z-50 sl-min-w-max sl-overflow-hidden\"\n :style=\"menuStyles\"\n role=\"menu\"\n aria-orientation=\"vertical\"\n >\n <!-- Header with user info -->\n <div class=\"sl-p-4 sl-border-b sl-border-gray-200 dark:sl-border-slate-700\">\n <slot name=\"menu-header\">\n <p class=\"sl-text-sm sl-font-medium sl-text-gray-900 dark:sl-text-white\">{{ userName }}</p>\n <p class=\"sl-text-xs sl-text-gray-500 dark:sl-text-slate-400\">{{ userEmail }}</p>\n </slot>\n </div>\n \n <!-- Custom menu items slot -->\n <div v-if=\"$slots['menu-items']\" class=\"sl-py-1\">\n <slot name=\"menu-items\" />\n </div>\n \n <!-- Logout button -->\n <button \n v-if=\"showLogout\"\n type=\"button\"\n @click=\"handleLogout\"\n class=\"sl-w-full sl-text-left sl-px-4 sl-py-2 sl-text-sm sl-text-red-600 dark:sl-text-red-400 hover:sl-bg-red-50 dark:hover:sl-bg-red-900/20 sl-transition-colors\"\n role=\"menuitem\"\n >\n {{ logoutLabel }}\n </button>\n </div>\n </Transition>\n\n <!-- Backdrop for closing menu -->\n <div \n v-if=\"isMenuOpen\" \n class=\"sl-fixed sl-inset-0 sl-z-40\" \n @click=\"closeMenu\" \n aria-hidden=\"true\"\n />\n </div>\n</template>\n\n<script setup lang=\"ts\">\n/**\n * ProfileHeaderAvatar - User avatar with dropdown menu\n * \n * @module components/layouts/ProfileHeaderAvatar\n */\nimport { ref, computed, onMounted, onBeforeUnmount, type CSSProperties } from 'vue';\nimport CloudinaryImage from '../CloudinaryImage.vue';\n\ninterface Props {\n /** Display name of the user */\n userName: string;\n /** Email address of the user */\n userEmail?: string;\n /** Cloudinary public_id for profile image */\n imagePublicId?: string;\n /** Direct URL for profile image (fallback if no publicId) */\n imageUrl?: string;\n /** Show logout button in dropdown */\n showLogout?: boolean;\n /** Label for logout button */\n logoutLabel?: string;\n /** Avatar size in pixels */\n size?: number;\n /** Custom ring color class for hover/active state */\n ringColorClass?: string;\n /** Menu position from top */\n menuTop?: string;\n /** Menu position from right */\n menuRight?: string;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n userEmail: '',\n showLogout: true,\n logoutLabel: 'Log Out',\n size: 40,\n ringColorClass: 'sl-ring-stachelock-400',\n menuTop: '3rem',\n menuRight: '0',\n});\n\nconst emit = defineEmits<{\n /** Emitted when logout button is clicked */\n logout: [];\n /** Emitted when menu is opened/closed */\n 'menu-toggle': [isOpen: boolean];\n}>();\n\nconst isMenuOpen = ref(false);\nconst avatarButton = ref<HTMLButtonElement | null>(null);\nconst menuRef = ref<HTMLDivElement | null>(null);\n\n// Check if we have any image source\nconst hasImage = computed(() => {\n return !!props.imagePublicId || !!props.imageUrl;\n});\n\n// Computed initials from user name\nconst computedInitials = computed(() => {\n if (!props.userName) return 'U';\n return props.userName\n .split(' ')\n .map((n: string) => n[0])\n .join('')\n .toUpperCase()\n .slice(0, 2);\n});\n\n// Ring classes for hover and active states\nconst ringClasses = computed(() => {\n return `hover:sl-ring-2 hover:${props.ringColorClass}`;\n});\n\nconst activeRingClass = computed(() => {\n return `sl-ring-2 ${props.ringColorClass}`;\n});\n\n// Text size based on avatar size\nconst initialsTextSize = computed(() => {\n if (props.size < 32) return 'sl-text-xs';\n if (props.size < 48) return 'sl-text-sm';\n return 'sl-text-base';\n});\n\n// Menu positioning styles\nconst menuStyles = computed((): CSSProperties => ({\n top: props.menuTop,\n right: props.menuRight,\n}));\n\n// Toggle menu open/close\nconst toggleMenu = () => {\n isMenuOpen.value = !isMenuOpen.value;\n emit('menu-toggle', isMenuOpen.value);\n};\n\n// Close menu\nconst closeMenu = () => {\n if (isMenuOpen.value) {\n isMenuOpen.value = false;\n emit('menu-toggle', false);\n }\n};\n\n// Handle logout click\nconst handleLogout = () => {\n closeMenu();\n emit('logout');\n};\n\n// Handle escape key to close menu\nconst handleEscapeKey = (event: KeyboardEvent) => {\n if (event.key === 'Escape') {\n closeMenu();\n }\n};\n\nonMounted(() => {\n document.addEventListener('keydown', handleEscapeKey);\n});\n\nonBeforeUnmount(() => {\n document.removeEventListener('keydown', handleEscapeKey);\n});\n\n// Expose methods for parent components\ndefineExpose({\n toggleMenu,\n closeMenu,\n isMenuOpen,\n});\n</script>\n"],"names":["props","__props","emit","__emit","isMenuOpen","ref","avatarButton","menuRef","hasImage","computed","computedInitials","n","ringClasses","activeRingClass","initialsTextSize","menuStyles","toggleMenu","closeMenu","handleLogout","handleEscapeKey","event","onMounted","onBeforeUnmount","__expose","_openBlock","_createElementBlock","_hoisted_1","_createElementVNode","_normalizeStyle","_renderSlot","_ctx","_createBlock","CloudinaryImage","_hoisted_3","_normalizeClass","_createVNode","_Transition","_hoisted_4","_hoisted_5","_toDisplayString","_hoisted_6","$slots","_hoisted_7"],"mappings":"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"}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { createElementBlock as d, openBlock as u, createElementVNode as r, defineComponent as
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
function H(i, f) {
|
|
1
|
+
import { createElementBlock as d, openBlock as u, createElementVNode as r, defineComponent as Z, inject as E, ref as v, computed as l, watch as U, onMounted as D, onUnmounted as F, normalizeClass as n, normalizeStyle as C, withDirectives as g, createCommentVNode as W, createBlock as x, resolveDynamicComponent as k, vShow as y } from "vue";
|
|
2
|
+
import { _ as z } from "../_plugin-vue_export-helper-CHgC5LLL.js";
|
|
3
|
+
function O(i, f) {
|
|
5
4
|
return u(), d("svg", {
|
|
6
5
|
xmlns: "http://www.w3.org/2000/svg",
|
|
7
6
|
viewBox: "0 0 20 20",
|
|
@@ -16,7 +15,7 @@ function H(i, f) {
|
|
|
16
15
|
})
|
|
17
16
|
]);
|
|
18
17
|
}
|
|
19
|
-
function
|
|
18
|
+
function V(i, f) {
|
|
20
19
|
return u(), d("svg", {
|
|
21
20
|
xmlns: "http://www.w3.org/2000/svg",
|
|
22
21
|
viewBox: "0 0 20 20",
|
|
@@ -31,10 +30,10 @@ function G(i, f) {
|
|
|
31
30
|
})
|
|
32
31
|
]);
|
|
33
32
|
}
|
|
34
|
-
const
|
|
33
|
+
const H = { class: "sl-flex sl-h-full sl-w-full sl-items-center sl-justify-center" }, G = { class: "sl-flex sl-h-full sl-w-full sl-items-center sl-justify-center" }, J = {
|
|
35
34
|
key: 0,
|
|
36
35
|
class: "sl-h-full sl-w-full"
|
|
37
|
-
},
|
|
36
|
+
}, K = ["src", "alt"], Q = /* @__PURE__ */ Z({
|
|
38
37
|
__name: "CloudinaryImage",
|
|
39
38
|
props: {
|
|
40
39
|
/** Direct image URL - bypasses Cloudinary URL generation */
|
|
@@ -114,84 +113,82 @@ const J = { class: "sl-flex sl-h-full sl-w-full sl-items-center sl-justify-cente
|
|
|
114
113
|
},
|
|
115
114
|
emits: ["update:imageLoaded", "error"],
|
|
116
115
|
setup(i, { emit: f }) {
|
|
117
|
-
const b =
|
|
116
|
+
const b = E("cloudinary", {}), s = v(!1), o = v(!1), c = v(!0), w = f, e = i, m = (t) => t ? t.startsWith("http://") || t.startsWith("https://") || t.startsWith("//") : !1, p = l(() => e.src && m(e.src) ? e.src : e.asset?.secure_url ? e.asset.secure_url : e.asset?.url ? e.asset.url : e.publicId && m(e.publicId) ? e.publicId : e.imagePublicId && m(e.imagePublicId) ? e.imagePublicId : null), _ = l(() => p.value ? null : e.asset?.public_id ? e.asset.public_id : e.imagePublicId || e.publicId || e.fallbackPublicId || null), P = l(() => {
|
|
118
117
|
if (!_.value) return null;
|
|
119
118
|
const t = b?.cloudName || "demo", S = b?.baseUrl || `https://res.cloudinary.com/${t}/image/upload`, a = [];
|
|
120
119
|
e.width && e.width !== "auto" && a.push(`w_${e.width}`), e.height && e.height !== "auto" && a.push(`h_${e.height}`), e.quality && a.push(`q_${e.quality}`), e.devicePixelRatio && a.push(`dpr_${e.devicePixelRatio}`), a.push("f_auto"), a.push("c_fill");
|
|
121
|
-
const
|
|
122
|
-
return `${S}/${
|
|
123
|
-
}), h = l(() => p.value ? p.value :
|
|
120
|
+
const M = a.join(",");
|
|
121
|
+
return `${S}/${M}/${_.value}`;
|
|
122
|
+
}), h = l(() => p.value ? p.value : P.value), I = l(() => e.skeleton === "user" ? V : O), $ = l(() => {
|
|
124
123
|
const t = {};
|
|
125
124
|
return e.width && e.width !== "auto" && (t.width = typeof e.width == "number" ? `${e.width}px` : e.width), e.height && e.height !== "auto" && (t.height = typeof e.height == "number" ? `${e.height}px` : e.height), e.aspectRatio && (t.aspectRatio = String(e.aspectRatio)), t;
|
|
126
|
-
}),
|
|
125
|
+
}), q = l(() => ({
|
|
127
126
|
"sl-relative sl-overflow-hidden": !0,
|
|
128
127
|
...e.customClasses?.div
|
|
129
|
-
})),
|
|
128
|
+
})), j = l(() => ({
|
|
130
129
|
"sl-h-full sl-w-full sl-text-gray-200": !0,
|
|
131
130
|
...e.customClasses?.skeleton
|
|
132
|
-
})),
|
|
131
|
+
})), N = l(() => ({
|
|
133
132
|
"sl-h-full sl-w-full sl-text-gray-300": !0,
|
|
134
133
|
...e.customClasses?.fallback
|
|
135
|
-
})),
|
|
134
|
+
})), A = l(() => ({
|
|
136
135
|
"sl-h-full sl-w-full sl-object-cover": !0,
|
|
137
136
|
...e.customClasses?.image
|
|
138
|
-
})),
|
|
137
|
+
})), R = l(() => ({
|
|
139
138
|
objectFit: "cover"
|
|
140
|
-
})),
|
|
139
|
+
})), B = () => {
|
|
141
140
|
s.value = !0, o.value = !1, w("update:imageLoaded", !0);
|
|
142
|
-
},
|
|
141
|
+
}, L = (t) => {
|
|
143
142
|
c.value && (o.value = !0, s.value = !1, w("error", t));
|
|
144
143
|
};
|
|
145
|
-
return
|
|
144
|
+
return U(
|
|
146
145
|
() => h.value,
|
|
147
146
|
() => {
|
|
148
147
|
s.value = !1, o.value = !1;
|
|
149
148
|
}
|
|
150
|
-
),
|
|
149
|
+
), D(() => {
|
|
151
150
|
c.value = !0;
|
|
152
|
-
}),
|
|
151
|
+
}), F(() => {
|
|
153
152
|
c.value = !1;
|
|
154
153
|
}), (t, S) => (u(), d("div", {
|
|
155
|
-
style: C(
|
|
156
|
-
class: n(
|
|
154
|
+
style: C($.value),
|
|
155
|
+
class: n(q.value)
|
|
157
156
|
}, [
|
|
158
|
-
g(r("div",
|
|
157
|
+
g(r("div", H, [
|
|
159
158
|
r("div", {
|
|
160
159
|
role: "status",
|
|
161
160
|
class: n([{ "sl-animate-pulse": i.pulse }])
|
|
162
161
|
}, [
|
|
163
162
|
(u(), x(k(I.value), {
|
|
164
|
-
class: n(
|
|
163
|
+
class: n(j.value)
|
|
165
164
|
}, null, 8, ["class"]))
|
|
166
165
|
], 2)
|
|
167
166
|
], 512), [
|
|
168
167
|
[y, !s.value && !o.value]
|
|
169
168
|
]),
|
|
170
|
-
g(r("div",
|
|
169
|
+
g(r("div", G, [
|
|
171
170
|
(u(), x(k(I.value), {
|
|
172
|
-
class: n(
|
|
171
|
+
class: n(N.value)
|
|
173
172
|
}, null, 8, ["class"]))
|
|
174
173
|
], 512), [
|
|
175
174
|
[y, o.value && !s.value]
|
|
176
175
|
]),
|
|
177
|
-
h.value && c.value ? g((u(), d("div",
|
|
176
|
+
h.value && c.value ? g((u(), d("div", J, [
|
|
178
177
|
r("img", {
|
|
179
178
|
src: h.value,
|
|
180
179
|
alt: i.alt,
|
|
181
|
-
onLoad:
|
|
182
|
-
onError:
|
|
183
|
-
class: n(
|
|
184
|
-
style: C(
|
|
185
|
-
}, null, 46,
|
|
180
|
+
onLoad: B,
|
|
181
|
+
onError: L,
|
|
182
|
+
class: n(A.value),
|
|
183
|
+
style: C(R.value)
|
|
184
|
+
}, null, 46, K)
|
|
186
185
|
], 512)), [
|
|
187
186
|
[y, s.value]
|
|
188
|
-
]) :
|
|
187
|
+
]) : W("", !0)
|
|
189
188
|
], 6));
|
|
190
189
|
}
|
|
191
|
-
});
|
|
192
|
-
typeof P == "function" && P($);
|
|
193
|
-
const te = /* @__PURE__ */ V($, [["__scopeId", "data-v-18ba2d71"]]);
|
|
190
|
+
}), Y = /* @__PURE__ */ z(Q, [["__scopeId", "data-v-2a9fe480"]]);
|
|
194
191
|
export {
|
|
195
|
-
|
|
192
|
+
Y as default
|
|
196
193
|
};
|
|
197
194
|
//# sourceMappingURL=CloudinaryImage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CloudinaryImage.js","sources":["../../node_modules/@heroicons/vue/20/solid/esm/PhotoIcon.js","../../node_modules/@heroicons/vue/20/solid/esm/UserCircleIcon.js","../../src/components/CloudinaryImage.vue"],"sourcesContent":["import { createElementVNode as _createElementVNode, openBlock as _openBlock, createElementBlock as _createElementBlock } from \"vue\"\n\nexport default function render(_ctx, _cache) {\n return (_openBlock(), _createElementBlock(\"svg\", {\n xmlns: \"http://www.w3.org/2000/svg\",\n viewBox: \"0 0 20 20\",\n fill: \"currentColor\",\n \"aria-hidden\": \"true\",\n \"data-slot\": \"icon\"\n }, [\n _createElementVNode(\"path\", {\n \"fill-rule\": \"evenodd\",\n d: \"M1 5.25A2.25 2.25 0 0 1 3.25 3h13.5A2.25 2.25 0 0 1 19 5.25v9.5A2.25 2.25 0 0 1 16.75 17H3.25A2.25 2.25 0 0 1 1 14.75v-9.5Zm1.5 5.81v3.69c0 .414.336.75.75.75h13.5a.75.75 0 0 0 .75-.75v-2.69l-2.22-2.219a.75.75 0 0 0-1.06 0l-1.91 1.909.47.47a.75.75 0 1 1-1.06 1.06L6.53 8.091a.75.75 0 0 0-1.06 0l-2.97 2.97ZM12 7a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\",\n \"clip-rule\": \"evenodd\"\n })\n ]))\n}","import { createElementVNode as _createElementVNode, openBlock as _openBlock, createElementBlock as _createElementBlock } from \"vue\"\n\nexport default function render(_ctx, _cache) {\n return (_openBlock(), _createElementBlock(\"svg\", {\n xmlns: \"http://www.w3.org/2000/svg\",\n viewBox: \"0 0 20 20\",\n fill: \"currentColor\",\n \"aria-hidden\": \"true\",\n \"data-slot\": \"icon\"\n }, [\n _createElementVNode(\"path\", {\n \"fill-rule\": \"evenodd\",\n d: \"M18 10a8 8 0 1 1-16 0 8 8 0 0 1 16 0Zm-5.5-2.5a2.5 2.5 0 1 1-5 0 2.5 2.5 0 0 1 5 0ZM10 12a5.99 5.99 0 0 0-4.793 2.39A6.483 6.483 0 0 0 10 16.5a6.483 6.483 0 0 0 4.793-2.11A5.99 5.99 0 0 0 10 12Z\",\n \"clip-rule\": \"evenodd\"\n })\n ]))\n}","<!--\n @component CloudinaryImage\n @description Cloudinary image component with loading states and fallbacks.\n \n Displays images from Cloudinary with automatic transformations, loading\n skeleton, error fallback, and flexible sizing options.\n \n @props\n - src (string, optional): Direct image URL (bypasses Cloudinary URL generation)\n - publicId (string, optional): Cloudinary public ID\n - imagePublicId (string, optional): Alias for publicId (for compatibility)\n - asset (CloudinaryAsset, optional): Full asset object with transformations\n - fallbackPublicId (string, optional): Fallback image public ID\n - transformations (array, optional): Additional Cloudinary transformations\n - alt (string, optional): Alt text for accessibility\n - aspectRatio (string|number, optional): Aspect ratio (e.g., '16/9')\n - width (string|number, optional): Width in pixels or 'auto'\n - height (string|number, optional): Height in pixels or 'auto'\n - quality (string|number, optional): Image quality (1-100 or 'auto')\n - skeleton (string, optional): Skeleton type - 'user' or 'photo'\n - pulse (boolean, optional): Animate skeleton\n \n @emits\n - update:imageLoaded: Emitted when image load state changes\n - error: Emitted on image load error\n \n @example\n <!-- Using direct URL -->\n <CloudinaryImage\n src=\"https://res.cloudinary.com/demo/image/upload/sample.jpg\"\n :width=\"200\"\n :height=\"200\"\n alt=\"Sample image\"\n />\n \n @example\n <!-- Using public ID with auto-generated URL -->\n <CloudinaryImage\n public-id=\"avatars/user123\"\n :width=\"200\"\n :height=\"200\"\n alt=\"User avatar\"\n skeleton=\"user\"\n />\n-->\n<template>\n <div :style=\"computedDivStyle\" :class=\"computedDivClass\">\n <!-- Loading skeleton -->\n <div v-show=\"!imageLoaded && !imageError\" class=\"sl-flex sl-h-full sl-w-full sl-items-center sl-justify-center\">\n <div role=\"status\" :class=\"[{ 'sl-animate-pulse': pulse }]\">\n <component :is=\"skeletonComponent\" :class=\"computedSkeletonClass\" />\n </div>\n </div>\n\n <!-- Error fallback -->\n <div v-show=\"imageError && !imageLoaded\" class=\"sl-flex sl-h-full sl-w-full sl-items-center sl-justify-center\">\n <component :is=\"skeletonComponent\" :class=\"computedFallbackClass\" />\n </div>\n\n <!-- Image -->\n <div v-if=\"computedImg && isMounted\" v-show=\"imageLoaded\" class=\"sl-h-full sl-w-full\">\n <img\n :src=\"computedImg\"\n :alt=\"alt\"\n @load=\"onImageLoad\"\n @error=\"onImageError\"\n :class=\"computedImageClass\"\n :style=\"computedImageStyle\"\n />\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\n/**\n * CloudinaryImage - Image component with Cloudinary CDN support\n * \n * Provides a comprehensive image component with loading states, error handling,\n * and Cloudinary transformations. Uses plugin configuration for Cloudinary setup.\n * \n * ## Features\n * - Automatic loading skeleton\n * - Error fallback display\n * - Cloudinary URL generation\n * - Responsive sizing\n * - Aspect ratio control\n * - Quality optimization\n * \n * ## Plugin Configuration\n * Configure Cloudinary in your app setup:\n * ```typescript\n * app.use(StachelockUI, {\n * cloudinary: {\n * cloudName: 'your-cloud-name',\n * defaultTransformations: [...]\n * }\n * })\n * ```\n * \n * @module components/CloudinaryImage\n * @see {@link CloudinaryImageProps} for prop interface\n */\nimport { UserCircleIcon, PhotoIcon } from '@heroicons/vue/20/solid';\nimport { computed, inject, onMounted, onUnmounted, ref, watch } from 'vue';\nimport type { PropType } from 'vue';\nimport type { CloudinaryAsset, CloudinaryTransformationStep } from '../types/core';\n\n// Plugin configuration injection\nconst cloudinaryConfig = inject<{\n cloudName?: string;\n baseUrl?: string;\n defaultTransformations?: CloudinaryTransformationStep[];\n}>('cloudinary', {});\n\ninterface CustomClasses {\n div?: Record<string, boolean>;\n skeleton?: Record<string, boolean>;\n image?: Record<string, boolean>;\n fallback?: Record<string, boolean>;\n}\n\n// State\nconst imageLoaded = ref(false);\nconst imageError = ref(false);\nconst isMounted = ref(true);\n\nconst emit = defineEmits<{\n 'update:imageLoaded': [value: boolean];\n 'error': [error: unknown];\n}>();\n\nconst props = defineProps({\n /** Direct image URL - bypasses Cloudinary URL generation */\n src: {\n type: String,\n required: false,\n default: null\n },\n /** Cloudinary public ID */\n publicId: {\n type: String,\n required: false,\n default: null\n },\n /** Alias for publicId (for compatibility with different naming conventions) */\n imagePublicId: {\n type: String,\n required: false,\n default: null\n },\n asset: {\n type: Object as PropType<CloudinaryAsset | null>,\n default: null,\n required: false\n },\n fallbackPublicId: {\n type: String,\n required: false,\n default: null\n },\n /** Fallback URL to use if primary image fails */\n fallbackSrc: {\n type: String,\n required: false,\n default: null\n },\n transformations: {\n type: Array as PropType<Array<(image: unknown) => void>>,\n default: () => []\n },\n alt: {\n type: String,\n default: ''\n },\n aspectRatio: {\n type: [String, Number] as PropType<string | number>,\n default: null\n },\n width: {\n type: [String, Number] as PropType<string | number>,\n default: 64\n },\n height: {\n type: [String, Number] as PropType<string | number>,\n default: 64\n },\n quality: {\n type: [String, Number],\n default: '90'\n },\n devicePixelRatio: {\n type: String,\n default: '2.0'\n },\n skeleton: {\n type: String as PropType<'user' | 'photo'>,\n default: 'photo'\n },\n pulse: {\n type: Boolean,\n default: true\n },\n customClasses: {\n type: Object as PropType<CustomClasses>,\n default: () => ({})\n }\n});\n\n/**\n * Helper to check if a string is a full URL\n */\nconst isFullUrl = (value: string | null | undefined): boolean => {\n if (!value) return false;\n return value.startsWith('http://') || value.startsWith('https://') || value.startsWith('//');\n};\n\n// Computed: Direct URL source (if provided)\nconst directSrc = computed(() => {\n // Check src prop first\n if (props.src && isFullUrl(props.src)) {\n return props.src;\n }\n \n // Check if asset has secure_url or url\n if (props.asset?.secure_url) {\n return props.asset.secure_url;\n }\n if ((props.asset as any)?.url) {\n return (props.asset as any).url;\n }\n \n // Check if publicId or imagePublicId is actually a full URL\n if (props.publicId && isFullUrl(props.publicId)) {\n return props.publicId;\n }\n if (props.imagePublicId && isFullUrl(props.imagePublicId)) {\n return props.imagePublicId;\n }\n \n return null;\n});\n\n// Computed: Effective public ID (when not using direct URL)\nconst effectivePublicId = computed(() => {\n // If we have a direct URL, we don't need a public ID\n if (directSrc.value) return null;\n \n if (props.asset?.public_id) {\n return props.asset.public_id;\n }\n return props.imagePublicId || props.publicId || props.fallbackPublicId || null;\n});\n\n// Computed: Generate Cloudinary URL from public ID\nconst generatedCloudinaryUrl = computed(() => {\n if (!effectivePublicId.value) return null;\n \n const cloudName = cloudinaryConfig?.cloudName || 'demo';\n const baseUrl = cloudinaryConfig?.baseUrl || `https://res.cloudinary.com/${cloudName}/image/upload`;\n \n // Build transformation string\n const transformations: string[] = [];\n \n // Add width/height\n if (props.width && props.width !== 'auto') {\n transformations.push(`w_${props.width}`);\n }\n if (props.height && props.height !== 'auto') {\n transformations.push(`h_${props.height}`);\n }\n \n // Add quality\n if (props.quality) {\n transformations.push(`q_${props.quality}`);\n }\n \n // Add DPR\n if (props.devicePixelRatio) {\n transformations.push(`dpr_${props.devicePixelRatio}`);\n }\n \n // Auto format\n transformations.push('f_auto');\n \n // Crop mode\n transformations.push('c_fill');\n \n const transformString = transformations.join(',');\n \n return `${baseUrl}/${transformString}/${effectivePublicId.value}`;\n});\n\n// Computed: Final image URL (prefers direct URL over generated)\nconst computedImg = computed(() => {\n // Use direct URL if available\n if (directSrc.value) {\n return directSrc.value;\n }\n \n // Otherwise use generated Cloudinary URL\n return generatedCloudinaryUrl.value;\n});\n\n// Skeleton component based on type\nconst skeletonComponent = computed(() => {\n return props.skeleton === 'user' ? UserCircleIcon : PhotoIcon;\n});\n\n// Style computations\nconst computedDivStyle = computed(() => {\n const style: Record<string, string> = {};\n \n if (props.width && props.width !== 'auto') {\n style.width = typeof props.width === 'number' ? `${props.width}px` : props.width;\n }\n if (props.height && props.height !== 'auto') {\n style.height = typeof props.height === 'number' ? `${props.height}px` : props.height;\n }\n if (props.aspectRatio) {\n style.aspectRatio = String(props.aspectRatio);\n }\n \n return style;\n});\n\nconst computedDivClass = computed(() => ({\n 'sl-relative sl-overflow-hidden': true,\n ...props.customClasses?.div\n}));\n\nconst computedSkeletonClass = computed(() => ({\n 'sl-h-full sl-w-full sl-text-gray-200': true,\n ...props.customClasses?.skeleton\n}));\n\nconst computedFallbackClass = computed(() => ({\n 'sl-h-full sl-w-full sl-text-gray-300': true,\n ...props.customClasses?.fallback\n}));\n\nconst computedImageClass = computed(() => ({\n 'sl-h-full sl-w-full sl-object-cover': true,\n ...props.customClasses?.image\n}));\n\nconst computedImageStyle = computed(() => ({\n objectFit: 'cover' as const,\n}));\n\n// Event handlers\nconst onImageLoad = () => {\n imageLoaded.value = true;\n imageError.value = false;\n emit('update:imageLoaded', true);\n};\n\nconst onImageError = (error: Event) => {\n if (!isMounted.value) return;\n \n imageError.value = true;\n imageLoaded.value = false;\n emit('error', error);\n};\n\n// Reset state when source changes\nwatch(\n () => computedImg.value,\n () => {\n imageLoaded.value = false;\n imageError.value = false;\n }\n);\n\n// Lifecycle\nonMounted(() => {\n isMounted.value = true;\n});\n\nonUnmounted(() => {\n isMounted.value = false;\n});\n</script>\n\n<style scoped>\n/* Prevent layout shift */\n[data-loading=\"true\"] {\n min-height: 20px;\n}\n</style>\n\n"],"names":["render","_ctx","_cache","_openBlock","_createElementBlock","_createElementVNode","cloudinaryConfig","inject","imageLoaded","ref","imageError","isMounted","emit","__emit","props","__props","isFullUrl","value","directSrc","computed","effectivePublicId","generatedCloudinaryUrl","cloudName","baseUrl","transformations","transformString","computedImg","skeletonComponent","UserCircleIcon","PhotoIcon","computedDivStyle","style","computedDivClass","computedSkeletonClass","computedFallbackClass","computedImageClass","computedImageStyle","onImageLoad","onImageError","error","watch","onMounted","onUnmounted","_withDirectives","_hoisted_1","_createBlock","_resolveDynamicComponent","_vShow","_hoisted_2","_hoisted_3"],"mappings":"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","x_google_ignoreList":[0,1]}
|
|
1
|
+
{"version":3,"file":"CloudinaryImage.js","sources":["../../node_modules/@heroicons/vue/20/solid/esm/PhotoIcon.js","../../node_modules/@heroicons/vue/20/solid/esm/UserCircleIcon.js","../../src/components/CloudinaryImage.vue"],"sourcesContent":["import { createElementVNode as _createElementVNode, openBlock as _openBlock, createElementBlock as _createElementBlock } from \"vue\"\n\nexport default function render(_ctx, _cache) {\n return (_openBlock(), _createElementBlock(\"svg\", {\n xmlns: \"http://www.w3.org/2000/svg\",\n viewBox: \"0 0 20 20\",\n fill: \"currentColor\",\n \"aria-hidden\": \"true\",\n \"data-slot\": \"icon\"\n }, [\n _createElementVNode(\"path\", {\n \"fill-rule\": \"evenodd\",\n d: \"M1 5.25A2.25 2.25 0 0 1 3.25 3h13.5A2.25 2.25 0 0 1 19 5.25v9.5A2.25 2.25 0 0 1 16.75 17H3.25A2.25 2.25 0 0 1 1 14.75v-9.5Zm1.5 5.81v3.69c0 .414.336.75.75.75h13.5a.75.75 0 0 0 .75-.75v-2.69l-2.22-2.219a.75.75 0 0 0-1.06 0l-1.91 1.909.47.47a.75.75 0 1 1-1.06 1.06L6.53 8.091a.75.75 0 0 0-1.06 0l-2.97 2.97ZM12 7a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z\",\n \"clip-rule\": \"evenodd\"\n })\n ]))\n}","import { createElementVNode as _createElementVNode, openBlock as _openBlock, createElementBlock as _createElementBlock } from \"vue\"\n\nexport default function render(_ctx, _cache) {\n return (_openBlock(), _createElementBlock(\"svg\", {\n xmlns: \"http://www.w3.org/2000/svg\",\n viewBox: \"0 0 20 20\",\n fill: \"currentColor\",\n \"aria-hidden\": \"true\",\n \"data-slot\": \"icon\"\n }, [\n _createElementVNode(\"path\", {\n \"fill-rule\": \"evenodd\",\n d: \"M18 10a8 8 0 1 1-16 0 8 8 0 0 1 16 0Zm-5.5-2.5a2.5 2.5 0 1 1-5 0 2.5 2.5 0 0 1 5 0ZM10 12a5.99 5.99 0 0 0-4.793 2.39A6.483 6.483 0 0 0 10 16.5a6.483 6.483 0 0 0 4.793-2.11A5.99 5.99 0 0 0 10 12Z\",\n \"clip-rule\": \"evenodd\"\n })\n ]))\n}","<!--\n @component CloudinaryImage\n @description Cloudinary image component with loading states and fallbacks.\n \n Displays images from Cloudinary with automatic transformations, loading\n skeleton, error fallback, and flexible sizing options.\n \n @props\n - src (string, optional): Direct image URL (bypasses Cloudinary URL generation)\n - publicId (string, optional): Cloudinary public ID\n - imagePublicId (string, optional): Alias for publicId (for compatibility)\n - asset (CloudinaryAsset, optional): Full asset object with transformations\n - fallbackPublicId (string, optional): Fallback image public ID\n - transformations (array, optional): Additional Cloudinary transformations\n - alt (string, optional): Alt text for accessibility\n - aspectRatio (string|number, optional): Aspect ratio (e.g., '16/9')\n - width (string|number, optional): Width in pixels or 'auto'\n - height (string|number, optional): Height in pixels or 'auto'\n - quality (string|number, optional): Image quality (1-100 or 'auto')\n - skeleton (string, optional): Skeleton type - 'user' or 'photo'\n - pulse (boolean, optional): Animate skeleton\n \n @emits\n - update:imageLoaded: Emitted when image load state changes\n - error: Emitted on image load error\n \n @example Using direct URL\n ```vue\n <CloudinaryImage\n src=\"https://res.cloudinary.com/demo/image/upload/sample.jpg\"\n :width=\"200\"\n :height=\"200\"\n alt=\"Sample image\"\n />\n ```\n \n @example Using public ID with auto-generated URL\n ```vue\n <CloudinaryImage\n public-id=\"avatars/user123\"\n :width=\"200\"\n :height=\"200\"\n alt=\"User avatar\"\n skeleton=\"user\"\n />\n ```\n-->\n<template>\n <div :style=\"computedDivStyle\" :class=\"computedDivClass\">\n <!-- Loading skeleton -->\n <div v-show=\"!imageLoaded && !imageError\" class=\"sl-flex sl-h-full sl-w-full sl-items-center sl-justify-center\">\n <div role=\"status\" :class=\"[{ 'sl-animate-pulse': pulse }]\">\n <component :is=\"skeletonComponent\" :class=\"computedSkeletonClass\" />\n </div>\n </div>\n\n <!-- Error fallback -->\n <div v-show=\"imageError && !imageLoaded\" class=\"sl-flex sl-h-full sl-w-full sl-items-center sl-justify-center\">\n <component :is=\"skeletonComponent\" :class=\"computedFallbackClass\" />\n </div>\n\n <!-- Image -->\n <div v-if=\"computedImg && isMounted\" v-show=\"imageLoaded\" class=\"sl-h-full sl-w-full\">\n <img\n :src=\"computedImg\"\n :alt=\"alt\"\n @load=\"onImageLoad\"\n @error=\"onImageError\"\n :class=\"computedImageClass\"\n :style=\"computedImageStyle\"\n />\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\n/**\n * CloudinaryImage - Image component with Cloudinary CDN support\n * \n * Provides a comprehensive image component with loading states, error handling,\n * and Cloudinary transformations. Uses plugin configuration for Cloudinary setup.\n * \n * ## Features\n * - Automatic loading skeleton\n * - Error fallback display\n * - Cloudinary URL generation\n * - Responsive sizing\n * - Aspect ratio control\n * - Quality optimization\n * \n * ## Plugin Configuration\n * Configure Cloudinary in your app setup:\n * ```typescript\n * app.use(StachelockUI, {\n * cloudinary: {\n * cloudName: 'your-cloud-name',\n * defaultTransformations: [...]\n * }\n * })\n * ```\n * \n * @module components/CloudinaryImage\n * @see {@link CloudinaryImageProps} for prop interface\n */\nimport { UserCircleIcon, PhotoIcon } from '@heroicons/vue/20/solid';\nimport { computed, inject, onMounted, onUnmounted, ref, watch } from 'vue';\nimport type { PropType } from 'vue';\nimport type { CloudinaryAsset, CloudinaryTransformationStep } from '../types/core';\n\n// Plugin configuration injection\nconst cloudinaryConfig = inject<{\n cloudName?: string;\n baseUrl?: string;\n defaultTransformations?: CloudinaryTransformationStep[];\n}>('cloudinary', {});\n\ninterface CustomClasses {\n div?: Record<string, boolean>;\n skeleton?: Record<string, boolean>;\n image?: Record<string, boolean>;\n fallback?: Record<string, boolean>;\n}\n\n// State\nconst imageLoaded = ref(false);\nconst imageError = ref(false);\nconst isMounted = ref(true);\n\nconst emit = defineEmits<{\n 'update:imageLoaded': [value: boolean];\n 'error': [error: unknown];\n}>();\n\nconst props = defineProps({\n /** Direct image URL - bypasses Cloudinary URL generation */\n src: {\n type: String,\n required: false,\n default: null\n },\n /** Cloudinary public ID */\n publicId: {\n type: String,\n required: false,\n default: null\n },\n /** Alias for publicId (for compatibility with different naming conventions) */\n imagePublicId: {\n type: String,\n required: false,\n default: null\n },\n asset: {\n type: Object as PropType<CloudinaryAsset | null>,\n default: null,\n required: false\n },\n fallbackPublicId: {\n type: String,\n required: false,\n default: null\n },\n /** Fallback URL to use if primary image fails */\n fallbackSrc: {\n type: String,\n required: false,\n default: null\n },\n transformations: {\n type: Array as PropType<Array<(image: unknown) => void>>,\n default: () => []\n },\n alt: {\n type: String,\n default: ''\n },\n aspectRatio: {\n type: [String, Number] as PropType<string | number>,\n default: null\n },\n width: {\n type: [String, Number] as PropType<string | number>,\n default: 64\n },\n height: {\n type: [String, Number] as PropType<string | number>,\n default: 64\n },\n quality: {\n type: [String, Number],\n default: '90'\n },\n devicePixelRatio: {\n type: String,\n default: '2.0'\n },\n skeleton: {\n type: String as PropType<'user' | 'photo'>,\n default: 'photo'\n },\n pulse: {\n type: Boolean,\n default: true\n },\n customClasses: {\n type: Object as PropType<CustomClasses>,\n default: () => ({})\n }\n});\n\n/**\n * Helper to check if a string is a full URL\n */\nconst isFullUrl = (value: string | null | undefined): boolean => {\n if (!value) return false;\n return value.startsWith('http://') || value.startsWith('https://') || value.startsWith('//');\n};\n\n// Computed: Direct URL source (if provided)\nconst directSrc = computed(() => {\n // Check src prop first\n if (props.src && isFullUrl(props.src)) {\n return props.src;\n }\n \n // Check if asset has secure_url or url\n if (props.asset?.secure_url) {\n return props.asset.secure_url;\n }\n if ((props.asset as any)?.url) {\n return (props.asset as any).url;\n }\n \n // Check if publicId or imagePublicId is actually a full URL\n if (props.publicId && isFullUrl(props.publicId)) {\n return props.publicId;\n }\n if (props.imagePublicId && isFullUrl(props.imagePublicId)) {\n return props.imagePublicId;\n }\n \n return null;\n});\n\n// Computed: Effective public ID (when not using direct URL)\nconst effectivePublicId = computed(() => {\n // If we have a direct URL, we don't need a public ID\n if (directSrc.value) return null;\n \n if (props.asset?.public_id) {\n return props.asset.public_id;\n }\n return props.imagePublicId || props.publicId || props.fallbackPublicId || null;\n});\n\n// Computed: Generate Cloudinary URL from public ID\nconst generatedCloudinaryUrl = computed(() => {\n if (!effectivePublicId.value) return null;\n \n const cloudName = cloudinaryConfig?.cloudName || 'demo';\n const baseUrl = cloudinaryConfig?.baseUrl || `https://res.cloudinary.com/${cloudName}/image/upload`;\n \n // Build transformation string\n const transformations: string[] = [];\n \n // Add width/height\n if (props.width && props.width !== 'auto') {\n transformations.push(`w_${props.width}`);\n }\n if (props.height && props.height !== 'auto') {\n transformations.push(`h_${props.height}`);\n }\n \n // Add quality\n if (props.quality) {\n transformations.push(`q_${props.quality}`);\n }\n \n // Add DPR\n if (props.devicePixelRatio) {\n transformations.push(`dpr_${props.devicePixelRatio}`);\n }\n \n // Auto format\n transformations.push('f_auto');\n \n // Crop mode\n transformations.push('c_fill');\n \n const transformString = transformations.join(',');\n \n return `${baseUrl}/${transformString}/${effectivePublicId.value}`;\n});\n\n// Computed: Final image URL (prefers direct URL over generated)\nconst computedImg = computed(() => {\n // Use direct URL if available\n if (directSrc.value) {\n return directSrc.value;\n }\n \n // Otherwise use generated Cloudinary URL\n return generatedCloudinaryUrl.value;\n});\n\n// Skeleton component based on type\nconst skeletonComponent = computed(() => {\n return props.skeleton === 'user' ? UserCircleIcon : PhotoIcon;\n});\n\n// Style computations\nconst computedDivStyle = computed(() => {\n const style: Record<string, string> = {};\n \n if (props.width && props.width !== 'auto') {\n style.width = typeof props.width === 'number' ? `${props.width}px` : props.width;\n }\n if (props.height && props.height !== 'auto') {\n style.height = typeof props.height === 'number' ? `${props.height}px` : props.height;\n }\n if (props.aspectRatio) {\n style.aspectRatio = String(props.aspectRatio);\n }\n \n return style;\n});\n\nconst computedDivClass = computed(() => ({\n 'sl-relative sl-overflow-hidden': true,\n ...props.customClasses?.div\n}));\n\nconst computedSkeletonClass = computed(() => ({\n 'sl-h-full sl-w-full sl-text-gray-200': true,\n ...props.customClasses?.skeleton\n}));\n\nconst computedFallbackClass = computed(() => ({\n 'sl-h-full sl-w-full sl-text-gray-300': true,\n ...props.customClasses?.fallback\n}));\n\nconst computedImageClass = computed(() => ({\n 'sl-h-full sl-w-full sl-object-cover': true,\n ...props.customClasses?.image\n}));\n\nconst computedImageStyle = computed(() => ({\n objectFit: 'cover' as const,\n}));\n\n// Event handlers\nconst onImageLoad = () => {\n imageLoaded.value = true;\n imageError.value = false;\n emit('update:imageLoaded', true);\n};\n\nconst onImageError = (error: Event) => {\n if (!isMounted.value) return;\n \n imageError.value = true;\n imageLoaded.value = false;\n emit('error', error);\n};\n\n// Reset state when source changes\nwatch(\n () => computedImg.value,\n () => {\n imageLoaded.value = false;\n imageError.value = false;\n }\n);\n\n// Lifecycle\nonMounted(() => {\n isMounted.value = true;\n});\n\nonUnmounted(() => {\n isMounted.value = false;\n});\n</script>\n\n<style scoped>\n/* Prevent layout shift */\n[data-loading=\"true\"] {\n min-height: 20px;\n}\n</style>\n\n"],"names":["render","_ctx","_cache","_openBlock","_createElementBlock","_createElementVNode","cloudinaryConfig","inject","imageLoaded","ref","imageError","isMounted","emit","__emit","props","__props","isFullUrl","value","directSrc","computed","effectivePublicId","generatedCloudinaryUrl","cloudName","baseUrl","transformations","transformString","computedImg","skeletonComponent","UserCircleIcon","PhotoIcon","computedDivStyle","style","computedDivClass","computedSkeletonClass","computedFallbackClass","computedImageClass","computedImageStyle","onImageLoad","onImageError","error","watch","onMounted","onUnmounted","_withDirectives","_hoisted_1","_createBlock","_resolveDynamicComponent","_vShow","_hoisted_2","_hoisted_3"],"mappings":"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","x_google_ignoreList":[0,1]}
|
package/dist/index.js
CHANGED
|
@@ -58,7 +58,7 @@ import { _ as So } from "./DefaultLayout.vue_vue_type_script_setup_true_lang-BZA
|
|
|
58
58
|
import { _ as Io } from "./HeaderLayout.vue_vue_type_script_setup_true_lang-BY2G6hCc.js";
|
|
59
59
|
import { _ as Vo } from "./NavigationGroup.vue_vue_type_script_setup_true_lang-BWq5fpEm.js";
|
|
60
60
|
import { _ as Ao } from "./NavigationItem.vue_vue_type_script_setup_true_lang-C8aX-84Q.js";
|
|
61
|
-
import { _ as Lo } from "./ProfileHeaderAvatar.vue_vue_type_script_setup_true_lang-
|
|
61
|
+
import { _ as Lo } from "./ProfileHeaderAvatar.vue_vue_type_script_setup_true_lang-CKCoHD1o.js";
|
|
62
62
|
import { _ as Fo } from "./ProjectLogo.vue_vue_type_script_setup_true_lang-DYjp-RNh.js";
|
|
63
63
|
import { _ as zo } from "./SidebarLayout.vue_vue_type_script_setup_true_lang-BJ5jadgZ.js";
|
|
64
64
|
import { _ as No } from "./UiMapAll.vue_vue_type_script_setup_true_lang-CMAyvJMk.js";
|