@lukas_holdings/castdom 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +707 -0
- package/bin/castdom.js +2 -0
- package/dist/astro.cjs +86 -0
- package/dist/astro.cjs.map +1 -0
- package/dist/astro.d.cts +88 -0
- package/dist/astro.d.ts +88 -0
- package/dist/astro.js +80 -0
- package/dist/astro.js.map +1 -0
- package/dist/chunk-COLESJ66.js +57 -0
- package/dist/chunk-COLESJ66.js.map +1 -0
- package/dist/chunk-EJRNKHL5.js +31 -0
- package/dist/chunk-EJRNKHL5.js.map +1 -0
- package/dist/chunk-JRQ6EVQP.cjs +35 -0
- package/dist/chunk-JRQ6EVQP.cjs.map +1 -0
- package/dist/chunk-KGLTVTHU.js +73 -0
- package/dist/chunk-KGLTVTHU.js.map +1 -0
- package/dist/chunk-O4OOMGGM.cjs +198 -0
- package/dist/chunk-O4OOMGGM.cjs.map +1 -0
- package/dist/chunk-ONS533CQ.js +104 -0
- package/dist/chunk-ONS533CQ.js.map +1 -0
- package/dist/chunk-ORY4OMZ5.cjs +110 -0
- package/dist/chunk-ORY4OMZ5.cjs.map +1 -0
- package/dist/chunk-QLEBTZIB.cjs +64 -0
- package/dist/chunk-QLEBTZIB.cjs.map +1 -0
- package/dist/chunk-XS5HAU5E.cjs +109 -0
- package/dist/chunk-XS5HAU5E.cjs.map +1 -0
- package/dist/chunk-YDT4TPB7.cjs +84 -0
- package/dist/chunk-YDT4TPB7.cjs.map +1 -0
- package/dist/chunk-ZBJB7WVV.js +193 -0
- package/dist/chunk-ZBJB7WVV.js.map +1 -0
- package/dist/chunk-ZWZ5ZLJE.js +103 -0
- package/dist/chunk-ZWZ5ZLJE.js.map +1 -0
- package/dist/cli.js +135 -0
- package/dist/index.cjs +540 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +176 -0
- package/dist/index.d.ts +176 -0
- package/dist/index.js +440 -0
- package/dist/index.js.map +1 -0
- package/dist/next.cjs +65 -0
- package/dist/next.cjs.map +1 -0
- package/dist/next.d.cts +72 -0
- package/dist/next.d.ts +72 -0
- package/dist/next.js +48 -0
- package/dist/next.js.map +1 -0
- package/dist/react.cjs +30 -0
- package/dist/react.cjs.map +1 -0
- package/dist/react.d.cts +70 -0
- package/dist/react.d.ts +70 -0
- package/dist/react.js +7 -0
- package/dist/react.js.map +1 -0
- package/dist/renderer-B1R7u2wm.d.ts +30 -0
- package/dist/renderer-Bfzjr6l9.d.cts +30 -0
- package/dist/ssr.cjs +46 -0
- package/dist/ssr.cjs.map +1 -0
- package/dist/ssr.d.cts +83 -0
- package/dist/ssr.d.ts +83 -0
- package/dist/ssr.js +5 -0
- package/dist/ssr.js.map +1 -0
- package/dist/types-ChD5jENU.d.cts +105 -0
- package/dist/types-ChD5jENU.d.ts +105 -0
- package/dist/vite.cjs +83 -0
- package/dist/vite.cjs.map +1 -0
- package/dist/vite.d.cts +81 -0
- package/dist/vite.d.ts +81 -0
- package/dist/vite.js +77 -0
- package/dist/vite.js.map +1 -0
- package/package.json +130 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,440 @@
|
|
|
1
|
+
import { selectBreakpoint } from './chunk-ONS533CQ.js';
|
|
2
|
+
export { diffBreakpoints, getStaleBreakpoints, interpolateBones, selectBreakpoint, validateBreakpoints } from './chunk-ONS533CQ.js';
|
|
3
|
+
import { get, register, loadManifest } from './chunk-KGLTVTHU.js';
|
|
4
|
+
export { clear, configure, get, getAllCSS, has, loadManifest, names, register, registerAll, remove } from './chunk-KGLTVTHU.js';
|
|
5
|
+
import { generateCriticalCSS, renderStandalone } from './chunk-ZWZ5ZLJE.js';
|
|
6
|
+
export { generateCSS, generateCriticalCSS, renderBonesHTML, renderResponsiveHTML, renderStandalone } from './chunk-ZWZ5ZLJE.js';
|
|
7
|
+
import { BONE_KIND_INDEX, BONE_KIND_FROM_INDEX, DEFAULTS } from './chunk-EJRNKHL5.js';
|
|
8
|
+
export { BONE_KIND_FROM_INDEX, BONE_KIND_INDEX, DEFAULTS } from './chunk-EJRNKHL5.js';
|
|
9
|
+
|
|
10
|
+
// src/core/compress.ts
|
|
11
|
+
function compressBones(bp) {
|
|
12
|
+
const sorted = [...bp.bones].sort((a, b) => a.y - b.y || a.x - b.x);
|
|
13
|
+
const data = [];
|
|
14
|
+
let prevX = 0;
|
|
15
|
+
let prevY = 0;
|
|
16
|
+
for (const bone of sorted) {
|
|
17
|
+
const x = Math.round(bone.x * 2);
|
|
18
|
+
const y = Math.round(bone.y * 2);
|
|
19
|
+
const w = Math.round(bone.w * 2);
|
|
20
|
+
const h = Math.round(bone.h * 2);
|
|
21
|
+
const r = Math.round(bone.r * 2);
|
|
22
|
+
const kind = BONE_KIND_INDEX[bone.kind ?? "block"];
|
|
23
|
+
data.push(x - prevX, y - prevY, w, h, r, kind);
|
|
24
|
+
prevX = x;
|
|
25
|
+
prevY = y;
|
|
26
|
+
}
|
|
27
|
+
return {
|
|
28
|
+
v: 1,
|
|
29
|
+
vw: bp.viewport,
|
|
30
|
+
c: [
|
|
31
|
+
Math.round(bp.containerWidth * 2),
|
|
32
|
+
Math.round(bp.containerHeight * 2)
|
|
33
|
+
],
|
|
34
|
+
d: data
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
function decompressBones(compressed) {
|
|
38
|
+
const bones = [];
|
|
39
|
+
const d = compressed.d;
|
|
40
|
+
let prevX = 0;
|
|
41
|
+
let prevY = 0;
|
|
42
|
+
for (let i = 0; i < d.length; i += 6) {
|
|
43
|
+
const dx = d[i];
|
|
44
|
+
const dy = d[i + 1];
|
|
45
|
+
const w = d[i + 2];
|
|
46
|
+
const h = d[i + 3];
|
|
47
|
+
const r = d[i + 4];
|
|
48
|
+
const kindIdx = d[i + 5];
|
|
49
|
+
prevX += dx;
|
|
50
|
+
prevY += dy;
|
|
51
|
+
bones.push({
|
|
52
|
+
x: prevX / 2,
|
|
53
|
+
y: prevY / 2,
|
|
54
|
+
w: w / 2,
|
|
55
|
+
h: h / 2,
|
|
56
|
+
r: r / 2,
|
|
57
|
+
kind: BONE_KIND_FROM_INDEX[kindIdx] ?? "block"
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
return {
|
|
61
|
+
viewport: compressed.vw,
|
|
62
|
+
containerWidth: compressed.c[0] / 2,
|
|
63
|
+
containerHeight: compressed.c[1] / 2,
|
|
64
|
+
bones
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
function encodeBonesToBase64(compressed) {
|
|
68
|
+
const header = [compressed.v, compressed.vw, compressed.c[0], compressed.c[1]];
|
|
69
|
+
const allNums = [...header, compressed.d.length, ...compressed.d];
|
|
70
|
+
const bytes = [];
|
|
71
|
+
for (const n of allNums) {
|
|
72
|
+
const z = n >= 0 ? n * 2 : -n * 2 - 1;
|
|
73
|
+
let val = z;
|
|
74
|
+
while (val >= 128) {
|
|
75
|
+
bytes.push(val & 127 | 128);
|
|
76
|
+
val >>>= 7;
|
|
77
|
+
}
|
|
78
|
+
bytes.push(val & 127);
|
|
79
|
+
}
|
|
80
|
+
if (typeof Buffer !== "undefined") {
|
|
81
|
+
return Buffer.from(new Uint8Array(bytes)).toString("base64");
|
|
82
|
+
}
|
|
83
|
+
return btoa(String.fromCharCode(...bytes));
|
|
84
|
+
}
|
|
85
|
+
function decodeBonesToBase64(b64) {
|
|
86
|
+
let bytes;
|
|
87
|
+
if (typeof Buffer !== "undefined") {
|
|
88
|
+
bytes = Buffer.from(b64, "base64");
|
|
89
|
+
} else {
|
|
90
|
+
const raw = atob(b64);
|
|
91
|
+
bytes = new Uint8Array(raw.length);
|
|
92
|
+
for (let i = 0; i < raw.length; i++) bytes[i] = raw.charCodeAt(i);
|
|
93
|
+
}
|
|
94
|
+
const nums = [];
|
|
95
|
+
let pos = 0;
|
|
96
|
+
while (pos < bytes.length) {
|
|
97
|
+
let val = 0;
|
|
98
|
+
let shift = 0;
|
|
99
|
+
let b;
|
|
100
|
+
do {
|
|
101
|
+
b = bytes[pos++];
|
|
102
|
+
val |= (b & 127) << shift;
|
|
103
|
+
shift += 7;
|
|
104
|
+
} while (b & 128);
|
|
105
|
+
nums.push(val & 1 ? -(val >>> 1) - 1 : val >>> 1);
|
|
106
|
+
}
|
|
107
|
+
const v = nums[0];
|
|
108
|
+
const vw = nums[1];
|
|
109
|
+
const c = [nums[2], nums[3]];
|
|
110
|
+
const dLen = nums[4];
|
|
111
|
+
const d = nums.slice(5, 5 + dLen);
|
|
112
|
+
return { v, vw, c, d };
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// src/core/animation.ts
|
|
116
|
+
function generateKeyframes(config) {
|
|
117
|
+
const type = config?.type ?? "shimmer";
|
|
118
|
+
const prefix = config?.classPrefix ?? DEFAULTS.classPrefix;
|
|
119
|
+
config?.duration ?? DEFAULTS.animationDuration;
|
|
120
|
+
switch (type) {
|
|
121
|
+
case "shimmer":
|
|
122
|
+
return `@keyframes ${prefix}-shimmer{0%{background-position:-200% 0}100%{background-position:200% 0}}`;
|
|
123
|
+
case "pulse":
|
|
124
|
+
return `@keyframes ${prefix}-pulse{0%,100%{opacity:1}50%{opacity:0.4}}`;
|
|
125
|
+
case "wave":
|
|
126
|
+
return `@keyframes ${prefix}-wave{0%{opacity:0.4}50%{opacity:1}100%{opacity:0.4}}`;
|
|
127
|
+
case "none":
|
|
128
|
+
return "";
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
function generateBoneAnimation(config) {
|
|
132
|
+
const type = config?.type ?? "shimmer";
|
|
133
|
+
const prefix = config?.classPrefix ?? DEFAULTS.classPrefix;
|
|
134
|
+
const duration = config?.duration ?? DEFAULTS.animationDuration;
|
|
135
|
+
const color = config?.color ?? DEFAULTS.color;
|
|
136
|
+
const shimmerColor = config?.shimmerColor ?? DEFAULTS.shimmerColor;
|
|
137
|
+
switch (type) {
|
|
138
|
+
case "shimmer":
|
|
139
|
+
return `background:linear-gradient(90deg,${color} 25%,${shimmerColor} 50%,${color} 75%);background-size:200% 100%;animation:${prefix}-shimmer ${duration}ms ease-in-out infinite`;
|
|
140
|
+
case "pulse":
|
|
141
|
+
return `background:${color};animation:${prefix}-pulse ${duration}ms ease-in-out infinite`;
|
|
142
|
+
case "wave":
|
|
143
|
+
return `background:${color};animation:${prefix}-wave ${duration}ms ease-in-out infinite`;
|
|
144
|
+
case "none":
|
|
145
|
+
return `background:${color}`;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
function generateStaggerCSS(skeletonName, boneCount, config) {
|
|
149
|
+
const prefix = config?.classPrefix ?? DEFAULTS.classPrefix;
|
|
150
|
+
const stagger = config?.stagger ?? 50;
|
|
151
|
+
const rules = [];
|
|
152
|
+
for (let i = 0; i < boneCount; i++) {
|
|
153
|
+
rules.push(
|
|
154
|
+
`.${prefix}-${skeletonName} .${prefix}-bone:nth-child(${i + 1}){animation-delay:${i * stagger}ms}`
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
return rules.join("");
|
|
158
|
+
}
|
|
159
|
+
function generateAnimationCSS(skeletonName, boneCount, config) {
|
|
160
|
+
const prefix = config?.classPrefix ?? DEFAULTS.classPrefix;
|
|
161
|
+
const type = config?.type ?? "shimmer";
|
|
162
|
+
const parts = [];
|
|
163
|
+
const kf = generateKeyframes(config);
|
|
164
|
+
if (kf) parts.push(kf);
|
|
165
|
+
const anim = generateBoneAnimation(config);
|
|
166
|
+
parts.push(`.${prefix}-${skeletonName} .${prefix}-bone{position:absolute;${anim}}`);
|
|
167
|
+
if (type === "wave") {
|
|
168
|
+
parts.push(generateStaggerCSS(skeletonName, boneCount, config));
|
|
169
|
+
}
|
|
170
|
+
parts.push(
|
|
171
|
+
`@media(prefers-reduced-motion:reduce){.${prefix}-${skeletonName} .${prefix}-bone{animation:none!important}}`
|
|
172
|
+
);
|
|
173
|
+
return parts.join("\n");
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// src/core/extractor.ts
|
|
177
|
+
var INLINE_TAGS = /* @__PURE__ */ new Set([
|
|
178
|
+
"A",
|
|
179
|
+
"ABBR",
|
|
180
|
+
"B",
|
|
181
|
+
"BDO",
|
|
182
|
+
"BR",
|
|
183
|
+
"CITE",
|
|
184
|
+
"CODE",
|
|
185
|
+
"DFN",
|
|
186
|
+
"EM",
|
|
187
|
+
"I",
|
|
188
|
+
"KBD",
|
|
189
|
+
"MARK",
|
|
190
|
+
"Q",
|
|
191
|
+
"S",
|
|
192
|
+
"SAMP",
|
|
193
|
+
"SMALL",
|
|
194
|
+
"SPAN",
|
|
195
|
+
"STRONG",
|
|
196
|
+
"SUB",
|
|
197
|
+
"SUP",
|
|
198
|
+
"TIME",
|
|
199
|
+
"U",
|
|
200
|
+
"VAR",
|
|
201
|
+
"WBR"
|
|
202
|
+
]);
|
|
203
|
+
var SKIP_TAGS = /* @__PURE__ */ new Set([
|
|
204
|
+
"SCRIPT",
|
|
205
|
+
"STYLE",
|
|
206
|
+
"NOSCRIPT",
|
|
207
|
+
"TEMPLATE",
|
|
208
|
+
"SVG",
|
|
209
|
+
"CANVAS",
|
|
210
|
+
"VIDEO",
|
|
211
|
+
"AUDIO",
|
|
212
|
+
"IFRAME",
|
|
213
|
+
"OBJECT",
|
|
214
|
+
"EMBED"
|
|
215
|
+
]);
|
|
216
|
+
function detectKind(el) {
|
|
217
|
+
const tag = el.tagName;
|
|
218
|
+
if (tag === "IMG" || tag === "PICTURE") {
|
|
219
|
+
const w = el.getBoundingClientRect().width;
|
|
220
|
+
const h = el.getBoundingClientRect().height;
|
|
221
|
+
const ratio = Math.min(w, h) / Math.max(w, h);
|
|
222
|
+
if (ratio > 0.85 && w < 120) return "avatar";
|
|
223
|
+
return "image";
|
|
224
|
+
}
|
|
225
|
+
if (tag === "INPUT" || tag === "TEXTAREA" || tag === "SELECT") return "input";
|
|
226
|
+
if (tag === "BUTTON" || el.getAttribute("role") === "button") return "button";
|
|
227
|
+
if (tag === "HR") return "divider";
|
|
228
|
+
if (/^H[1-6]$/.test(tag)) return "heading";
|
|
229
|
+
if (tag === "SVG" || tag === "svg") return "icon";
|
|
230
|
+
const style = getComputedStyle(el);
|
|
231
|
+
const borderRadius = parseInt(style.borderRadius, 10);
|
|
232
|
+
const rect = el.getBoundingClientRect();
|
|
233
|
+
if (borderRadius >= rect.width / 2 && rect.width < 120 && rect.width > 16) {
|
|
234
|
+
return "avatar";
|
|
235
|
+
}
|
|
236
|
+
if (el.childNodes.length > 0) {
|
|
237
|
+
const hasDirectText = Array.from(el.childNodes).some(
|
|
238
|
+
(n) => n.nodeType === Node.TEXT_NODE && n.textContent?.trim()
|
|
239
|
+
);
|
|
240
|
+
if (hasDirectText && INLINE_TAGS.has(tag)) return "text";
|
|
241
|
+
if (hasDirectText && tag === "P") return "text";
|
|
242
|
+
}
|
|
243
|
+
return "block";
|
|
244
|
+
}
|
|
245
|
+
function computeRadius(el, kind) {
|
|
246
|
+
if (kind === "avatar") return 9999;
|
|
247
|
+
if (kind === "button") {
|
|
248
|
+
const style2 = getComputedStyle(el);
|
|
249
|
+
return Math.min(parseInt(style2.borderRadius, 10) || 6, 9999);
|
|
250
|
+
}
|
|
251
|
+
const style = getComputedStyle(el);
|
|
252
|
+
const r = parseInt(style.borderRadius, 10);
|
|
253
|
+
return isNaN(r) ? 0 : Math.min(r, 9999);
|
|
254
|
+
}
|
|
255
|
+
function isVisible(el) {
|
|
256
|
+
const style = getComputedStyle(el);
|
|
257
|
+
if (style.display === "none") return false;
|
|
258
|
+
if (style.visibility === "hidden") return false;
|
|
259
|
+
if (parseFloat(style.opacity) === 0) return false;
|
|
260
|
+
const rect = el.getBoundingClientRect();
|
|
261
|
+
return rect.width > 0 && rect.height > 0;
|
|
262
|
+
}
|
|
263
|
+
function isLeaf(el, contentAware) {
|
|
264
|
+
const tag = el.tagName;
|
|
265
|
+
if (tag === "IMG" || tag === "PICTURE" || tag === "INPUT" || tag === "TEXTAREA" || tag === "SELECT" || tag === "BUTTON" || tag === "HR" || tag === "SVG" || tag === "svg") {
|
|
266
|
+
return true;
|
|
267
|
+
}
|
|
268
|
+
if (contentAware) {
|
|
269
|
+
const hasOnlyText = Array.from(el.childNodes).every(
|
|
270
|
+
(n) => n.nodeType === Node.TEXT_NODE || INLINE_TAGS.has(n.tagName)
|
|
271
|
+
);
|
|
272
|
+
if (hasOnlyText && el.textContent?.trim()) return true;
|
|
273
|
+
}
|
|
274
|
+
if (el.children.length === 0) return true;
|
|
275
|
+
return false;
|
|
276
|
+
}
|
|
277
|
+
function extractBones(container, options = {}) {
|
|
278
|
+
const contentAware = options.contentAware ?? DEFAULTS.contentAware;
|
|
279
|
+
const minSize = options.minBoneSize ?? DEFAULTS.minBoneSize;
|
|
280
|
+
const containerRect = container.getBoundingClientRect();
|
|
281
|
+
const bones = [];
|
|
282
|
+
function walk(el) {
|
|
283
|
+
if (SKIP_TAGS.has(el.tagName)) return;
|
|
284
|
+
if (!isVisible(el)) return;
|
|
285
|
+
if (isLeaf(el, contentAware)) {
|
|
286
|
+
const rect = el.getBoundingClientRect();
|
|
287
|
+
if (rect.width < minSize || rect.height < minSize) return;
|
|
288
|
+
const kind = contentAware ? detectKind(el) : "block";
|
|
289
|
+
const r = computeRadius(el, kind);
|
|
290
|
+
bones.push({
|
|
291
|
+
x: Math.round((rect.left - containerRect.left) * 2) / 2,
|
|
292
|
+
y: Math.round((rect.top - containerRect.top) * 2) / 2,
|
|
293
|
+
w: Math.round(rect.width * 2) / 2,
|
|
294
|
+
h: Math.round(rect.height * 2) / 2,
|
|
295
|
+
r,
|
|
296
|
+
kind
|
|
297
|
+
});
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
300
|
+
for (const child of el.children) {
|
|
301
|
+
walk(child);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
walk(container);
|
|
305
|
+
return {
|
|
306
|
+
viewport: window.innerWidth,
|
|
307
|
+
containerWidth: Math.round(containerRect.width * 2) / 2,
|
|
308
|
+
containerHeight: Math.round(containerRect.height * 2) / 2,
|
|
309
|
+
bones
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
function getExtractorScript(selector, options = {}) {
|
|
313
|
+
return `
|
|
314
|
+
(function() {
|
|
315
|
+
${isVisible.toString()}
|
|
316
|
+
${isLeaf.toString()}
|
|
317
|
+
${detectKind.toString()}
|
|
318
|
+
${computeRadius.toString()}
|
|
319
|
+
|
|
320
|
+
var INLINE_TAGS = new Set(${JSON.stringify([...INLINE_TAGS])});
|
|
321
|
+
var SKIP_TAGS = new Set(${JSON.stringify([...SKIP_TAGS])});
|
|
322
|
+
var DEFAULTS = { contentAware: true, minBoneSize: 4 };
|
|
323
|
+
|
|
324
|
+
${extractBones.toString()}
|
|
325
|
+
|
|
326
|
+
var container = document.querySelector(${JSON.stringify(selector)});
|
|
327
|
+
if (!container) throw new Error('CastDOM: Container not found: ' + ${JSON.stringify(selector)});
|
|
328
|
+
return extractBones(container, ${JSON.stringify(options)});
|
|
329
|
+
})()
|
|
330
|
+
`.trim();
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
// src/components/vanilla.ts
|
|
334
|
+
var ACTIVE_ATTR = "data-castdom-active";
|
|
335
|
+
var SKELETON_ATTR = "data-castdom-skeleton";
|
|
336
|
+
function createCastDOM(config) {
|
|
337
|
+
let styleEl = null;
|
|
338
|
+
let cssInjected = false;
|
|
339
|
+
const activeContainers = /* @__PURE__ */ new Set();
|
|
340
|
+
function ensureCSS() {
|
|
341
|
+
if (cssInjected || typeof document === "undefined") return;
|
|
342
|
+
styleEl = document.createElement("style");
|
|
343
|
+
styleEl.setAttribute("data-castdom", "critical");
|
|
344
|
+
styleEl.textContent = [
|
|
345
|
+
`@keyframes castdom-shimmer{0%{background-position:-200% 0}100%{background-position:200% 0}}`,
|
|
346
|
+
`@keyframes castdom-pulse{0%,100%{opacity:1}50%{opacity:0.4}}`,
|
|
347
|
+
`@keyframes castdom-wave{0%{opacity:0.4}50%{opacity:1}100%{opacity:0.4}}`,
|
|
348
|
+
`@media(prefers-reduced-motion:reduce){.castdom-bone{animation:none!important}}`
|
|
349
|
+
].join("");
|
|
350
|
+
document.head.appendChild(styleEl);
|
|
351
|
+
cssInjected = true;
|
|
352
|
+
}
|
|
353
|
+
return {
|
|
354
|
+
loadManifest(manifest) {
|
|
355
|
+
loadManifest(manifest);
|
|
356
|
+
},
|
|
357
|
+
register(data) {
|
|
358
|
+
register(data);
|
|
359
|
+
},
|
|
360
|
+
show(name, container) {
|
|
361
|
+
const entry = get(name);
|
|
362
|
+
if (!entry) {
|
|
363
|
+
console.warn(`CastDOM: Skeleton "${name}" not found in registry`);
|
|
364
|
+
return;
|
|
365
|
+
}
|
|
366
|
+
ensureCSS();
|
|
367
|
+
if (!container.hasAttribute(ACTIVE_ATTR)) {
|
|
368
|
+
container.setAttribute(ACTIVE_ATTR, "true");
|
|
369
|
+
for (const child of Array.from(container.children)) {
|
|
370
|
+
if (!child.hasAttribute(SKELETON_ATTR)) {
|
|
371
|
+
child.style.display = "none";
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
const vw = typeof window !== "undefined" ? window.innerWidth : 1280;
|
|
376
|
+
const bp = selectBreakpoint(entry.data, vw);
|
|
377
|
+
if (!bp) return;
|
|
378
|
+
const skeletonDiv = document.createElement("div");
|
|
379
|
+
skeletonDiv.setAttribute(SKELETON_ATTR, name);
|
|
380
|
+
skeletonDiv.innerHTML = renderStandalone(entry.data, config);
|
|
381
|
+
container.appendChild(skeletonDiv);
|
|
382
|
+
activeContainers.add(container);
|
|
383
|
+
},
|
|
384
|
+
hide(name, container) {
|
|
385
|
+
const skeleton = container.querySelector(`[${SKELETON_ATTR}="${name}"]`);
|
|
386
|
+
if (skeleton) skeleton.remove();
|
|
387
|
+
container.removeAttribute(ACTIVE_ATTR);
|
|
388
|
+
for (const child of Array.from(container.children)) {
|
|
389
|
+
if (!child.hasAttribute(SKELETON_ATTR)) {
|
|
390
|
+
child.style.display = "";
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
activeContainers.delete(container);
|
|
394
|
+
},
|
|
395
|
+
toggle(name, container, loading) {
|
|
396
|
+
if (loading) {
|
|
397
|
+
this.show(name, container);
|
|
398
|
+
} else {
|
|
399
|
+
this.hide(name, container);
|
|
400
|
+
}
|
|
401
|
+
},
|
|
402
|
+
html(name, viewportWidth) {
|
|
403
|
+
const entry = get(name);
|
|
404
|
+
if (!entry) return "";
|
|
405
|
+
return renderStandalone(entry.data, config);
|
|
406
|
+
},
|
|
407
|
+
css() {
|
|
408
|
+
return generateCriticalCSS(
|
|
409
|
+
Array.from(activeContainers).map((c) => {
|
|
410
|
+
const name = c.querySelector(`[${SKELETON_ATTR}]`)?.getAttribute(SKELETON_ATTR);
|
|
411
|
+
return name ? get(name)?.data : void 0;
|
|
412
|
+
}).filter(Boolean),
|
|
413
|
+
config
|
|
414
|
+
);
|
|
415
|
+
},
|
|
416
|
+
injectCSS() {
|
|
417
|
+
ensureCSS();
|
|
418
|
+
},
|
|
419
|
+
destroy() {
|
|
420
|
+
for (const container of activeContainers) {
|
|
421
|
+
const skeletons = container.querySelectorAll(`[${SKELETON_ATTR}]`);
|
|
422
|
+
for (const s of skeletons) s.remove();
|
|
423
|
+
container.removeAttribute(ACTIVE_ATTR);
|
|
424
|
+
for (const child of Array.from(container.children)) {
|
|
425
|
+
child.style.display = "";
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
activeContainers.clear();
|
|
429
|
+
if (styleEl) {
|
|
430
|
+
styleEl.remove();
|
|
431
|
+
styleEl = null;
|
|
432
|
+
cssInjected = false;
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
};
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
export { compressBones, createCastDOM, decodeBonesToBase64, decompressBones, encodeBonesToBase64, extractBones, generateAnimationCSS, generateBoneAnimation, generateKeyframes, generateStaggerCSS, getExtractorScript };
|
|
439
|
+
//# sourceMappingURL=index.js.map
|
|
440
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/compress.ts","../src/core/animation.ts","../src/core/extractor.ts","../src/components/vanilla.ts"],"names":["style"],"mappings":"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","file":"index.js","sourcesContent":["import type {\n Bone,\n BreakpointData,\n CompressedBones,\n BoneKind,\n} from \"./types.js\";\nimport { BONE_KIND_INDEX, BONE_KIND_FROM_INDEX } from \"./types.js\";\n\n/**\n * Compress bone data for storage/wire transfer.\n *\n * Strategy:\n * - Quantize all values to integers (multiply by 2, round, store as int)\n * - Delta-encode x/y positions (sorted top-to-bottom, left-to-right)\n * - Pack into a flat number array: [x, y, w, h, r, kind, ...]\n *\n * Achieves ~60-70% size reduction vs raw JSON.\n */\nexport function compressBones(bp: BreakpointData): CompressedBones {\n // Sort bones top-to-bottom, left-to-right for better delta encoding\n const sorted = [...bp.bones].sort((a, b) => a.y - b.y || a.x - b.x);\n\n const data: number[] = [];\n let prevX = 0;\n let prevY = 0;\n\n for (const bone of sorted) {\n // Quantize to half-pixels (multiply by 2 to store as int)\n const x = Math.round(bone.x * 2);\n const y = Math.round(bone.y * 2);\n const w = Math.round(bone.w * 2);\n const h = Math.round(bone.h * 2);\n const r = Math.round(bone.r * 2);\n const kind = BONE_KIND_INDEX[bone.kind ?? \"block\"];\n\n // Delta encode position\n data.push(x - prevX, y - prevY, w, h, r, kind);\n prevX = x;\n prevY = y;\n }\n\n return {\n v: 1,\n vw: bp.viewport,\n c: [\n Math.round(bp.containerWidth * 2),\n Math.round(bp.containerHeight * 2),\n ],\n d: data,\n };\n}\n\n/** Decompress bone data back to a BreakpointData */\nexport function decompressBones(compressed: CompressedBones): BreakpointData {\n const bones: Bone[] = [];\n const d = compressed.d;\n let prevX = 0;\n let prevY = 0;\n\n for (let i = 0; i < d.length; i += 6) {\n const dx = d[i];\n const dy = d[i + 1];\n const w = d[i + 2];\n const h = d[i + 3];\n const r = d[i + 4];\n const kindIdx = d[i + 5];\n\n prevX += dx;\n prevY += dy;\n\n bones.push({\n x: prevX / 2,\n y: prevY / 2,\n w: w / 2,\n h: h / 2,\n r: r / 2,\n kind: BONE_KIND_FROM_INDEX[kindIdx] ?? \"block\",\n });\n }\n\n return {\n viewport: compressed.vw,\n containerWidth: compressed.c[0] / 2,\n containerHeight: compressed.c[1] / 2,\n bones,\n };\n}\n\n/**\n * Encode compressed bones to a base64 string for embedding.\n * Uses a simple variable-length integer encoding for even smaller output.\n */\nexport function encodeBonesToBase64(compressed: CompressedBones): string {\n const header = [compressed.v, compressed.vw, compressed.c[0], compressed.c[1]];\n const allNums = [...header, compressed.d.length, ...compressed.d];\n\n // Zigzag encode signed integers, then varint encode\n const bytes: number[] = [];\n for (const n of allNums) {\n // Zigzag: map signed to unsigned\n const z = n >= 0 ? n * 2 : -n * 2 - 1;\n // Varint: 7 bits per byte, high bit = continuation\n let val = z;\n while (val >= 0x80) {\n bytes.push((val & 0x7f) | 0x80);\n val >>>= 7;\n }\n bytes.push(val & 0x7f);\n }\n\n // Convert to base64\n if (typeof Buffer !== \"undefined\") {\n return Buffer.from(new Uint8Array(bytes)).toString(\"base64\");\n }\n // Browser fallback\n return btoa(String.fromCharCode(...bytes));\n}\n\n/** Decode base64-encoded bones back to CompressedBones */\nexport function decodeBonesToBase64(b64: string): CompressedBones {\n let bytes: Uint8Array;\n\n if (typeof Buffer !== \"undefined\") {\n bytes = Buffer.from(b64, \"base64\");\n } else {\n const raw = atob(b64);\n bytes = new Uint8Array(raw.length);\n for (let i = 0; i < raw.length; i++) bytes[i] = raw.charCodeAt(i);\n }\n\n // Decode varints\n const nums: number[] = [];\n let pos = 0;\n while (pos < bytes.length) {\n let val = 0;\n let shift = 0;\n let b: number;\n do {\n b = bytes[pos++];\n val |= (b & 0x7f) << shift;\n shift += 7;\n } while (b & 0x80);\n // Zigzag decode\n nums.push(val & 1 ? -(val >>> 1) - 1 : val >>> 1);\n }\n\n const v = nums[0] as 1;\n const vw = nums[1];\n const c: [number, number] = [nums[2], nums[3]];\n const dLen = nums[4];\n const d = nums.slice(5, 5 + dLen);\n\n return { v, vw, c, d };\n}\n","import type { CastDOMConfig } from \"./types.js\";\nimport { DEFAULTS } from \"./types.js\";\n\n/**\n * CSS animation generator for CastDOM skeletons.\n *\n * Generates optimized CSS animations:\n * - Shimmer (default): gradient sweep from left to right\n * - Pulse: opacity fade in/out\n * - Wave: staggered reveal animation\n * - None: static placeholder (for prefers-reduced-motion)\n */\n\nexport type AnimationType = \"shimmer\" | \"pulse\" | \"wave\" | \"none\";\n\nexport interface AnimationConfig {\n type?: AnimationType;\n duration?: number;\n color?: string;\n shimmerColor?: string;\n classPrefix?: string;\n /** Stagger delay between bones for wave animation (ms) */\n stagger?: number;\n}\n\n/** Generate the CSS keyframes for a given animation type */\nexport function generateKeyframes(config?: AnimationConfig): string {\n const type = config?.type ?? \"shimmer\";\n const prefix = config?.classPrefix ?? DEFAULTS.classPrefix;\n const duration = config?.duration ?? DEFAULTS.animationDuration;\n\n switch (type) {\n case \"shimmer\":\n return `@keyframes ${prefix}-shimmer{0%{background-position:-200% 0}100%{background-position:200% 0}}`;\n\n case \"pulse\":\n return `@keyframes ${prefix}-pulse{0%,100%{opacity:1}50%{opacity:0.4}}`;\n\n case \"wave\":\n return `@keyframes ${prefix}-wave{0%{opacity:0.4}50%{opacity:1}100%{opacity:0.4}}`;\n\n case \"none\":\n return \"\";\n }\n}\n\n/** Generate the CSS for bone elements with a given animation type */\nexport function generateBoneAnimation(config?: AnimationConfig): string {\n const type = config?.type ?? \"shimmer\";\n const prefix = config?.classPrefix ?? DEFAULTS.classPrefix;\n const duration = config?.duration ?? DEFAULTS.animationDuration;\n const color = config?.color ?? DEFAULTS.color;\n const shimmerColor = config?.shimmerColor ?? DEFAULTS.shimmerColor;\n\n switch (type) {\n case \"shimmer\":\n return `background:linear-gradient(90deg,${color} 25%,${shimmerColor} 50%,${color} 75%);background-size:200% 100%;animation:${prefix}-shimmer ${duration}ms ease-in-out infinite`;\n\n case \"pulse\":\n return `background:${color};animation:${prefix}-pulse ${duration}ms ease-in-out infinite`;\n\n case \"wave\":\n return `background:${color};animation:${prefix}-wave ${duration}ms ease-in-out infinite`;\n\n case \"none\":\n return `background:${color}`;\n }\n}\n\n/**\n * Generate stagger delays for wave animation.\n * Each bone gets a progressively delayed start.\n */\nexport function generateStaggerCSS(\n skeletonName: string,\n boneCount: number,\n config?: AnimationConfig\n): string {\n const prefix = config?.classPrefix ?? DEFAULTS.classPrefix;\n const stagger = config?.stagger ?? 50;\n const rules: string[] = [];\n\n for (let i = 0; i < boneCount; i++) {\n rules.push(\n `.${prefix}-${skeletonName} .${prefix}-bone:nth-child(${i + 1}){animation-delay:${i * stagger}ms}`\n );\n }\n\n return rules.join(\"\");\n}\n\n/**\n * Generate complete animation CSS bundle for a skeleton.\n * Includes keyframes, bone styles, and reduced-motion fallback.\n */\nexport function generateAnimationCSS(\n skeletonName: string,\n boneCount: number,\n config?: AnimationConfig\n): string {\n const prefix = config?.classPrefix ?? DEFAULTS.classPrefix;\n const type = config?.type ?? \"shimmer\";\n\n const parts: string[] = [];\n\n // Keyframes\n const kf = generateKeyframes(config);\n if (kf) parts.push(kf);\n\n // Bone animation\n const anim = generateBoneAnimation(config);\n parts.push(`.${prefix}-${skeletonName} .${prefix}-bone{position:absolute;${anim}}`);\n\n // Stagger for wave\n if (type === \"wave\") {\n parts.push(generateStaggerCSS(skeletonName, boneCount, config));\n }\n\n // Reduced motion fallback\n parts.push(\n `@media(prefers-reduced-motion:reduce){.${prefix}-${skeletonName} .${prefix}-bone{animation:none!important}}`\n );\n\n return parts.join(\"\\n\");\n}\n","import type { Bone, BoneKind, BreakpointData, CastDOMConfig } from \"./types.js\";\nimport { DEFAULTS } from \"./types.js\";\n\n/**\n * DOM Extractor — runs in the browser context.\n * Reads getBoundingClientRect() on every visible element inside a container\n * and produces a flat array of bones.\n *\n * This is injected into the page via Playwright during the build step,\n * or can be called directly in dev mode.\n */\n\nconst INLINE_TAGS = new Set([\n \"A\", \"ABBR\", \"B\", \"BDO\", \"BR\", \"CITE\", \"CODE\", \"DFN\", \"EM\", \"I\",\n \"KBD\", \"MARK\", \"Q\", \"S\", \"SAMP\", \"SMALL\", \"SPAN\", \"STRONG\", \"SUB\",\n \"SUP\", \"TIME\", \"U\", \"VAR\", \"WBR\",\n]);\n\nconst SKIP_TAGS = new Set([\n \"SCRIPT\", \"STYLE\", \"NOSCRIPT\", \"TEMPLATE\", \"SVG\", \"CANVAS\",\n \"VIDEO\", \"AUDIO\", \"IFRAME\", \"OBJECT\", \"EMBED\",\n]);\n\n/** Detect the semantic kind of a DOM element */\nfunction detectKind(el: Element): BoneKind {\n const tag = el.tagName;\n\n if (tag === \"IMG\" || tag === \"PICTURE\") {\n const w = el.getBoundingClientRect().width;\n const h = el.getBoundingClientRect().height;\n const ratio = Math.min(w, h) / Math.max(w, h);\n if (ratio > 0.85 && w < 120) return \"avatar\";\n return \"image\";\n }\n\n if (tag === \"INPUT\" || tag === \"TEXTAREA\" || tag === \"SELECT\") return \"input\";\n if (tag === \"BUTTON\" || el.getAttribute(\"role\") === \"button\") return \"button\";\n if (tag === \"HR\") return \"divider\";\n if (/^H[1-6]$/.test(tag)) return \"heading\";\n if (tag === \"SVG\" || tag === \"svg\") return \"icon\";\n\n // Check for avatar-like elements (small, round images via CSS)\n const style = getComputedStyle(el);\n const borderRadius = parseInt(style.borderRadius, 10);\n const rect = el.getBoundingClientRect();\n if (borderRadius >= rect.width / 2 && rect.width < 120 && rect.width > 16) {\n return \"avatar\";\n }\n\n // Text detection\n if (el.childNodes.length > 0) {\n const hasDirectText = Array.from(el.childNodes).some(\n (n) => n.nodeType === Node.TEXT_NODE && n.textContent?.trim()\n );\n if (hasDirectText && INLINE_TAGS.has(tag)) return \"text\";\n if (hasDirectText && tag === \"P\") return \"text\";\n }\n\n return \"block\";\n}\n\n/** Compute border radius for a bone */\nfunction computeRadius(el: Element, kind: BoneKind): number {\n if (kind === \"avatar\") return 9999;\n if (kind === \"button\") {\n const style = getComputedStyle(el);\n return Math.min(parseInt(style.borderRadius, 10) || 6, 9999);\n }\n\n const style = getComputedStyle(el);\n const r = parseInt(style.borderRadius, 10);\n return isNaN(r) ? 0 : Math.min(r, 9999);\n}\n\n/** Check if element is visible */\nfunction isVisible(el: Element): boolean {\n const style = getComputedStyle(el);\n if (style.display === \"none\") return false;\n if (style.visibility === \"hidden\") return false;\n if (parseFloat(style.opacity) === 0) return false;\n\n const rect = el.getBoundingClientRect();\n return rect.width > 0 && rect.height > 0;\n}\n\n/** Check if element is a leaf (should be a bone, not traversed further) */\nfunction isLeaf(el: Element, contentAware: boolean): boolean {\n const tag = el.tagName;\n\n // Always leaf: replaced elements, form controls\n if (\n tag === \"IMG\" || tag === \"PICTURE\" || tag === \"INPUT\" ||\n tag === \"TEXTAREA\" || tag === \"SELECT\" || tag === \"BUTTON\" ||\n tag === \"HR\" || tag === \"SVG\" || tag === \"svg\"\n ) {\n return true;\n }\n\n // If content-aware, check for text-only leaves\n if (contentAware) {\n const hasOnlyText = Array.from(el.childNodes).every(\n (n) => n.nodeType === Node.TEXT_NODE || INLINE_TAGS.has((n as Element).tagName)\n );\n if (hasOnlyText && el.textContent?.trim()) return true;\n }\n\n // No children = leaf\n if (el.children.length === 0) return true;\n\n return false;\n}\n\nexport interface ExtractOptions {\n contentAware?: boolean;\n minBoneSize?: number;\n}\n\n/**\n * Extract bones from a container element.\n * Call this in the browser context (via Playwright or directly).\n */\nexport function extractBones(\n container: Element,\n options: ExtractOptions = {}\n): BreakpointData {\n const contentAware = options.contentAware ?? DEFAULTS.contentAware;\n const minSize = options.minBoneSize ?? DEFAULTS.minBoneSize;\n const containerRect = container.getBoundingClientRect();\n const bones: Bone[] = [];\n\n function walk(el: Element): void {\n if (SKIP_TAGS.has(el.tagName)) return;\n if (!isVisible(el)) return;\n\n if (isLeaf(el, contentAware)) {\n const rect = el.getBoundingClientRect();\n\n // Skip tiny elements\n if (rect.width < minSize || rect.height < minSize) return;\n\n const kind = contentAware ? detectKind(el) : \"block\";\n const r = computeRadius(el, kind);\n\n // Quantize to nearest 0.5px for smaller output\n bones.push({\n x: Math.round((rect.left - containerRect.left) * 2) / 2,\n y: Math.round((rect.top - containerRect.top) * 2) / 2,\n w: Math.round(rect.width * 2) / 2,\n h: Math.round(rect.height * 2) / 2,\n r,\n kind,\n });\n return;\n }\n\n // Traverse children\n for (const child of el.children) {\n walk(child);\n }\n }\n\n walk(container);\n\n return {\n viewport: window.innerWidth,\n containerWidth: Math.round(containerRect.width * 2) / 2,\n containerHeight: Math.round(containerRect.height * 2) / 2,\n bones,\n };\n}\n\n/**\n * Serializable extraction function — returns a string that can be\n * evaluated in a Playwright page context.\n */\nexport function getExtractorScript(\n selector: string,\n options: ExtractOptions = {}\n): string {\n // Serialize the entire extraction logic for injection\n return `\n(function() {\n ${isVisible.toString()}\n ${isLeaf.toString()}\n ${detectKind.toString()}\n ${computeRadius.toString()}\n\n var INLINE_TAGS = new Set(${JSON.stringify([...INLINE_TAGS])});\n var SKIP_TAGS = new Set(${JSON.stringify([...SKIP_TAGS])});\n var DEFAULTS = { contentAware: true, minBoneSize: 4 };\n\n ${extractBones.toString()}\n\n var container = document.querySelector(${JSON.stringify(selector)});\n if (!container) throw new Error('CastDOM: Container not found: ' + ${JSON.stringify(selector)});\n return extractBones(container, ${JSON.stringify(options)});\n})()\n `.trim();\n}\n","import type { SkeletonData, CastDOMConfig } from \"../core/types.js\";\nimport { get as getFromRegistry, register, loadManifest } from \"../core/registry.js\";\nimport { renderStandalone, renderResponsiveHTML, generateCriticalCSS } from \"../core/renderer.js\";\nimport { selectBreakpoint } from \"../core/responsive.js\";\nimport { DEFAULTS } from \"../core/types.js\";\n\n/**\n * Vanilla JS API for CastDOM.\n * Use this when you're not using React or another framework.\n *\n * Usage:\n * ```js\n * import { createCastDOM } from 'castdom';\n *\n * const castdom = createCastDOM();\n * castdom.loadManifest(manifest);\n *\n * // Show skeleton\n * castdom.show('user-card', document.getElementById('container'));\n *\n * // Later, hide skeleton and show real content\n * castdom.hide('user-card', document.getElementById('container'));\n * ```\n */\n\nexport interface CastDOMInstance {\n /** Load skeleton data from a manifest */\n loadManifest(manifest: { skeletons: SkeletonData[] }): void;\n /** Register a single skeleton */\n register(data: SkeletonData): void;\n /** Show a skeleton in a container element */\n show(name: string, container: HTMLElement): void;\n /** Hide the skeleton and restore the container */\n hide(name: string, container: HTMLElement): void;\n /** Toggle skeleton visibility based on loading state */\n toggle(name: string, container: HTMLElement, loading: boolean): void;\n /** Get the HTML string for a skeleton (for manual insertion) */\n html(name: string, viewportWidth?: number): string;\n /** Get the CSS for all registered skeletons */\n css(): string;\n /** Inject critical CSS into the document head */\n injectCSS(): void;\n /** Destroy the instance and clean up */\n destroy(): void;\n}\n\nconst ACTIVE_ATTR = \"data-castdom-active\";\nconst SKELETON_ATTR = \"data-castdom-skeleton\";\n\nexport function createCastDOM(config?: Partial<CastDOMConfig>): CastDOMInstance {\n let styleEl: HTMLStyleElement | null = null;\n let cssInjected = false;\n const activeContainers = new Set<HTMLElement>();\n\n function ensureCSS(): void {\n if (cssInjected || typeof document === \"undefined\") return;\n\n styleEl = document.createElement(\"style\");\n styleEl.setAttribute(\"data-castdom\", \"critical\");\n styleEl.textContent = [\n `@keyframes castdom-shimmer{0%{background-position:-200% 0}100%{background-position:200% 0}}`,\n `@keyframes castdom-pulse{0%,100%{opacity:1}50%{opacity:0.4}}`,\n `@keyframes castdom-wave{0%{opacity:0.4}50%{opacity:1}100%{opacity:0.4}}`,\n `@media(prefers-reduced-motion:reduce){.castdom-bone{animation:none!important}}`,\n ].join(\"\");\n document.head.appendChild(styleEl);\n cssInjected = true;\n }\n\n return {\n loadManifest(manifest) {\n loadManifest(manifest);\n },\n\n register(data) {\n register(data);\n },\n\n show(name, container) {\n const entry = getFromRegistry(name);\n if (!entry) {\n console.warn(`CastDOM: Skeleton \"${name}\" not found in registry`);\n return;\n }\n\n ensureCSS();\n\n // Store original content\n if (!container.hasAttribute(ACTIVE_ATTR)) {\n container.setAttribute(ACTIVE_ATTR, \"true\");\n // Hide children but keep them in DOM\n for (const child of Array.from(container.children)) {\n if (!child.hasAttribute(SKELETON_ATTR)) {\n (child as HTMLElement).style.display = \"none\";\n }\n }\n }\n\n // Create skeleton element\n const vw = typeof window !== \"undefined\" ? window.innerWidth : 1280;\n const bp = selectBreakpoint(entry.data, vw);\n if (!bp) return;\n\n const skeletonDiv = document.createElement(\"div\");\n skeletonDiv.setAttribute(SKELETON_ATTR, name);\n skeletonDiv.innerHTML = renderStandalone(entry.data, config);\n container.appendChild(skeletonDiv);\n activeContainers.add(container);\n },\n\n hide(name, container) {\n // Remove skeleton\n const skeleton = container.querySelector(`[${SKELETON_ATTR}=\"${name}\"]`);\n if (skeleton) skeleton.remove();\n\n // Restore children\n container.removeAttribute(ACTIVE_ATTR);\n for (const child of Array.from(container.children)) {\n if (!(child as HTMLElement).hasAttribute(SKELETON_ATTR)) {\n (child as HTMLElement).style.display = \"\";\n }\n }\n activeContainers.delete(container);\n },\n\n toggle(name, container, loading) {\n if (loading) {\n this.show(name, container);\n } else {\n this.hide(name, container);\n }\n },\n\n html(name, viewportWidth) {\n const entry = getFromRegistry(name);\n if (!entry) return \"\";\n return renderStandalone(entry.data, config);\n },\n\n css() {\n return generateCriticalCSS(\n Array.from(activeContainers)\n .map((c) => {\n const name = c.querySelector(`[${SKELETON_ATTR}]`)?.getAttribute(SKELETON_ATTR);\n return name ? getFromRegistry(name)?.data : undefined;\n })\n .filter(Boolean) as SkeletonData[],\n config\n );\n },\n\n injectCSS() {\n ensureCSS();\n },\n\n destroy() {\n // Remove all active skeletons\n for (const container of activeContainers) {\n const skeletons = container.querySelectorAll(`[${SKELETON_ATTR}]`);\n for (const s of skeletons) s.remove();\n container.removeAttribute(ACTIVE_ATTR);\n for (const child of Array.from(container.children)) {\n (child as HTMLElement).style.display = \"\";\n }\n }\n activeContainers.clear();\n\n // Remove injected CSS\n if (styleEl) {\n styleEl.remove();\n styleEl = null;\n cssInjected = false;\n }\n },\n };\n}\n\nexport default createCastDOM;\n"]}
|
package/dist/next.cjs
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunkO4OOMGGM_cjs = require('./chunk-O4OOMGGM.cjs');
|
|
4
|
+
require('./chunk-ORY4OMZ5.cjs');
|
|
5
|
+
var chunkYDT4TPB7_cjs = require('./chunk-YDT4TPB7.cjs');
|
|
6
|
+
var chunkQLEBTZIB_cjs = require('./chunk-QLEBTZIB.cjs');
|
|
7
|
+
var chunkXS5HAU5E_cjs = require('./chunk-XS5HAU5E.cjs');
|
|
8
|
+
require('./chunk-JRQ6EVQP.cjs');
|
|
9
|
+
|
|
10
|
+
// src/adapters/nextjs.ts
|
|
11
|
+
function initCastDOM(manifest) {
|
|
12
|
+
chunkYDT4TPB7_cjs.loadManifest(manifest);
|
|
13
|
+
}
|
|
14
|
+
function getSkeletonProps(names, config) {
|
|
15
|
+
const skeletonHTML = {};
|
|
16
|
+
const skeletons = [];
|
|
17
|
+
for (const name of names) {
|
|
18
|
+
const entry = chunkYDT4TPB7_cjs.get(name);
|
|
19
|
+
if (entry) {
|
|
20
|
+
skeletonHTML[name] = chunkQLEBTZIB_cjs.renderSkeleton(entry.data, { config });
|
|
21
|
+
skeletons.push(entry.data);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return {
|
|
25
|
+
skeletonHTML,
|
|
26
|
+
skeletonCSS: chunkXS5HAU5E_cjs.generateCriticalCSS(skeletons, config)
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
function generateCastDOMHead(skeletonNames, config) {
|
|
30
|
+
const skeletons = [];
|
|
31
|
+
for (const name of skeletonNames) {
|
|
32
|
+
const entry = chunkYDT4TPB7_cjs.get(name);
|
|
33
|
+
if (entry) skeletons.push(entry.data);
|
|
34
|
+
}
|
|
35
|
+
if (skeletons.length === 0) return "";
|
|
36
|
+
return [chunkQLEBTZIB_cjs.renderCriticalStyleTag(skeletons, config), chunkQLEBTZIB_cjs.renderHydrationScript()].join("\n");
|
|
37
|
+
}
|
|
38
|
+
function withCastDOMConfig(nextConfig = {}) {
|
|
39
|
+
return {
|
|
40
|
+
...nextConfig,
|
|
41
|
+
webpack(config, options) {
|
|
42
|
+
const existingWebpack = typeof nextConfig.webpack === "function" ? nextConfig.webpack(config, options) : config;
|
|
43
|
+
return existingWebpack;
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
Object.defineProperty(exports, "CastDOM", {
|
|
49
|
+
enumerable: true,
|
|
50
|
+
get: function () { return chunkO4OOMGGM_cjs.CastDOM; }
|
|
51
|
+
});
|
|
52
|
+
Object.defineProperty(exports, "CastDOMStyle", {
|
|
53
|
+
enumerable: true,
|
|
54
|
+
get: function () { return chunkO4OOMGGM_cjs.CastDOMStyle; }
|
|
55
|
+
});
|
|
56
|
+
Object.defineProperty(exports, "useCastDOM", {
|
|
57
|
+
enumerable: true,
|
|
58
|
+
get: function () { return chunkO4OOMGGM_cjs.useCastDOM; }
|
|
59
|
+
});
|
|
60
|
+
exports.generateCastDOMHead = generateCastDOMHead;
|
|
61
|
+
exports.getSkeletonProps = getSkeletonProps;
|
|
62
|
+
exports.initCastDOM = initCastDOM;
|
|
63
|
+
exports.withCastDOMConfig = withCastDOMConfig;
|
|
64
|
+
//# sourceMappingURL=next.cjs.map
|
|
65
|
+
//# sourceMappingURL=next.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/adapters/nextjs.ts"],"names":["loadManifest","get","renderSkeleton","generateCriticalCSS","renderCriticalStyleTag","renderHydrationScript"],"mappings":";;;;;;;;;;AA8CO,SAAS,YAAY,QAAA,EAA+C;AACzE,EAAAA,8BAAA,CAAa,QAAQ,CAAA;AACvB;AAaO,SAAS,gBAAA,CACd,OACA,MAAA,EAC+D;AAC/D,EAAA,MAAM,eAAuC,EAAC;AAC9C,EAAA,MAAM,YAA4B,EAAC;AAEnC,EAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,IAAA,MAAM,KAAA,GAAQC,sBAAgB,IAAI,CAAA;AAClC,IAAA,IAAI,KAAA,EAAO;AACT,MAAA,YAAA,CAAa,IAAI,CAAA,GAAIC,gCAAA,CAAe,MAAM,IAAA,EAAM,EAAE,QAAQ,CAAA;AAC1D,MAAA,SAAA,CAAU,IAAA,CAAK,MAAM,IAAI,CAAA;AAAA,IAC3B;AAAA,EACF;AAEA,EAAA,OAAO;AAAA,IACL,YAAA;AAAA,IACA,WAAA,EAAaC,qCAAA,CAAoB,SAAA,EAAW,MAAM;AAAA,GACpD;AACF;AAaO,SAAS,mBAAA,CACd,eACA,MAAA,EACQ;AACR,EAAA,MAAM,YAA4B,EAAC;AAEnC,EAAA,KAAA,MAAW,QAAQ,aAAA,EAAe;AAChC,IAAA,MAAM,KAAA,GAAQF,sBAAgB,IAAI,CAAA;AAClC,IAAA,IAAI,KAAA,EAAO,SAAA,CAAU,IAAA,CAAK,KAAA,CAAM,IAAI,CAAA;AAAA,EACtC;AAEA,EAAA,IAAI,SAAA,CAAU,MAAA,KAAW,CAAA,EAAG,OAAO,EAAA;AAEnC,EAAA,OAAO,CAACG,yCAAuB,SAAA,EAAW,MAAM,GAAGC,uCAAA,EAAuB,CAAA,CAAE,IAAA,CAAK,IAAI,CAAA;AACvF;AAkCO,SAAS,iBAAA,CAAkB,UAAA,GAAsC,EAAC,EAA4B;AACnG,EAAA,OAAO;AAAA,IACL,GAAG,UAAA;AAAA,IACH,OAAA,CAAQ,QAAiC,OAAA,EAAkC;AAEzE,MAAA,MAAM,eAAA,GACJ,OAAO,UAAA,CAAW,OAAA,KAAY,aACzB,UAAA,CAAW,OAAA,CAAqB,MAAA,EAAQ,OAAO,CAAA,GAChD,MAAA;AAEN,MAAA,OAAO,eAAA;AAAA,IACT;AAAA,GACF;AACF","file":"next.cjs","sourcesContent":["import type { SkeletonData, CastDOMConfig } from \"../core/types.js\";\nimport { renderSkeleton, renderCriticalStyleTag, renderHydrationScript } from \"../seo/ssr.js\";\nimport { register, loadManifest, get as getFromRegistry } from \"../core/registry.js\";\nimport { generateCriticalCSS } from \"../core/renderer.js\";\n\n/**\n * Next.js adapter for CastDOM.\n *\n * Supports:\n * - App Router (React Server Components)\n * - Pages Router (getServerSideProps / getStaticProps)\n * - Automatic loading.tsx generation\n * - Middleware-based skeleton injection\n *\n * Usage (App Router):\n * ```tsx\n * // app/layout.tsx\n * import { CastDOMProvider } from \"castdom/next\";\n * import manifest from \".castdom/manifest.json\";\n *\n * export default function RootLayout({ children }) {\n * return (\n * <CastDOMProvider manifest={manifest}>\n * {children}\n * </CastDOMProvider>\n * );\n * }\n * ```\n *\n * Usage (Pages Router):\n * ```tsx\n * // pages/_app.tsx\n * import { initCastDOM } from \"castdom/next\";\n * import manifest from \".castdom/manifest.json\";\n *\n * initCastDOM(manifest);\n * ```\n */\n\n// Re-export React components for convenience\nexport { CastDOM, CastDOMStyle, useCastDOM } from \"../components/react.js\";\n\n/**\n * Initialize CastDOM in a Next.js app.\n * Call once in _app.tsx or layout.tsx.\n */\nexport function initCastDOM(manifest: { skeletons: SkeletonData[] }): void {\n loadManifest(manifest);\n}\n\n/**\n * Server-side helper for getServerSideProps / getStaticProps.\n * Returns skeleton HTML that can be passed as props.\n *\n * ```ts\n * export async function getServerSideProps() {\n * const { skeletonHTML, skeletonCSS } = getSkeletonProps([\"user-card\", \"feed-item\"]);\n * return { props: { skeletonHTML, skeletonCSS } };\n * }\n * ```\n */\nexport function getSkeletonProps(\n names: string[],\n config?: Partial<CastDOMConfig>\n): { skeletonHTML: Record<string, string>; skeletonCSS: string } {\n const skeletonHTML: Record<string, string> = {};\n const skeletons: SkeletonData[] = [];\n\n for (const name of names) {\n const entry = getFromRegistry(name);\n if (entry) {\n skeletonHTML[name] = renderSkeleton(entry.data, { config });\n skeletons.push(entry.data);\n }\n }\n\n return {\n skeletonHTML,\n skeletonCSS: generateCriticalCSS(skeletons, config),\n };\n}\n\n/**\n * Next.js App Router metadata helper.\n * Generates <head> tags for skeleton critical CSS.\n *\n * ```tsx\n * // app/layout.tsx\n * import { generateCastDOMMetadata } from \"castdom/next\";\n *\n * export const metadata = generateCastDOMMetadata([\"user-card\"]);\n * ```\n */\nexport function generateCastDOMHead(\n skeletonNames: string[],\n config?: Partial<CastDOMConfig>\n): string {\n const skeletons: SkeletonData[] = [];\n\n for (const name of skeletonNames) {\n const entry = getFromRegistry(name);\n if (entry) skeletons.push(entry.data);\n }\n\n if (skeletons.length === 0) return \"\";\n\n return [renderCriticalStyleTag(skeletons, config), renderHydrationScript()].join(\"\\n\");\n}\n\n/**\n * Next.js middleware helper — injects skeleton HTML into streaming responses.\n * Use this for automatic skeleton injection without modifying page components.\n *\n * ```ts\n * // middleware.ts\n * import { withCastDOM } from \"castdom/next\";\n *\n * export default withCastDOM({\n * skeletons: { \"/dashboard\": \"dashboard-skeleton\" },\n * });\n * ```\n */\nexport interface CastDOMMiddlewareConfig {\n /** Map of route patterns to skeleton names */\n skeletons: Record<string, string | string[]>;\n /** Config overrides */\n config?: Partial<CastDOMConfig>;\n}\n\n/**\n * Create a Next.js config plugin that adds CastDOM webpack config.\n *\n * ```js\n * // next.config.js\n * const { withCastDOMConfig } = require(\"castdom/next\");\n *\n * module.exports = withCastDOMConfig({\n * // your next.js config\n * });\n * ```\n */\nexport function withCastDOMConfig(nextConfig: Record<string, unknown> = {}): Record<string, unknown> {\n return {\n ...nextConfig,\n webpack(config: Record<string, unknown>, options: Record<string, unknown>) {\n // Add .castdom to module resolution\n const existingWebpack =\n typeof nextConfig.webpack === \"function\"\n ? (nextConfig.webpack as Function)(config, options)\n : config;\n\n return existingWebpack;\n },\n };\n}\n"]}
|
package/dist/next.d.cts
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { C as CastDOMConfig, S as SkeletonData } from './types-ChD5jENU.cjs';
|
|
2
|
+
export { CastDOM, CastDOMStyle, useCastDOM } from './react.cjs';
|
|
3
|
+
import 'react';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Initialize CastDOM in a Next.js app.
|
|
7
|
+
* Call once in _app.tsx or layout.tsx.
|
|
8
|
+
*/
|
|
9
|
+
declare function initCastDOM(manifest: {
|
|
10
|
+
skeletons: SkeletonData[];
|
|
11
|
+
}): void;
|
|
12
|
+
/**
|
|
13
|
+
* Server-side helper for getServerSideProps / getStaticProps.
|
|
14
|
+
* Returns skeleton HTML that can be passed as props.
|
|
15
|
+
*
|
|
16
|
+
* ```ts
|
|
17
|
+
* export async function getServerSideProps() {
|
|
18
|
+
* const { skeletonHTML, skeletonCSS } = getSkeletonProps(["user-card", "feed-item"]);
|
|
19
|
+
* return { props: { skeletonHTML, skeletonCSS } };
|
|
20
|
+
* }
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
declare function getSkeletonProps(names: string[], config?: Partial<CastDOMConfig>): {
|
|
24
|
+
skeletonHTML: Record<string, string>;
|
|
25
|
+
skeletonCSS: string;
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Next.js App Router metadata helper.
|
|
29
|
+
* Generates <head> tags for skeleton critical CSS.
|
|
30
|
+
*
|
|
31
|
+
* ```tsx
|
|
32
|
+
* // app/layout.tsx
|
|
33
|
+
* import { generateCastDOMMetadata } from "castdom/next";
|
|
34
|
+
*
|
|
35
|
+
* export const metadata = generateCastDOMMetadata(["user-card"]);
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
declare function generateCastDOMHead(skeletonNames: string[], config?: Partial<CastDOMConfig>): string;
|
|
39
|
+
/**
|
|
40
|
+
* Next.js middleware helper — injects skeleton HTML into streaming responses.
|
|
41
|
+
* Use this for automatic skeleton injection without modifying page components.
|
|
42
|
+
*
|
|
43
|
+
* ```ts
|
|
44
|
+
* // middleware.ts
|
|
45
|
+
* import { withCastDOM } from "castdom/next";
|
|
46
|
+
*
|
|
47
|
+
* export default withCastDOM({
|
|
48
|
+
* skeletons: { "/dashboard": "dashboard-skeleton" },
|
|
49
|
+
* });
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
52
|
+
interface CastDOMMiddlewareConfig {
|
|
53
|
+
/** Map of route patterns to skeleton names */
|
|
54
|
+
skeletons: Record<string, string | string[]>;
|
|
55
|
+
/** Config overrides */
|
|
56
|
+
config?: Partial<CastDOMConfig>;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Create a Next.js config plugin that adds CastDOM webpack config.
|
|
60
|
+
*
|
|
61
|
+
* ```js
|
|
62
|
+
* // next.config.js
|
|
63
|
+
* const { withCastDOMConfig } = require("castdom/next");
|
|
64
|
+
*
|
|
65
|
+
* module.exports = withCastDOMConfig({
|
|
66
|
+
* // your next.js config
|
|
67
|
+
* });
|
|
68
|
+
* ```
|
|
69
|
+
*/
|
|
70
|
+
declare function withCastDOMConfig(nextConfig?: Record<string, unknown>): Record<string, unknown>;
|
|
71
|
+
|
|
72
|
+
export { type CastDOMMiddlewareConfig, generateCastDOMHead, getSkeletonProps, initCastDOM, withCastDOMConfig };
|