@place-framework/place-block-image 1.0.1 → 1.0.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/constants/index.d.ts +2 -2
- package/dist/constants/index.d.ts.map +1 -1
- package/dist/constants/index.js +4 -5
- package/dist/constants/index.js.map +1 -1
- package/dist/generate-components.d.ts +16 -0
- package/dist/generate-components.d.ts.map +1 -0
- package/dist/generate-components.js +93 -0
- package/dist/generate-components.js.map +1 -0
- package/dist/react/PlaceBlockImage.cjs +1 -0
- package/dist/react/PlaceBlockImage.js +67 -0
- package/dist/templates/shared/index.d.ts.map +1 -1
- package/dist/templates/shared/index.js +8 -16
- package/dist/templates/shared/index.js.map +1 -1
- package/dist/templates/shared/vue.d.ts +6 -0
- package/dist/templates/shared/vue.d.ts.map +1 -0
- package/dist/templates/shared/vue.js +26 -0
- package/dist/templates/shared/vue.js.map +1 -0
- package/dist/templates/vue.d.ts.map +1 -1
- package/dist/templates/vue.js +14 -19
- package/dist/templates/vue.js.map +1 -1
- package/dist/utils/index.d.ts +61 -14
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +108 -40
- package/dist/utils/index.js.map +1 -1
- package/dist/vue/PlaceBlockImage.cjs +1 -0
- package/dist/vue/PlaceBlockImage.js +83 -0
- package/dist/webpack-plugin.d.ts +20 -7
- package/dist/webpack-plugin.d.ts.map +1 -1
- package/dist/webpack-plugin.js +22 -28
- package/dist/webpack-plugin.js.map +1 -1
- package/package.json +36 -10
- package/src/constants/index.ts +5 -6
- package/src/react/PlaceBlockImage.tsx +63 -0
- package/src/react/index.ts +1 -0
- package/src/utils/index.ts +121 -44
- package/src/vue/PlaceBlockImage.vue +98 -0
- package/src/vue/index.ts +1 -0
- package/src/webpack-plugin.ts +45 -40
- package/tsconfig.json +8 -3
- package/vite.config.mts +27 -0
- package/vite.react.config.mts +25 -0
- package/vite.vue.config.mts +26 -0
- package/src/templates/react-jsx.ts +0 -27
- package/src/templates/react-tsx.ts +0 -33
- package/src/templates/shared/index.ts +0 -47
- package/src/templates/shared/react.ts +0 -51
- package/src/templates/vue.ts +0 -98
- package/src/templates.ts +0 -29
|
@@ -1,8 +1,8 @@
|
|
|
1
|
+
export declare const IMAGE_PREFIX = "image-";
|
|
1
2
|
export declare const CLASS_NAMES: {
|
|
2
3
|
readonly LAZY: "lazy";
|
|
3
4
|
readonly LOADED: "loaded";
|
|
4
|
-
readonly
|
|
5
|
-
readonly IMAGE_BLOCK: "image-block";
|
|
5
|
+
readonly WRAPPER_SUFFIX: "wrapper";
|
|
6
6
|
};
|
|
7
7
|
export declare const getWrapperClassName: (imagePrefix: string) => string;
|
|
8
8
|
export declare const getImageClassName: (imagePrefix: string, filename: string) => string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/constants/index.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,WAAW
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/constants/index.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,YAAY,WAAW,CAAC;AAErC,eAAO,MAAM,WAAW;;;;CAOd,CAAC;AAEX,eAAO,MAAM,mBAAmB,GAAI,aAAa,MAAM,WAA4B,CAAC;AACpF,eAAO,MAAM,iBAAiB,GAAI,aAAa,MAAM,EAAE,UAAU,MAAM,WAAgC,CAAC"}
|
package/dist/constants/index.js
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getImageClassName = exports.getWrapperClassName = exports.CLASS_NAMES = void 0;
|
|
3
|
+
exports.getImageClassName = exports.getWrapperClassName = exports.CLASS_NAMES = exports.IMAGE_PREFIX = void 0;
|
|
4
|
+
exports.IMAGE_PREFIX = 'image-';
|
|
4
5
|
exports.CLASS_NAMES = {
|
|
5
6
|
// Lazy loading states
|
|
6
7
|
LAZY: 'lazy',
|
|
7
8
|
LOADED: 'loaded',
|
|
8
|
-
//
|
|
9
|
-
|
|
10
|
-
// Base image class
|
|
11
|
-
IMAGE_BLOCK: 'image-block'
|
|
9
|
+
// Suffix appended to imagePrefix to form the wrapper class (e.g. 'image-wrapper')
|
|
10
|
+
WRAPPER_SUFFIX: 'wrapper',
|
|
12
11
|
};
|
|
13
12
|
const getWrapperClassName = (imagePrefix) => `${imagePrefix}wrapper`;
|
|
14
13
|
exports.getWrapperClassName = getWrapperClassName;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/constants/index.ts"],"names":[],"mappings":";;;AAAa,QAAA,WAAW,GAAG;IACzB,sBAAsB;IACtB,IAAI,EAAE,MAAM;IACZ,MAAM,EAAE,QAAQ;IAEhB,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/constants/index.ts"],"names":[],"mappings":";;;AAAa,QAAA,YAAY,GAAG,QAAQ,CAAC;AAExB,QAAA,WAAW,GAAG;IACzB,sBAAsB;IACtB,IAAI,EAAE,MAAM;IACZ,MAAM,EAAE,QAAQ;IAEhB,kFAAkF;IAClF,cAAc,EAAE,SAAS;CACjB,CAAC;AAEJ,MAAM,mBAAmB,GAAG,CAAC,WAAmB,EAAE,EAAE,CAAC,GAAG,WAAW,SAAS,CAAC;AAAvE,QAAA,mBAAmB,uBAAoD;AAC7E,MAAM,iBAAiB,GAAG,CAAC,WAAmB,EAAE,QAAgB,EAAE,EAAE,CAAC,GAAG,WAAW,GAAG,QAAQ,EAAE,CAAC;AAA3F,QAAA,iBAAiB,qBAA0E"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generates Vue and React component source files from templates.
|
|
3
|
+
*
|
|
4
|
+
* Usage:
|
|
5
|
+
* node dist/generate-components.js [imagePrefix]
|
|
6
|
+
*
|
|
7
|
+
* imagePrefix defaults to 'image-' if not provided.
|
|
8
|
+
* The webpack plugin calls this automatically with the configured imagePrefix.
|
|
9
|
+
*
|
|
10
|
+
* Generated files are written to src/vue/ and src/react/ so they are
|
|
11
|
+
* shipped as source and consumers can import directly:
|
|
12
|
+
* import { PlaceBlockImage } from '@place-framework/place-block-image/vue'
|
|
13
|
+
* import { PlaceBlockImage } from '@place-framework/place-block-image/react'
|
|
14
|
+
*/
|
|
15
|
+
export {};
|
|
16
|
+
//# sourceMappingURL=generate-components.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate-components.d.ts","sourceRoot":"","sources":["../src/generate-components.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Generates Vue and React component source files from templates.
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* node dist/generate-components.js [imagePrefix]
|
|
7
|
+
*
|
|
8
|
+
* imagePrefix defaults to 'image-' if not provided.
|
|
9
|
+
* The webpack plugin calls this automatically with the configured imagePrefix.
|
|
10
|
+
*
|
|
11
|
+
* Generated files are written to src/vue/ and src/react/ so they are
|
|
12
|
+
* shipped as source and consumers can import directly:
|
|
13
|
+
* import { PlaceBlockImage } from '@place-framework/place-block-image/vue'
|
|
14
|
+
* import { PlaceBlockImage } from '@place-framework/place-block-image/react'
|
|
15
|
+
*/
|
|
16
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
17
|
+
if (k2 === undefined) k2 = k;
|
|
18
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
19
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
20
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
21
|
+
}
|
|
22
|
+
Object.defineProperty(o, k2, desc);
|
|
23
|
+
}) : (function(o, m, k, k2) {
|
|
24
|
+
if (k2 === undefined) k2 = k;
|
|
25
|
+
o[k2] = m[k];
|
|
26
|
+
}));
|
|
27
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
28
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
29
|
+
}) : function(o, v) {
|
|
30
|
+
o["default"] = v;
|
|
31
|
+
});
|
|
32
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
33
|
+
var ownKeys = function(o) {
|
|
34
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
35
|
+
var ar = [];
|
|
36
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
37
|
+
return ar;
|
|
38
|
+
};
|
|
39
|
+
return ownKeys(o);
|
|
40
|
+
};
|
|
41
|
+
return function (mod) {
|
|
42
|
+
if (mod && mod.__esModule) return mod;
|
|
43
|
+
var result = {};
|
|
44
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
45
|
+
__setModuleDefault(result, mod);
|
|
46
|
+
return result;
|
|
47
|
+
};
|
|
48
|
+
})();
|
|
49
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
50
|
+
const fs = __importStar(require("fs"));
|
|
51
|
+
const path = __importStar(require("path"));
|
|
52
|
+
const vue_1 = require("./templates/vue");
|
|
53
|
+
const react_tsx_1 = require("./templates/react-tsx");
|
|
54
|
+
const imagePrefix = process.argv[2] || 'image-';
|
|
55
|
+
const frameworks = [
|
|
56
|
+
{
|
|
57
|
+
name: 'vue',
|
|
58
|
+
dir: path.resolve(__dirname, '../src/vue'),
|
|
59
|
+
files: [
|
|
60
|
+
{
|
|
61
|
+
filename: 'PlaceBlockImage.vue',
|
|
62
|
+
content: () => (0, vue_1.getVueTemplate)(imagePrefix),
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
filename: 'index.ts',
|
|
66
|
+
content: () => `export { default as PlaceBlockImage } from './PlaceBlockImage.vue';\n`,
|
|
67
|
+
},
|
|
68
|
+
],
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
name: 'react',
|
|
72
|
+
dir: path.resolve(__dirname, '../src/react'),
|
|
73
|
+
files: [
|
|
74
|
+
{
|
|
75
|
+
filename: 'PlaceBlockImage.tsx',
|
|
76
|
+
content: () => (0, react_tsx_1.getReactTsxTemplate)(imagePrefix),
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
filename: 'index.ts',
|
|
80
|
+
content: () => `export { PlaceBlockImage, default } from './PlaceBlockImage';\n`,
|
|
81
|
+
},
|
|
82
|
+
],
|
|
83
|
+
},
|
|
84
|
+
];
|
|
85
|
+
for (const framework of frameworks) {
|
|
86
|
+
fs.mkdirSync(framework.dir, { recursive: true });
|
|
87
|
+
for (const file of framework.files) {
|
|
88
|
+
const filePath = path.join(framework.dir, file.filename);
|
|
89
|
+
fs.writeFileSync(filePath, file.content(), 'utf-8');
|
|
90
|
+
console.log(`✅ Generated src/${framework.name}/${file.filename}`);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=generate-components.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate-components.js","sourceRoot":"","sources":["../src/generate-components.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;GAaG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEH,uCAAyB;AACzB,2CAA6B;AAC7B,yCAAiD;AACjD,qDAA4D;AAE5D,MAAM,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,QAAQ,CAAC;AAEhD,MAAM,UAAU,GAAG;IACjB;QACE,IAAI,EAAE,KAAK;QACX,GAAG,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,YAAY,CAAC;QAC1C,KAAK,EAAE;YACL;gBACE,QAAQ,EAAE,qBAAqB;gBAC/B,OAAO,EAAE,GAAG,EAAE,CAAC,IAAA,oBAAc,EAAC,WAAW,CAAC;aAC3C;YACD;gBACE,QAAQ,EAAE,UAAU;gBACpB,OAAO,EAAE,GAAG,EAAE,CAAC,uEAAuE;aACvF;SACF;KACF;IACD;QACE,IAAI,EAAE,OAAO;QACb,GAAG,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,cAAc,CAAC;QAC5C,KAAK,EAAE;YACL;gBACE,QAAQ,EAAE,qBAAqB;gBAC/B,OAAO,EAAE,GAAG,EAAE,CAAC,IAAA,+BAAmB,EAAC,WAAW,CAAC;aAChD;YACD;gBACE,QAAQ,EAAE,UAAU;gBACpB,OAAO,EAAE,GAAG,EAAE,CAAC,iEAAiE;aACjF;SACF;KACF;CACF,CAAC;AAEF,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;IACnC,EAAE,CAAC,SAAS,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAEjD,KAAK,MAAM,IAAI,IAAI,SAAS,CAAC,KAAK,EAAE,CAAC;QACnC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;QACzD,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,IAAI,CAAC,OAAO,EAAE,EAAE,OAAO,CAAC,CAAC;QACpD,OAAO,CAAC,GAAG,CAAC,mBAAmB,SAAS,CAAC,IAAI,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;IACpE,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +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;
|
|
@@ -0,0 +1,67 @@
|
|
|
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;
|
|
11
|
+
}
|
|
12
|
+
function R(e, t, n) {
|
|
13
|
+
return e ? `${t}${P(d(e, n))}` : "";
|
|
14
|
+
}
|
|
15
|
+
function $(e, t, n, r = "") {
|
|
16
|
+
return [
|
|
17
|
+
`${t}${c.WRAPPER_SUFFIX}`,
|
|
18
|
+
R(e, t, n),
|
|
19
|
+
r
|
|
20
|
+
].filter(Boolean).join(" ");
|
|
21
|
+
}
|
|
22
|
+
function v(e, t) {
|
|
23
|
+
return e ? t ? `${c.LAZY} ${c.LOADED}` : c.LAZY : "";
|
|
24
|
+
}
|
|
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;
|
|
35
|
+
}
|
|
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
|
|
67
|
+
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/templates/shared/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/templates/shared/index.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,iBAAiB,GAAI,aAAa,MAAM;;;;CAmCnD,CAAC"}
|
|
@@ -2,35 +2,27 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.getSharedTemplate = void 0;
|
|
4
4
|
const constants_1 = require("../../constants");
|
|
5
|
+
const utils_1 = require("../../utils");
|
|
5
6
|
const getSharedTemplate = (imagePrefix) => ({
|
|
6
7
|
// Common comment block
|
|
7
8
|
comment: `/**
|
|
8
9
|
* PlaceBlockImage component that prevents layout shift using CSS custom properties
|
|
9
10
|
* Generated by place-block-image webpack plugin
|
|
10
|
-
*
|
|
11
|
+
*
|
|
11
12
|
* Usage:
|
|
12
13
|
* <PlaceBlockImage src="/images/logo.svg" alt="Logo" />
|
|
13
14
|
* <PlaceBlockImage src="/images/hero.jpg" alt="Hero" lazy={true} />
|
|
14
|
-
*
|
|
15
|
+
*
|
|
15
16
|
* This will automatically apply:
|
|
16
17
|
* - .${imagePrefix}wrapper class on picture (for dimensions)
|
|
17
18
|
* - .${imagePrefix}logo class on picture (specific dimensions via CSS custom properties)
|
|
18
19
|
* - ${constants_1.CLASS_NAMES.LAZY}/${constants_1.CLASS_NAMES.LAZY}.${constants_1.CLASS_NAMES.LOADED} classes for lazy loading states
|
|
19
20
|
*/`,
|
|
20
|
-
//
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
.replace(/^.*\\/images\\//, '') // Remove path up to /images/
|
|
26
|
-
.replace(/\\.[^/.]+$/, '') // Remove file extension
|
|
27
|
-
.toLowerCase()
|
|
28
|
-
.replace(/[^a-z0-9-]/g, '-') // Convert special chars to hyphens
|
|
29
|
-
.replace(/-+/g, '-') // Remove duplicate hyphens
|
|
30
|
-
.replace(/^-|-$/g, ''); // Remove leading/trailing hyphens
|
|
31
|
-
|
|
32
|
-
return \`${imagePrefix}\${filename}\`;
|
|
33
|
-
};`,
|
|
21
|
+
// Serialises cleanImagePath from utils so the generated component uses the
|
|
22
|
+
// exact same function — single source of truth, no duplicated regex.
|
|
23
|
+
getImageClassNameTemplate: `// Serialised from cleanImagePath in utils/index.ts — single source of truth.
|
|
24
|
+
const cleanImagePath = ${utils_1.cleanImagePath.toString()};
|
|
25
|
+
const getImageClassName = (imageSrc) => imageSrc ? \`${imagePrefix}\${cleanImagePath(imageSrc)}\` : '';`,
|
|
34
26
|
// Common intersection observer logic
|
|
35
27
|
intersectionObserverTemplate: `const observer = new IntersectionObserver(
|
|
36
28
|
(entries) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/templates/shared/index.ts"],"names":[],"mappings":";;;AAAA,+CAA8C;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/templates/shared/index.ts"],"names":[],"mappings":";;;AAAA,+CAA8C;AAC9C,uCAA6C;AAEtC,MAAM,iBAAiB,GAAG,CAAC,WAAmB,EAAE,EAAE,CAAC,CAAC;IACzD,uBAAuB;IACvB,OAAO,EAAE;;;;;;;;;QASH,WAAW;QACX,WAAW;OACZ,uBAAW,CAAC,IAAI,IAAI,uBAAW,CAAC,IAAI,IAAI,uBAAW,CAAC,MAAM;IAC7D;IAEF,2EAA2E;IAC3E,qEAAqE;IACrE,yBAAyB,EAAE;2BACF,sBAAc,CAAC,QAAQ,EAAE;yDACK,WAAW,sCAAsC;IAExG,qCAAqC;IACrC,4BAA4B,EAAE;;;;;;;;;;;OAWzB;CACN,CAAC,CAAC;AAnCU,QAAA,iBAAiB,qBAmC3B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vue.d.ts","sourceRoot":"","sources":["../../../src/templates/shared/vue.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,oBAAoB,GAAI,aAAa,MAAM;;;;CAsBvD,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getSharedVueTemplate = void 0;
|
|
4
|
+
const index_1 = require("./index");
|
|
5
|
+
const getSharedVueTemplate = (imagePrefix) => {
|
|
6
|
+
const shared = (0, index_1.getSharedTemplate)(imagePrefix);
|
|
7
|
+
return {
|
|
8
|
+
comment: shared.comment,
|
|
9
|
+
getImageClassName: shared.getImageClassNameTemplate,
|
|
10
|
+
// Vue Composition API intersection observer - uses refs instead of React state setters
|
|
11
|
+
intersectionObserverTemplate: `observer = new IntersectionObserver(
|
|
12
|
+
(entries) => {
|
|
13
|
+
entries.forEach((entry) => {
|
|
14
|
+
if (entry.isIntersecting) {
|
|
15
|
+
imageSrc.value = props.src;
|
|
16
|
+
isLoaded.value = true;
|
|
17
|
+
observer?.unobserve(entry.target);
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
},
|
|
21
|
+
{ threshold: 0.1 }
|
|
22
|
+
);`,
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
exports.getSharedVueTemplate = getSharedVueTemplate;
|
|
26
|
+
//# sourceMappingURL=vue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vue.js","sourceRoot":"","sources":["../../../src/templates/shared/vue.ts"],"names":[],"mappings":";;;AAAA,mCAA4C;AAErC,MAAM,oBAAoB,GAAG,CAAC,WAAmB,EAAE,EAAE;IAC1D,MAAM,MAAM,GAAG,IAAA,yBAAiB,EAAC,WAAW,CAAC,CAAC;IAE9C,OAAO;QACL,OAAO,EAAE,MAAM,CAAC,OAAO;QAEvB,iBAAiB,EAAE,MAAM,CAAC,yBAAyB;QAEnD,uFAAuF;QACvF,4BAA4B,EAAE;;;;;;;;;;;OAW3B;KACJ,CAAC;AACJ,CAAC,CAAC;AAtBW,QAAA,oBAAoB,wBAsB/B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vue.d.ts","sourceRoot":"","sources":["../../src/templates/vue.ts"],"names":[],"mappings":"AAGA,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"vue.d.ts","sourceRoot":"","sources":["../../src/templates/vue.ts"],"names":[],"mappings":"AAGA,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAyF1D"}
|
package/dist/templates/vue.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.getVueTemplate = getVueTemplate;
|
|
4
|
-
const
|
|
4
|
+
const vue_1 = require("./shared/vue");
|
|
5
5
|
const constants_1 = require("../constants");
|
|
6
6
|
function getVueTemplate(imagePrefix) {
|
|
7
|
-
const shared = (0,
|
|
7
|
+
const shared = (0, vue_1.getSharedVueTemplate)(imagePrefix);
|
|
8
8
|
return `<template>
|
|
9
9
|
<picture :class="wrapperClassName">
|
|
10
10
|
<img
|
|
@@ -17,40 +17,35 @@ function getVueTemplate(imagePrefix) {
|
|
|
17
17
|
</picture>
|
|
18
18
|
</template>
|
|
19
19
|
|
|
20
|
-
<script setup
|
|
20
|
+
<script setup>
|
|
21
21
|
import { computed, ref, onMounted, onUnmounted, watch } from 'vue';
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
src:
|
|
25
|
-
alt:
|
|
26
|
-
lazy
|
|
27
|
-
class
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
const props = withDefaults(defineProps<Props>(), {
|
|
31
|
-
lazy: false,
|
|
32
|
-
class: ''
|
|
23
|
+
const props = defineProps({
|
|
24
|
+
src: { type: String, required: true },
|
|
25
|
+
alt: { type: String, required: true },
|
|
26
|
+
lazy: { type: Boolean, default: false },
|
|
27
|
+
class: { type: String, default: '' }
|
|
33
28
|
});
|
|
34
29
|
|
|
35
30
|
${shared.comment}
|
|
36
31
|
|
|
37
|
-
const imgRef = ref
|
|
32
|
+
const imgRef = ref(null);
|
|
38
33
|
const imageSrc = ref(props.lazy ? '' : props.src);
|
|
39
34
|
const isLoaded = ref(!props.lazy);
|
|
40
|
-
let observer
|
|
35
|
+
let observer = null;
|
|
41
36
|
|
|
42
|
-
${shared.
|
|
37
|
+
${shared.getImageClassName}
|
|
43
38
|
|
|
44
39
|
const imageClassName = computed(() => getImageClassName(props.src));
|
|
45
|
-
const wrapperClassName = computed(() =>
|
|
40
|
+
const wrapperClassName = computed(() =>
|
|
46
41
|
\`${imagePrefix}wrapper \${imageClassName.value}\`
|
|
47
42
|
);
|
|
48
43
|
|
|
49
|
-
const lazyClass = computed(() =>
|
|
44
|
+
const lazyClass = computed(() =>
|
|
50
45
|
props.lazy ? (isLoaded.value ? '${constants_1.CLASS_NAMES.LAZY} ${constants_1.CLASS_NAMES.LOADED}' : '${constants_1.CLASS_NAMES.LAZY}') : ''
|
|
51
46
|
);
|
|
52
47
|
|
|
53
|
-
const imgClassName = computed(() =>
|
|
48
|
+
const imgClassName = computed(() =>
|
|
54
49
|
\`\${props.class} \${lazyClass.value}\`.trim()
|
|
55
50
|
);
|
|
56
51
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vue.js","sourceRoot":"","sources":["../../src/templates/vue.ts"],"names":[],"mappings":";;AAGA,
|
|
1
|
+
{"version":3,"file":"vue.js","sourceRoot":"","sources":["../../src/templates/vue.ts"],"names":[],"mappings":";;AAGA,wCAyFC;AA5FD,sCAAoD;AACpD,4CAA2C;AAE3C,SAAgB,cAAc,CAAC,WAAmB;IAChD,MAAM,MAAM,GAAG,IAAA,0BAAoB,EAAC,WAAW,CAAC,CAAC;IAEjD,OAAO;;;;;;;;;;;;;;;;;;;;;;EAsBP,MAAM,CAAC,OAAO;;;;;;;EAOd,MAAM,CAAC,iBAAiB;;;;MAIpB,WAAW;;;;oCAImB,uBAAW,CAAC,IAAI,IAAI,uBAAW,CAAC,MAAM,QAAQ,uBAAW,CAAC,IAAI;;;;;;;;;;IAU9F,MAAM,CAAC,4BAA4B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsCtC,CAAC;AACF,CAAC"}
|
package/dist/utils/index.d.ts
CHANGED
|
@@ -1,15 +1,62 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
export declare
|
|
7
|
-
/**
|
|
8
|
-
* Generate CSS class name from file path -
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* @
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
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;
|
|
15
62
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAIA;;;;GAIG;AACH,eAAO,MAAM,cAAc,GAAI,KAAK,MAAM,KAAG,MASnB,CAAC;AAE3B;;;;;;;;;;GAUG;AACH,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,EACnB,YAAY,GAAE,MAAW,GACxB,MAAM,CAMR;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAGvE;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAGzF;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAC7B,GAAG,EAAE,MAAM,EACX,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,UAAU,GAAE,MAAW,GACtB,MAAM,CAOR;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,GAAG,MAAM,CAGrE;AAED;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,OAAO,EAChB,WAAW,EAAE,MAAM,IAAI,EACvB,SAAS,GAAE,MAAY,GACtB,oBAAoB,CActB"}
|