@lukas_holdings/castdom 1.0.0 → 1.0.1
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/README.md +50 -21
- package/package.json +10 -1
package/README.md
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<p align="center">
|
|
2
|
-
<img src="https://img.shields.io/npm/v/castdom?style=flat-square&color=000" alt="npm version"
|
|
2
|
+
<a href="https://www.npmjs.com/package/@lukas_holdings/castdom"><img src="https://img.shields.io/npm/v/@lukas_holdings/castdom?style=flat-square&color=000" alt="npm version" /></a>
|
|
3
|
+
<a href="https://www.npmjs.com/package/@lukas_holdings/castdom"><img src="https://img.shields.io/npm/dm/@lukas_holdings/castdom?style=flat-square&color=000" alt="npm downloads" /></a>
|
|
3
4
|
<img src="https://img.shields.io/badge/license-MIT-000?style=flat-square" alt="license" />
|
|
4
5
|
<img src="https://img.shields.io/badge/runtime-CSS%20only-000?style=flat-square" alt="CSS only runtime" />
|
|
5
6
|
<img src="https://img.shields.io/badge/bundle-~14KB-000?style=flat-square" alt="bundle size" />
|
|
@@ -13,6 +14,10 @@
|
|
|
13
14
|
No manual measurement. No hand-tuned placeholders. Zero-config, SSR-first, CSS-only runtime.
|
|
14
15
|
</p>
|
|
15
16
|
|
|
17
|
+
<p align="center">
|
|
18
|
+
<code>npm install @lukas_holdings/castdom</code>
|
|
19
|
+
</p>
|
|
20
|
+
|
|
16
21
|
<p align="center">
|
|
17
22
|
<a href="#quick-start">Quick Start</a> •
|
|
18
23
|
<a href="#how-it-works">How It Works</a> •
|
|
@@ -65,7 +70,7 @@ Your Component CastDOM Skeleton
|
|
|
65
70
|
### 1. Install
|
|
66
71
|
|
|
67
72
|
```bash
|
|
68
|
-
npm install castdom
|
|
73
|
+
npm install @lukas_holdings/castdom
|
|
69
74
|
```
|
|
70
75
|
|
|
71
76
|
### 2. Mark your components
|
|
@@ -138,7 +143,7 @@ CastDOM Build
|
|
|
138
143
|
import ".castdom/loader.js";
|
|
139
144
|
|
|
140
145
|
// Use anywhere
|
|
141
|
-
import { CastDOM } from "castdom/react";
|
|
146
|
+
import { CastDOM } from "@lukas_holdings/castdom/react";
|
|
142
147
|
|
|
143
148
|
function UserProfile({ userId }) {
|
|
144
149
|
const { data, isLoading } = useFetch(`/api/users/${userId}`);
|
|
@@ -237,7 +242,7 @@ The compression pipeline:
|
|
|
237
242
|
### `<CastDOM>` Component
|
|
238
243
|
|
|
239
244
|
```tsx
|
|
240
|
-
import { CastDOM } from "castdom/react";
|
|
245
|
+
import { CastDOM } from "@lukas_holdings/castdom/react";
|
|
241
246
|
|
|
242
247
|
<CastDOM
|
|
243
248
|
name="user-card" // Registered skeleton name
|
|
@@ -260,7 +265,7 @@ import { CastDOM } from "castdom/react";
|
|
|
260
265
|
Add to your `<head>` for critical CSS:
|
|
261
266
|
|
|
262
267
|
```tsx
|
|
263
|
-
import { CastDOMStyle } from "castdom/react";
|
|
268
|
+
import { CastDOMStyle } from "@lukas_holdings/castdom/react";
|
|
264
269
|
|
|
265
270
|
function Layout({ children }) {
|
|
266
271
|
return (
|
|
@@ -277,7 +282,7 @@ function Layout({ children }) {
|
|
|
277
282
|
### `useCastDOM` Hook
|
|
278
283
|
|
|
279
284
|
```tsx
|
|
280
|
-
import { useCastDOM } from "castdom/react";
|
|
285
|
+
import { useCastDOM } from "@lukas_holdings/castdom/react";
|
|
281
286
|
|
|
282
287
|
function CustomSkeleton() {
|
|
283
288
|
const { exists, data, breakpoint, css, html } = useCastDOM("user-card");
|
|
@@ -296,7 +301,7 @@ function CustomSkeleton() {
|
|
|
296
301
|
|
|
297
302
|
```tsx
|
|
298
303
|
// app/layout.tsx
|
|
299
|
-
import { initCastDOM } from "castdom/next";
|
|
304
|
+
import { initCastDOM } from "@lukas_holdings/castdom/next";
|
|
300
305
|
import manifest from "../.castdom/manifest.json";
|
|
301
306
|
|
|
302
307
|
initCastDOM(manifest);
|
|
@@ -312,7 +317,7 @@ export default function RootLayout({ children }) {
|
|
|
312
317
|
|
|
313
318
|
```tsx
|
|
314
319
|
// app/dashboard/page.tsx
|
|
315
|
-
import { CastDOM } from "castdom/next";
|
|
320
|
+
import { CastDOM } from "@lukas_holdings/castdom/next";
|
|
316
321
|
|
|
317
322
|
export default async function Dashboard() {
|
|
318
323
|
const data = await fetchDashboard();
|
|
@@ -329,7 +334,7 @@ export default async function Dashboard() {
|
|
|
329
334
|
|
|
330
335
|
```tsx
|
|
331
336
|
// pages/_app.tsx
|
|
332
|
-
import { initCastDOM } from "castdom/next";
|
|
337
|
+
import { initCastDOM } from "@lukas_holdings/castdom/next";
|
|
333
338
|
import manifest from "../.castdom/manifest.json";
|
|
334
339
|
|
|
335
340
|
initCastDOM(manifest);
|
|
@@ -342,7 +347,7 @@ export default function App({ Component, pageProps }) {
|
|
|
342
347
|
### Server-Side Props
|
|
343
348
|
|
|
344
349
|
```tsx
|
|
345
|
-
import { getSkeletonProps } from "castdom/next";
|
|
350
|
+
import { getSkeletonProps } from "@lukas_holdings/castdom/next";
|
|
346
351
|
|
|
347
352
|
export async function getServerSideProps() {
|
|
348
353
|
const { skeletonHTML, skeletonCSS } = getSkeletonProps(["user-card"]);
|
|
@@ -367,7 +372,7 @@ cp .castdom/nextjs-loading.tsx app/dashboard/loading.tsx
|
|
|
367
372
|
```js
|
|
368
373
|
// astro.config.mjs
|
|
369
374
|
import { defineConfig } from "astro/config";
|
|
370
|
-
import { castdomIntegration } from "castdom/astro";
|
|
375
|
+
import { castdomIntegration } from "@lukas_holdings/castdom/astro";
|
|
371
376
|
|
|
372
377
|
export default defineConfig({
|
|
373
378
|
integrations: [castdomIntegration()],
|
|
@@ -378,7 +383,7 @@ export default defineConfig({
|
|
|
378
383
|
|
|
379
384
|
```astro
|
|
380
385
|
---
|
|
381
|
-
import { skeleton } from "castdom/astro";
|
|
386
|
+
import { skeleton } from "@lukas_holdings/castdom/astro";
|
|
382
387
|
const { html, css } = skeleton("user-card");
|
|
383
388
|
---
|
|
384
389
|
|
|
@@ -393,7 +398,7 @@ const { html, css } = skeleton("user-card");
|
|
|
393
398
|
|
|
394
399
|
```astro
|
|
395
400
|
---
|
|
396
|
-
import { skeleton, viewTransitionProps } from "castdom/astro";
|
|
401
|
+
import { skeleton, viewTransitionProps } from "@lukas_holdings/castdom/astro";
|
|
397
402
|
const { html } = skeleton("sidebar");
|
|
398
403
|
const transitionProps = viewTransitionProps("sidebar");
|
|
399
404
|
---
|
|
@@ -410,7 +415,7 @@ const transitionProps = viewTransitionProps("sidebar");
|
|
|
410
415
|
```ts
|
|
411
416
|
// vite.config.ts
|
|
412
417
|
import { defineConfig } from "vite";
|
|
413
|
-
import { castdom } from "castdom/vite";
|
|
418
|
+
import { castdom } from "@lukas_holdings/castdom/vite";
|
|
414
419
|
|
|
415
420
|
export default defineConfig({
|
|
416
421
|
plugins: [castdom()],
|
|
@@ -435,7 +440,7 @@ The plugin provides:
|
|
|
435
440
|
For non-framework usage:
|
|
436
441
|
|
|
437
442
|
```js
|
|
438
|
-
import { createCastDOM } from "castdom";
|
|
443
|
+
import { createCastDOM } from "@lukas_holdings/castdom";
|
|
439
444
|
import manifest from ".castdom/manifest.json";
|
|
440
445
|
|
|
441
446
|
const castdom = createCastDOM();
|
|
@@ -468,7 +473,7 @@ CastDOM is SSR-first. Skeletons render as server-side HTML with zero JavaScript.
|
|
|
468
473
|
### Server-Side Rendering
|
|
469
474
|
|
|
470
475
|
```ts
|
|
471
|
-
import { renderSkeleton, renderSSRFragment } from "castdom/ssr";
|
|
476
|
+
import { renderSkeleton, renderSSRFragment } from "@lukas_holdings/castdom/ssr";
|
|
472
477
|
|
|
473
478
|
// Single skeleton
|
|
474
479
|
const html = renderSkeleton(skeletonData);
|
|
@@ -485,7 +490,7 @@ const { head, body } = renderSSRFragment([skeleton1, skeleton2]);
|
|
|
485
490
|
SSR skeletons include `data-castdom-ssr` attributes. A tiny (~200 byte) inline hydration script automatically removes them once real content renders:
|
|
486
491
|
|
|
487
492
|
```ts
|
|
488
|
-
import { renderHydrationScript } from "castdom/ssr";
|
|
493
|
+
import { renderHydrationScript } from "@lukas_holdings/castdom/ssr";
|
|
489
494
|
|
|
490
495
|
const script = renderHydrationScript();
|
|
491
496
|
// <script data-castdom="hydration">(...)</script>
|
|
@@ -494,7 +499,7 @@ const script = renderHydrationScript();
|
|
|
494
499
|
### Critical CSS
|
|
495
500
|
|
|
496
501
|
```ts
|
|
497
|
-
import { renderCriticalStyleTag } from "castdom/ssr";
|
|
502
|
+
import { renderCriticalStyleTag } from "@lukas_holdings/castdom/ssr";
|
|
498
503
|
|
|
499
504
|
const styleTag = renderCriticalStyleTag([skeleton1, skeleton2]);
|
|
500
505
|
// <style data-castdom="critical">@keyframes castdom-shimmer{...}...</style>
|
|
@@ -630,7 +635,7 @@ import {
|
|
|
630
635
|
extractBones, // Extract bones from a DOM element (browser-side)
|
|
631
636
|
compressBones, // Compress bone data for storage
|
|
632
637
|
decompressBones, // Decompress bone data
|
|
633
|
-
} from "castdom";
|
|
638
|
+
} from "@lukas_holdings/castdom";
|
|
634
639
|
```
|
|
635
640
|
|
|
636
641
|
### React
|
|
@@ -640,7 +645,7 @@ import {
|
|
|
640
645
|
CastDOM, // Wrapper component
|
|
641
646
|
CastDOMStyle, // Critical CSS component for <head>
|
|
642
647
|
useCastDOM, // Hook for programmatic access
|
|
643
|
-
} from "castdom/react";
|
|
648
|
+
} from "@lukas_holdings/castdom/react";
|
|
644
649
|
```
|
|
645
650
|
|
|
646
651
|
### SSR
|
|
@@ -652,7 +657,7 @@ import {
|
|
|
652
657
|
renderCriticalStyleTag, // Generate <style> tag
|
|
653
658
|
renderHydrationScript, // Generate hydration <script>
|
|
654
659
|
renderSSRFragment, // Complete head + body fragments
|
|
655
|
-
} from "castdom/ssr";
|
|
660
|
+
} from "@lukas_holdings/castdom/ssr";
|
|
656
661
|
```
|
|
657
662
|
|
|
658
663
|
---
|
|
@@ -689,6 +694,30 @@ export type SkeletonName = "user-card" | "feed-item";
|
|
|
689
694
|
|
|
690
695
|
---
|
|
691
696
|
|
|
697
|
+
## Interactive Demo
|
|
698
|
+
|
|
699
|
+
Open `demo/index.html` to see a live side-by-side comparison:
|
|
700
|
+
|
|
701
|
+
- **Left panel**: Traditional spinner — blank until data loads, layout shifts on content render
|
|
702
|
+
- **Right panel**: CastDOM skeleton — pixel-perfect placeholder visible instantly, zero CLS
|
|
703
|
+
|
|
704
|
+
The demo simulates network latency (1s, 2s, 3s) and shows real-time Core Web Vitals metrics (CLS, FCP, LCP) for both approaches. [View the demo →](demo/index.html)
|
|
705
|
+
|
|
706
|
+
---
|
|
707
|
+
|
|
708
|
+
## AI Integration
|
|
709
|
+
|
|
710
|
+
CastDOM ships AI-friendly reference files for use with LLMs, AI coding assistants, and generative engine optimization:
|
|
711
|
+
|
|
712
|
+
| File | Purpose |
|
|
713
|
+
|------|---------|
|
|
714
|
+
| [`llms.txt`](llms.txt) | Short summary — install, concepts, exports, links |
|
|
715
|
+
| [`llms-full.txt`](llms-full.txt) | Complete reference — all types, APIs, patterns, config, file structure |
|
|
716
|
+
|
|
717
|
+
These follow the [llms.txt](https://llmstxt.org/) convention. Any AI assistant can read them to understand how to install, configure, and integrate CastDOM into a project.
|
|
718
|
+
|
|
719
|
+
---
|
|
720
|
+
|
|
692
721
|
## Browser Support
|
|
693
722
|
|
|
694
723
|
CastDOM's runtime is pure CSS — it works everywhere CSS animations work:
|
package/package.json
CHANGED
|
@@ -1,7 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lukas_holdings/castdom",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"description": "Pixel-perfect skeleton loading screens, extracted from your real DOM. Zero-config, SSR-first, CSS-only runtime.",
|
|
5
|
+
"homepage": "https://kameeleonn.github.io/CastDOM/",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "https://github.com/Kameeleonn/CastDOM.git"
|
|
9
|
+
},
|
|
10
|
+
"bugs": {
|
|
11
|
+
"url": "https://github.com/Kameeleonn/CastDOM/issues"
|
|
12
|
+
},
|
|
13
|
+
"author": "Lukas Holdings",
|
|
5
14
|
"type": "module",
|
|
6
15
|
"main": "./dist/index.cjs",
|
|
7
16
|
"module": "./dist/index.js",
|