@place-framework/place-block-image 1.0.3 → 1.0.5

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 +1 @@
1
- "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const a=require("react"),E="image-",o={LAZY:"lazy",LOADED:"loaded",WRAPPER_SUFFIX:"wrapper"},I=e=>e.replace(/^https?:\/\/[^/]+/,"").replace(/^[/\\]+/,"").replace(/\.[^/.]+$/,"").toLowerCase().replace(/[^a-z0-9/-]/g,"-").replace(/\//g,"-").replace(/-+/g,"-").replace(/^-|-$/g,"");function d(e,t){return t?e.replace(new RegExp(`^${t.replace(/\//g,"\\/")}\\/?`),""):e}function L(e,t,n){return e?`${t}${I(d(e,n))}`:""}function P(e,t,n,r=""){return[`${t}${o.WRAPPER_SUFFIX}`,L(e,t,n),r].filter(Boolean).join(" ")}function v(e,t){return e?t?`${o.LAZY} ${o.LOADED}`:o.LAZY:""}function R(e,t,n=.1){const r=new IntersectionObserver(s=>{s.forEach(c=>{c.isIntersecting&&(t(),r.unobserve(c.target))})},{threshold:n});return r.observe(e),r}const i=({src:e,alt:t,imagePrefix:n=E,lazy:r=!1,className:s="",...c})=>{const u=a.useRef(null),[g,p]=a.useState(r?"":e),[l,f]=a.useState(!r),_=typeof __PLUGIN_ASSET_PATH__<"u"?__PLUGIN_ASSET_PATH__:"";a.useEffect(()=>{if(!r||l||!u.current)return;const S=R(u.current,()=>{p(e),f(!0)});return()=>S.disconnect()},[e,r,l]);const m=P(e,n,_,s),A=v(r,l);return a.createElement("picture",{className:m},a.createElement("img",{ref:u,src:g,alt:t,className:A,...c}))};exports.PlaceBlockImage=i;exports.default=i;
1
+ Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}});var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},s=(n,r,a)=>(a=n==null?{}:e(i(n)),o(r||!n||!n.__esModule?t(a,`default`,{value:n,enumerable:!0}):a,n));let c=require("react");c=s(c);var l=`image-`,u={LAZY:`lazy`,LOADED:`loaded`,WRAPPER_SUFFIX:`wrapper`},d=e=>e.replace(/^https?:\/\/[^/]+/,``).replace(/^[/\\]+/,``).replace(/\.[^/.]+$/,``).toLowerCase().replace(/[^a-z0-9/-]/g,`-`).replace(/\//g,`-`).replace(/-+/g,`-`).replace(/^-|-$/g,``);function f(e,t){return t?e.replace(RegExp(`^${t.replace(/\//g,`\\/`)}\\/?`),``):e}function p(e,t,n){return e?`${t}${d(f(e,n))}`:``}function m(e,t,n,r=``){return[`${t}${u.WRAPPER_SUFFIX}`,p(e,t,n),r].filter(Boolean).join(` `)}function h(e,t){return e?t?`${u.LAZY} ${u.LOADED}`:u.LAZY:``}function g(e,t,n=.1){let r=new IntersectionObserver(e=>{e.forEach(e=>{e.isIntersecting&&(t(),r.unobserve(e.target))})},{threshold:n});return r.observe(e),r}var _=({src:e,alt:t,imagePrefix:n=l,lazy:r=!1,className:i=``,...a})=>{let o=(0,c.useRef)(null),[s,u]=(0,c.useState)(r?``:e),[d,f]=(0,c.useState)(!r),p=typeof __PLUGIN_ASSET_PATH__<`u`?__PLUGIN_ASSET_PATH__:``;(0,c.useEffect)(()=>{if(!r||d||!o.current)return;let t=g(o.current,()=>{u(e),f(!0)});return()=>t.disconnect()},[e,r,d]);let _=m(e,n,p,i),v=h(r,d);return c.default.createElement(`picture`,{className:_},c.default.createElement(`img`,{ref:o,src:s,alt:t,className:v,...a}))};exports.PlaceBlockImage=_,exports.default=_;
@@ -0,0 +1,18 @@
1
+ import { default as React } from 'react';
2
+ interface PlaceBlockImageProps extends React.ImgHTMLAttributes<HTMLImageElement> {
3
+ src: string;
4
+ alt: string;
5
+ imagePrefix?: string;
6
+ lazy?: boolean;
7
+ }
8
+ /**
9
+ * PlaceBlockImage — prevents layout shift using CSS custom properties.
10
+ * Import: import PlaceBlockImage from '@place-framework/place-block-image/react'
11
+ *
12
+ * Usage:
13
+ * <PlaceBlockImage src="/assets/logo.png" alt="Logo" />
14
+ * <PlaceBlockImage src="/assets/hero.jpg" alt="Hero" lazy={true} />
15
+ */
16
+ export declare const PlaceBlockImage: React.FC<PlaceBlockImageProps>;
17
+ export default PlaceBlockImage;
18
+ //# sourceMappingURL=PlaceBlockImage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PlaceBlockImage.d.ts","sourceRoot":"","sources":["../../src/react/PlaceBlockImage.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAsC,MAAM,OAAO,CAAC;AAI3D,UAAU,oBAAqB,SAAQ,KAAK,CAAC,iBAAiB,CAAC,gBAAgB,CAAC;IAC9E,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,oBAAoB,CAuC1D,CAAC;AAEF,eAAe,eAAe,CAAC"}
@@ -1,67 +1,57 @@
1
- import l, { useRef as I, useState as i, useEffect as L } from "react";
2
- const S = "image-", c = {
3
- // Lazy loading states
4
- LAZY: "lazy",
5
- LOADED: "loaded",
6
- // Suffix appended to imagePrefix to form the wrapper class (e.g. 'image-wrapper')
7
- WRAPPER_SUFFIX: "wrapper"
8
- }, P = (e) => e.replace(/^https?:\/\/[^/]+/, "").replace(/^[/\\]+/, "").replace(/\.[^/.]+$/, "").toLowerCase().replace(/[^a-z0-9/-]/g, "-").replace(/\//g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
9
- function d(e, t) {
10
- return t ? e.replace(new RegExp(`^${t.replace(/\//g, "\\/")}\\/?`), "") : e;
1
+ import e, { useEffect as t, useRef as n, useState as r } from "react";
2
+ //#region src/constants/index.ts
3
+ var i = "image-", a = {
4
+ LAZY: "lazy",
5
+ LOADED: "loaded",
6
+ WRAPPER_SUFFIX: "wrapper"
7
+ }, o = (e) => e.replace(/^https?:\/\/[^/]+/, "").replace(/^[/\\]+/, "").replace(/\.[^/.]+$/, "").toLowerCase().replace(/[^a-z0-9/-]/g, "-").replace(/\//g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
8
+ function s(e, t) {
9
+ return t ? e.replace(RegExp(`^${t.replace(/\//g, "\\/")}\\/?`), "") : e;
11
10
  }
12
- function R(e, t, n) {
13
- return e ? `${t}${P(d(e, n))}` : "";
11
+ function c(e, t, n) {
12
+ return e ? `${t}${o(s(e, n))}` : "";
14
13
  }
15
- function $(e, t, n, r = "") {
16
- return [
17
- `${t}${c.WRAPPER_SUFFIX}`,
18
- R(e, t, n),
19
- r
20
- ].filter(Boolean).join(" ");
14
+ function l(e, t, n, r = "") {
15
+ return [
16
+ `${t}${a.WRAPPER_SUFFIX}`,
17
+ c(e, t, n),
18
+ r
19
+ ].filter(Boolean).join(" ");
21
20
  }
22
- function v(e, t) {
23
- return e ? t ? `${c.LAZY} ${c.LOADED}` : c.LAZY : "";
21
+ function u(e, t) {
22
+ return e ? t ? `${a.LAZY} ${a.LOADED}` : a.LAZY : "";
24
23
  }
25
- function C(e, t, n = 0.1) {
26
- const r = new IntersectionObserver(
27
- (a) => {
28
- a.forEach((s) => {
29
- s.isIntersecting && (t(), r.unobserve(s.target));
30
- });
31
- },
32
- { threshold: n }
33
- );
34
- return r.observe(e), r;
24
+ function d(e, t, n = .1) {
25
+ let r = new IntersectionObserver((e) => {
26
+ e.forEach((e) => {
27
+ e.isIntersecting && (t(), r.unobserve(e.target));
28
+ });
29
+ }, { threshold: n });
30
+ return r.observe(e), r;
35
31
  }
36
- const b = ({
37
- src: e,
38
- alt: t,
39
- imagePrefix: n = S,
40
- lazy: r = !1,
41
- className: a = "",
42
- ...s
43
- }) => {
44
- const o = I(null), [p, f] = i(r ? "" : e), [u, g] = i(!r), m = typeof __PLUGIN_ASSET_PATH__ < "u" ? __PLUGIN_ASSET_PATH__ : "";
45
- L(() => {
46
- if (!r || u || !o.current) return;
47
- const E = C(o.current, () => {
48
- f(e), g(!0);
49
- });
50
- return () => E.disconnect();
51
- }, [e, r, u]);
52
- const _ = $(e, n, m, a), A = v(r, u);
53
- return /* @__PURE__ */ l.createElement("picture", { className: _ }, /* @__PURE__ */ l.createElement(
54
- "img",
55
- {
56
- ref: o,
57
- src: p,
58
- alt: t,
59
- className: A,
60
- ...s
61
- }
62
- ));
63
- };
64
- export {
65
- b as PlaceBlockImage,
66
- b as default
32
+ //#endregion
33
+ //#region src/react/PlaceBlockImage.tsx
34
+ var f = ({ src: a, alt: o, imagePrefix: s = i, lazy: c = !1, className: f = "", ...p }) => {
35
+ let m = n(null), [h, g] = r(c ? "" : a), [_, v] = r(!c), y = typeof __PLUGIN_ASSET_PATH__ < "u" ? __PLUGIN_ASSET_PATH__ : "";
36
+ t(() => {
37
+ if (!c || _ || !m.current) return;
38
+ let e = d(m.current, () => {
39
+ g(a), v(!0);
40
+ });
41
+ return () => e.disconnect();
42
+ }, [
43
+ a,
44
+ c,
45
+ _
46
+ ]);
47
+ let b = l(a, s, y, f), x = u(c, _);
48
+ return /* @__PURE__ */ e.createElement("picture", { className: b }, /* @__PURE__ */ e.createElement("img", {
49
+ ref: m,
50
+ src: h,
51
+ alt: o,
52
+ className: x,
53
+ ...p
54
+ }));
67
55
  };
56
+ //#endregion
57
+ export { f as PlaceBlockImage, f as default };
@@ -1 +1 @@
1
- "use strict";const e=require("vue"),d="image-",i={LAZY:"lazy",LOADED:"loaded",WRAPPER_SUFFIX:"wrapper"},A=r=>r.replace(/^https?:\/\/[^/]+/,"").replace(/^[/\\]+/,"").replace(/\.[^/.]+$/,"").toLowerCase().replace(/[^a-z0-9/-]/g,"-").replace(/\//g,"-").replace(/-+/g,"-").replace(/^-|-$/g,"");function y(r,a){return a?r.replace(new RegExp(`^${a.replace(/\//g,"\\/")}\\/?`),""):r}function L(r,a,t){return r?`${a}${A(y(r,t))}`:""}function P(r,a,t,s=""){return[`${a}${i.WRAPPER_SUFFIX}`,L(r,a,t),s].filter(Boolean).join(" ")}function E(r,a){return r?a?`${i.LAZY} ${i.LOADED}`:i.LAZY:""}function S(r,a,t=.1){const s=new IntersectionObserver(l=>{l.forEach(n=>{n.isIntersecting&&(a(),s.unobserve(n.target))})},{threshold:t});return s.observe(r),s}const z=["src","alt"],I=e.defineComponent({inheritAttrs:!1,__name:"PlaceBlockImage",props:{src:{type:String,required:!0},alt:{type:String,required:!0},imagePrefix:{type:String,default:()=>d},lazy:{type:Boolean,default:!1}},setup(r){const a=e.useAttrs(),t=r,s=e.computed(()=>{const{class:o,...g}=a;return g}),l=e.ref(null),n=e.ref(t.lazy?"":t.src),c=e.ref(!t.lazy);let u=null;const m=typeof __PLUGIN_ASSET_PATH__<"u"?__PLUGIN_ASSET_PATH__:"",_=e.computed(()=>P(t.src,t.imagePrefix,m)),v=e.computed(()=>E(t.lazy,c.value)),f=()=>{!t.lazy||c.value||!l.value||(u=S(l.value,()=>{n.value=t.src,c.value=!0}))},p=()=>{u&&(u.disconnect(),u=null)};return e.onMounted(()=>{f()}),e.onUnmounted(()=>{p()}),e.watch(()=>t.src,o=>{t.lazy?c.value||(p(),f()):n.value=o}),e.watch(c,o=>{o&&(n.value=t.src,p())}),(o,g)=>(e.openBlock(),e.createElementBlock("picture",{class:e.normalizeClass([_.value,e.unref(a).class])},[e.createElementVNode("img",e.mergeProps({ref_key:"imgRef",ref:l,src:n.value,alt:r.alt,class:v.value},s.value),null,16,z)],2))}});module.exports=I;
1
+ let e=require("vue");var t=`image-`,n={LAZY:`lazy`,LOADED:`loaded`,WRAPPER_SUFFIX:`wrapper`},r=e=>e.replace(/^https?:\/\/[^/]+/,``).replace(/^[/\\]+/,``).replace(/\.[^/.]+$/,``).toLowerCase().replace(/[^a-z0-9/-]/g,`-`).replace(/\//g,`-`).replace(/-+/g,`-`).replace(/^-|-$/g,``);function i(e,t){return t?e.replace(RegExp(`^${t.replace(/\//g,`\\/`)}\\/?`),``):e}function a(e,t,n){return e?`${t}${r(i(e,n))}`:``}function o(e,t,r,i=``){return[`${t}${n.WRAPPER_SUFFIX}`,a(e,t,r),i].filter(Boolean).join(` `)}function s(e,t){return e?t?`${n.LAZY} ${n.LOADED}`:n.LAZY:``}function c(e,t,n=.1){let r=new IntersectionObserver(e=>{e.forEach(e=>{e.isIntersecting&&(t(),r.unobserve(e.target))})},{threshold:n});return r.observe(e),r}var l=[`src`,`alt`],u=(0,e.defineComponent)({inheritAttrs:!1,__name:`PlaceBlockImage`,props:{src:{type:String,required:!0},alt:{type:String,required:!0},imagePrefix:{type:String,default:()=>t},lazy:{type:Boolean,default:!1}},setup(t){let n=(0,e.useAttrs)(),r=t,i=(0,e.computed)(()=>{let{class:e,...t}=n;return t}),a=(0,e.ref)(null),u=(0,e.ref)(r.lazy?``:r.src),d=(0,e.ref)(!r.lazy),f=null,p=typeof __PLUGIN_ASSET_PATH__<`u`?__PLUGIN_ASSET_PATH__:``,m=(0,e.computed)(()=>o(r.src,r.imagePrefix,p)),h=(0,e.computed)(()=>s(r.lazy,d.value)),g=()=>{!r.lazy||d.value||!a.value||(f=c(a.value,()=>{u.value=r.src,d.value=!0}))},_=()=>{f&&=(f.disconnect(),null)};return(0,e.onMounted)(()=>{g()}),(0,e.onUnmounted)(()=>{_()}),(0,e.watch)(()=>r.src,e=>{r.lazy?d.value||(_(),g()):u.value=e}),(0,e.watch)(d,e=>{e&&(u.value=r.src,_())}),(r,o)=>((0,e.openBlock)(),(0,e.createElementBlock)(`picture`,{class:(0,e.normalizeClass)([m.value,(0,e.unref)(n).class])},[(0,e.createElementVNode)(`img`,(0,e.mergeProps)({ref_key:`imgRef`,ref:a,src:u.value,alt:t.alt,class:h.value},i.value),null,16,l)],2))}});module.exports=u;
@@ -0,0 +1,41 @@
1
+ import { DefineComponent, ExtractPropTypes, ComponentOptionsMixin, PublicProps, ComponentProvideOptions } from 'vue';
2
+ declare const __VLS_export: DefineComponent<ExtractPropTypes<{
3
+ src: {
4
+ type: StringConstructor;
5
+ required: true;
6
+ };
7
+ alt: {
8
+ type: StringConstructor;
9
+ required: true;
10
+ };
11
+ imagePrefix: {
12
+ type: StringConstructor;
13
+ default: () => string;
14
+ };
15
+ lazy: {
16
+ type: BooleanConstructor;
17
+ default: boolean;
18
+ };
19
+ }>, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {}, string, PublicProps, Readonly< ExtractPropTypes<{
20
+ src: {
21
+ type: StringConstructor;
22
+ required: true;
23
+ };
24
+ alt: {
25
+ type: StringConstructor;
26
+ required: true;
27
+ };
28
+ imagePrefix: {
29
+ type: StringConstructor;
30
+ default: () => string;
31
+ };
32
+ lazy: {
33
+ type: BooleanConstructor;
34
+ default: boolean;
35
+ };
36
+ }>> & Readonly<{}>, {
37
+ lazy: boolean;
38
+ imagePrefix: string;
39
+ }, {}, {}, {}, string, ComponentProvideOptions, true, {}, any>;
40
+ declare const _default: typeof __VLS_export;
41
+ export default _default;
@@ -1,83 +1,84 @@
1
- import { defineComponent as y, useAttrs as L, computed as p, ref as f, onMounted as P, onUnmounted as E, watch as _, openBlock as S, createElementBlock as z, normalizeClass as I, unref as C, createElementVNode as $, mergeProps as h } from "vue";
2
- const R = "image-", u = {
3
- // Lazy loading states
4
- LAZY: "lazy",
5
- LOADED: "loaded",
6
- // Suffix appended to imagePrefix to form the wrapper class (e.g. 'image-wrapper')
7
- WRAPPER_SUFFIX: "wrapper"
8
- }, b = (t) => t.replace(/^https?:\/\/[^/]+/, "").replace(/^[/\\]+/, "").replace(/\.[^/.]+$/, "").toLowerCase().replace(/[^a-z0-9/-]/g, "-").replace(/\//g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
9
- function w(t, r) {
10
- return r ? t.replace(new RegExp(`^${r.replace(/\//g, "\\/")}\\/?`), "") : t;
1
+ import { computed as e, createElementBlock as t, createElementVNode as n, defineComponent as r, mergeProps as i, normalizeClass as a, onMounted as o, onUnmounted as s, openBlock as c, ref as l, unref as u, useAttrs as d, watch as f } from "vue";
2
+ //#region src/constants/index.ts
3
+ var p = "image-", m = {
4
+ LAZY: "lazy",
5
+ LOADED: "loaded",
6
+ WRAPPER_SUFFIX: "wrapper"
7
+ }, h = (e) => e.replace(/^https?:\/\/[^/]+/, "").replace(/^[/\\]+/, "").replace(/\.[^/.]+$/, "").toLowerCase().replace(/[^a-z0-9/-]/g, "-").replace(/\//g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
8
+ function g(e, t) {
9
+ return t ? e.replace(RegExp(`^${t.replace(/\//g, "\\/")}\\/?`), "") : e;
11
10
  }
12
- function N(t, r, e) {
13
- return t ? `${r}${b(w(t, e))}` : "";
11
+ function _(e, t, n) {
12
+ return e ? `${t}${h(g(e, n))}` : "";
14
13
  }
15
- function B(t, r, e, a = "") {
16
- return [
17
- `${r}${u.WRAPPER_SUFFIX}`,
18
- N(t, r, e),
19
- a
20
- ].filter(Boolean).join(" ");
14
+ function v(e, t, n, r = "") {
15
+ return [
16
+ `${t}${m.WRAPPER_SUFFIX}`,
17
+ _(e, t, n),
18
+ r
19
+ ].filter(Boolean).join(" ");
21
20
  }
22
- function F(t, r) {
23
- return t ? r ? `${u.LAZY} ${u.LOADED}` : u.LAZY : "";
21
+ function y(e, t) {
22
+ return e ? t ? `${m.LAZY} ${m.LOADED}` : m.LAZY : "";
24
23
  }
25
- function O(t, r, e = 0.1) {
26
- const a = new IntersectionObserver(
27
- (s) => {
28
- s.forEach((n) => {
29
- n.isIntersecting && (r(), a.unobserve(n.target));
30
- });
31
- },
32
- { threshold: e }
33
- );
34
- return a.observe(t), a;
24
+ function b(e, t, n = .1) {
25
+ let r = new IntersectionObserver((e) => {
26
+ e.forEach((e) => {
27
+ e.isIntersecting && (t(), r.unobserve(e.target));
28
+ });
29
+ }, { threshold: n });
30
+ return r.observe(e), r;
35
31
  }
36
- const U = ["src", "alt"], x = /* @__PURE__ */ y({
37
- inheritAttrs: !1,
38
- __name: "PlaceBlockImage",
39
- props: {
40
- src: { type: String, required: !0 },
41
- alt: { type: String, required: !0 },
42
- imagePrefix: { type: String, default: () => R },
43
- lazy: { type: Boolean, default: !1 }
44
- },
45
- setup(t) {
46
- const r = L(), e = t, a = p(() => {
47
- const { class: c, ...m } = r;
48
- return m;
49
- }), s = f(null), n = f(e.lazy ? "" : e.src), l = f(!e.lazy);
50
- let o = null;
51
- const v = typeof __PLUGIN_ASSET_PATH__ < "u" ? __PLUGIN_ASSET_PATH__ : "", d = p(
52
- () => B(e.src, e.imagePrefix, v)
53
- ), A = p(() => F(e.lazy, l.value)), g = () => {
54
- !e.lazy || l.value || !s.value || (o = O(s.value, () => {
55
- n.value = e.src, l.value = !0;
56
- }));
57
- }, i = () => {
58
- o && (o.disconnect(), o = null);
59
- };
60
- return P(() => {
61
- g();
62
- }), E(() => {
63
- i();
64
- }), _(() => e.src, (c) => {
65
- e.lazy ? l.value || (i(), g()) : n.value = c;
66
- }), _(l, (c) => {
67
- c && (n.value = e.src, i());
68
- }), (c, m) => (S(), z("picture", {
69
- class: I([d.value, C(r).class])
70
- }, [
71
- $("img", h({
72
- ref_key: "imgRef",
73
- ref: s,
74
- src: n.value,
75
- alt: t.alt,
76
- class: A.value
77
- }, a.value), null, 16, U)
78
- ], 2));
79
- }
32
+ //#endregion
33
+ //#region src/vue/PlaceBlockImage.vue?vue&type=script&setup=true&lang.ts
34
+ var x = ["src", "alt"], S = /* @__PURE__ */ r({
35
+ inheritAttrs: !1,
36
+ __name: "PlaceBlockImage",
37
+ props: {
38
+ src: {
39
+ type: String,
40
+ required: !0
41
+ },
42
+ alt: {
43
+ type: String,
44
+ required: !0
45
+ },
46
+ imagePrefix: {
47
+ type: String,
48
+ default: () => p
49
+ },
50
+ lazy: {
51
+ type: Boolean,
52
+ default: !1
53
+ }
54
+ },
55
+ setup(r) {
56
+ let p = d(), m = r, h = e(() => {
57
+ let { class: e, ...t } = p;
58
+ return t;
59
+ }), g = l(null), _ = l(m.lazy ? "" : m.src), S = l(!m.lazy), C = null, w = typeof __PLUGIN_ASSET_PATH__ < "u" ? __PLUGIN_ASSET_PATH__ : "", T = e(() => v(m.src, m.imagePrefix, w)), E = e(() => y(m.lazy, S.value)), D = () => {
60
+ !m.lazy || S.value || !g.value || (C = b(g.value, () => {
61
+ _.value = m.src, S.value = !0;
62
+ }));
63
+ }, O = () => {
64
+ C &&= (C.disconnect(), null);
65
+ };
66
+ return o(() => {
67
+ D();
68
+ }), s(() => {
69
+ O();
70
+ }), f(() => m.src, (e) => {
71
+ m.lazy ? S.value || (O(), D()) : _.value = e;
72
+ }), f(S, (e) => {
73
+ e && (_.value = m.src, O());
74
+ }), (e, o) => (c(), t("picture", { class: a([T.value, u(p).class]) }, [n("img", i({
75
+ ref_key: "imgRef",
76
+ ref: g,
77
+ src: _.value,
78
+ alt: r.alt,
79
+ class: E.value
80
+ }, h.value), null, 16, x)], 2));
81
+ }
80
82
  });
81
- export {
82
- x as default
83
- };
83
+ //#endregion
84
+ export { S as default };
@@ -0,0 +1 @@
1
+ export { default as PlaceBlockImage } from './PlaceBlockImage';
@@ -0,0 +1,8 @@
1
+ export declare const IMAGE_PREFIX = "image-";
2
+ export declare const CLASS_NAMES: {
3
+ readonly LAZY: "lazy";
4
+ readonly LOADED: "loaded";
5
+ readonly WRAPPER_SUFFIX: "wrapper";
6
+ };
7
+ export declare const getWrapperClassName: (imagePrefix: string) => string;
8
+ export declare const getImageClassName: (imagePrefix: string, filename: string) => string;
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Converts any image URL or path into a CSS-safe kebab-case string.
3
+ * Used at build time by generateImageClassName() and at runtime by
4
+ * the Vue/React components to derive the CSS class from the src prop.
5
+ */
6
+ export declare const cleanImagePath: (src: string) => string;
7
+ /**
8
+ * Generate CSS class name from a file path — path-agnostic, works with any URL format.
9
+ * Matches the runtime getImageClassName logic emitted by getSharedLogic().
10
+ *
11
+ * @param filePath - Relative path from imageDir (e.g. "story/accent-orchid.png")
12
+ * @param imagePrefix - The prefix to add to the class name (e.g. "image-")
13
+ * @param outputPrefix - Optional output path prefix prepended before filePath to mirror
14
+ * the served URL (e.g. "images/" when assetModuleFilename outputs
15
+ * to "images/…" so the browser requests "/images/story/…")
16
+ * @returns The generated CSS class name (e.g. "image-images-story-accent-orchid")
17
+ */
18
+ export declare function generateImageClassName(filePath: string, imagePrefix: string, outputPrefix?: string): string;
19
+ /**
20
+ * Strips the Vite/webpack plugin's injected asset-path prefix from a src string
21
+ * so the remaining path matches what the plugin used when generating CSS classes.
22
+ *
23
+ * @param src - The raw src value (may include the asset path prefix)
24
+ * @param assetPath - The value of __PLUGIN_ASSET_PATH__ (empty string if undefined)
25
+ */
26
+ export declare function resolveAssetPath(src: string, assetPath: string): string;
27
+ /**
28
+ * Derives the per-image CSS class from a src URL, stripping the asset-path
29
+ * prefix first so the class matches what the plugin generated at build time.
30
+ *
31
+ * @param src - Raw src prop value
32
+ * @param imagePrefix - e.g. "image-"
33
+ * @param assetPath - Value of __PLUGIN_ASSET_PATH__ (pass '' if not defined)
34
+ */
35
+ export declare function getImageClass(src: string, imagePrefix: string, assetPath: string): string;
36
+ /**
37
+ * Builds the full className string for the <picture> wrapper element.
38
+ *
39
+ * @param src - Raw src prop value
40
+ * @param imagePrefix - e.g. "image-"
41
+ * @param assetPath - Value of __PLUGIN_ASSET_PATH__ (pass '' if not defined)
42
+ * @param extraClass - Any additional class(es) passed by the consumer (e.g. className prop)
43
+ */
44
+ export declare function getWrapperClass(src: string, imagePrefix: string, assetPath: string, extraClass?: string): string;
45
+ /**
46
+ * Returns the CSS class string for the <img> element based on lazy-load state.
47
+ *
48
+ * @param lazy - Whether lazy loading is enabled
49
+ * @param isLoaded - Whether the image has been loaded (intersected)
50
+ */
51
+ export declare function getLazyClass(lazy: boolean, isLoaded: boolean): string;
52
+ /**
53
+ * Creates an IntersectionObserver that fires `onIntersect` once when the given
54
+ * element enters the viewport, then automatically stops observing.
55
+ *
56
+ * @param element - The DOM element to observe
57
+ * @param onIntersect - Callback invoked when the element intersects
58
+ * @param threshold - Intersection threshold (default 0.1)
59
+ * @returns The created IntersectionObserver (call .disconnect() to clean up early)
60
+ */
61
+ export declare function createLazyObserver(element: Element, onIntersect: () => void, threshold?: number): IntersectionObserver;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@place-framework/place-block-image",
3
- "version": "1.0.3",
3
+ "version": "1.0.5",
4
4
  "description": "A utility package for generating CSS custom properties from image dimensions to prevent layout shift",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -48,9 +48,11 @@
48
48
  "@types/glob": "^8.1.0",
49
49
  "@types/node": "^20.0.0",
50
50
  "@types/react": "^18.0.0",
51
- "@vitejs/plugin-vue": "^5.2.4",
51
+ "@vitejs/plugin-vue": "^6.0.7",
52
+ "@vue/language-core": "^3.1.8",
52
53
  "typescript": "^5.0.0",
53
- "vite": "^5.4.21"
54
+ "vite": "^8.0.16",
55
+ "vite-plugin-dts": "^5.0.2"
54
56
  },
55
57
  "dependencies": {
56
58
  "glob": "^10.0.0",
@@ -0,0 +1,17 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2020",
4
+ "module": "ESNext",
5
+ "lib": ["ES2020", "DOM"],
6
+ "strict": true,
7
+ "esModuleInterop": true,
8
+ "skipLibCheck": true,
9
+ "forceConsistentCasingInFileNames": true,
10
+ "declaration": true,
11
+ "moduleResolution": "node",
12
+ "resolveJsonModule": true,
13
+ "jsx": "preserve",
14
+ "baseUrl": "."
15
+ },
16
+ "include": ["src/vue/**/*", "src/utils/**/*", "src/constants/**/*"]
17
+ }
@@ -1,10 +1,18 @@
1
1
  import { resolve } from 'path';
2
2
  import type { UserConfig } from 'vite';
3
+ import dts from 'vite-plugin-dts';
3
4
 
4
-
5
- // Builds src/react/PlaceBlockImage.tsx → dist/react/PlaceBlockImage.{js,cjs}
5
+ // Builds src/react/PlaceBlockImage.tsx → dist/react/PlaceBlockImage.{js,cjs,d.ts}
6
6
  // React and its runtime are kept external — consumers supply their own.
7
7
  export const reactConfig: UserConfig = {
8
+ plugins: [
9
+ dts({
10
+ include: ['src/react/PlaceBlockImage.tsx'],
11
+ outDirs: 'dist/react',
12
+ entryRoot: 'src/react',
13
+ tsconfigPath: './tsconfig.json',
14
+ }),
15
+ ],
8
16
  build: {
9
17
  outDir: 'dist/react',
10
18
  emptyOutDir: true,
@@ -1,12 +1,22 @@
1
1
  import vue from '@vitejs/plugin-vue';
2
2
  import { resolve } from 'path';
3
3
  import type { UserConfig } from 'vite';
4
+ import dts from 'vite-plugin-dts';
4
5
 
5
-
6
- // Builds src/vue/PlaceBlockImage.vue → dist/vue/PlaceBlockImage.{js,cjs}
6
+ // Builds src/vue/PlaceBlockImage.vue → dist/vue/PlaceBlockImage.{js,cjs,d.ts}
7
7
  // Vue and its runtime are kept external — consumers supply their own.
8
8
  export const vueConfig: UserConfig = {
9
- plugins: [vue()],
9
+ plugins: [
10
+ vue(),
11
+ dts({
12
+ outDirs: 'dist/vue',
13
+ entryRoot: 'src/vue',
14
+ tsconfigPath: './tsconfig.vue.json',
15
+ processor: 'vue',
16
+ cleanVueFileName: true,
17
+ staticImport: true,
18
+ }),
19
+ ],
10
20
  build: {
11
21
  outDir: 'dist/vue',
12
22
  emptyOutDir: true,