@0xgf/boneyard 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/README.md +32 -0
- package/bin/boneyard.mjs +272 -0
- package/dist/extract.d.ts +15 -0
- package/dist/extract.js +380 -0
- package/dist/index.d.ts +54 -0
- package/dist/index.js +57 -0
- package/dist/layout.d.ts +15 -0
- package/dist/layout.js +256 -0
- package/dist/react.d.ts +107 -0
- package/dist/react.js +146 -0
- package/dist/responsive.d.ts +34 -0
- package/dist/responsive.js +67 -0
- package/dist/runtime.d.ts +17 -0
- package/dist/runtime.js +38 -0
- package/dist/types.d.ts +170 -0
- package/dist/types.js +1 -0
- package/package.json +67 -0
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Controls how `snapshotBones` extracts bones from the DOM.
|
|
3
|
+
* Pass as `snapshotConfig` on `<Skeleton>` or as the third arg to `snapshotBones()`.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* <Skeleton loading={isLoading} snapshotConfig={{ leafTags: ['p', 'h1', 'h2', 'li'] }}>
|
|
7
|
+
* <MyComponent />
|
|
8
|
+
* </Skeleton>
|
|
9
|
+
*/
|
|
10
|
+
export interface SnapshotConfig {
|
|
11
|
+
/**
|
|
12
|
+
* HTML tags always captured as a single atomic bone, regardless of children.
|
|
13
|
+
* Use this for block-level text elements in your design system.
|
|
14
|
+
* Default: ['p','h1','h2','h3','h4','h5','h6','li','tr']
|
|
15
|
+
*/
|
|
16
|
+
leafTags?: string[];
|
|
17
|
+
/**
|
|
18
|
+
* When true, containers with a visible border AND border-radius are captured
|
|
19
|
+
* as container bones — even with a white or transparent background.
|
|
20
|
+
* This catches white cards (`bg-white rounded-xl border`) that would otherwise
|
|
21
|
+
* produce no container bone.
|
|
22
|
+
* Default: true
|
|
23
|
+
*/
|
|
24
|
+
captureRoundedBorders?: boolean;
|
|
25
|
+
/**
|
|
26
|
+
* HTML tags to skip entirely — no bone emitted, children not walked.
|
|
27
|
+
* Useful for decorative elements, icons, or custom components you don't
|
|
28
|
+
* want represented in the skeleton.
|
|
29
|
+
*
|
|
30
|
+
* @example ['nav', 'footer', 'aside']
|
|
31
|
+
*/
|
|
32
|
+
excludeTags?: string[];
|
|
33
|
+
/**
|
|
34
|
+
* CSS selectors to skip entirely. Any element matching a selector is
|
|
35
|
+
* excluded along with all its descendants. Supports any valid CSS selector —
|
|
36
|
+
* classes, IDs, attributes, tags, or combinations.
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* excludeSelectors: [
|
|
40
|
+
* '.icon', // skip by class
|
|
41
|
+
* '[data-no-skeleton]', // skip by data attribute
|
|
42
|
+
* '#sidebar', // skip by ID
|
|
43
|
+
* 'nav', // skip by tag
|
|
44
|
+
* '.card .badge', // skip by nested selector
|
|
45
|
+
* ]
|
|
46
|
+
*/
|
|
47
|
+
excludeSelectors?: string[];
|
|
48
|
+
}
|
|
49
|
+
/** A single skeleton bone — a rounded rect placeholder */
|
|
50
|
+
export interface Bone {
|
|
51
|
+
x: number;
|
|
52
|
+
y: number;
|
|
53
|
+
w: number;
|
|
54
|
+
h: number;
|
|
55
|
+
r: number | string;
|
|
56
|
+
/** True if this bone is a background container — rendered lighter so children stand out */
|
|
57
|
+
c?: boolean;
|
|
58
|
+
}
|
|
59
|
+
/** Skeleton layout result for a component at a specific width */
|
|
60
|
+
export interface SkeletonResult {
|
|
61
|
+
name: string;
|
|
62
|
+
viewportWidth: number;
|
|
63
|
+
width: number;
|
|
64
|
+
height: number;
|
|
65
|
+
bones: Bone[];
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Describes a component's visual structure for skeleton generation.
|
|
69
|
+
* Auto-extracted from the DOM via `fromElement()`, or hand-authored for
|
|
70
|
+
* SSR/build-time paths where no DOM is available.
|
|
71
|
+
* `computeLayout` uses pretext to measure text and compute bone positions
|
|
72
|
+
* at any container width — no DOM needed at render time.
|
|
73
|
+
*
|
|
74
|
+
* For the simpler browser path, use `snapshotBones()` or `<Skeleton>` instead.
|
|
75
|
+
*
|
|
76
|
+
* @example
|
|
77
|
+
* const card: SkeletonDescriptor = {
|
|
78
|
+
* display: 'flex', flexDirection: 'column', padding: 16, gap: 12,
|
|
79
|
+
* children: [
|
|
80
|
+
* { aspectRatio: 16/9 },
|
|
81
|
+
* { text: 'Title text here', font: '700 18px Inter', lineHeight: 24 },
|
|
82
|
+
* { text: 'Body text content', font: '14px Inter', lineHeight: 20 },
|
|
83
|
+
* { height: 44, borderRadius: 8 },
|
|
84
|
+
* ]
|
|
85
|
+
* }
|
|
86
|
+
*/
|
|
87
|
+
export interface SkeletonDescriptor {
|
|
88
|
+
/** Display mode (default: 'block') */
|
|
89
|
+
display?: 'block' | 'flex';
|
|
90
|
+
/** Flex direction (default: 'row') */
|
|
91
|
+
flexDirection?: 'row' | 'column';
|
|
92
|
+
/** Align items — cross-axis alignment */
|
|
93
|
+
alignItems?: string;
|
|
94
|
+
/** Justify content — main-axis alignment */
|
|
95
|
+
justifyContent?: string;
|
|
96
|
+
/** Explicit width in px */
|
|
97
|
+
width?: number;
|
|
98
|
+
/** Explicit height in px */
|
|
99
|
+
height?: number;
|
|
100
|
+
/** CSS aspect-ratio (e.g. 16/9) */
|
|
101
|
+
aspectRatio?: number;
|
|
102
|
+
/** Padding — single number or per-side (missing sides default to 0) */
|
|
103
|
+
padding?: number | {
|
|
104
|
+
top?: number;
|
|
105
|
+
right?: number;
|
|
106
|
+
bottom?: number;
|
|
107
|
+
left?: number;
|
|
108
|
+
};
|
|
109
|
+
/** Margin — single number or per-side (missing sides default to 0) */
|
|
110
|
+
margin?: number | {
|
|
111
|
+
top?: number;
|
|
112
|
+
right?: number;
|
|
113
|
+
bottom?: number;
|
|
114
|
+
left?: number;
|
|
115
|
+
};
|
|
116
|
+
/** Gap between flex children */
|
|
117
|
+
gap?: number;
|
|
118
|
+
/** Row gap (overrides gap for vertical) */
|
|
119
|
+
rowGap?: number;
|
|
120
|
+
/** Column gap (overrides gap for horizontal) */
|
|
121
|
+
columnGap?: number;
|
|
122
|
+
/** Border radius (default: 8, use '50%' for circles) */
|
|
123
|
+
borderRadius?: number | string;
|
|
124
|
+
/** CSS font string for pretext measurement (e.g. '700 18px Inter') */
|
|
125
|
+
font?: string;
|
|
126
|
+
/** Line height in px */
|
|
127
|
+
lineHeight?: number;
|
|
128
|
+
/** Text content — pretext measures this to compute height */
|
|
129
|
+
text?: string;
|
|
130
|
+
/** Max width constraint (px) */
|
|
131
|
+
maxWidth?: number;
|
|
132
|
+
/** Whether this is a leaf bone (auto-detected if not set) */
|
|
133
|
+
leaf?: boolean;
|
|
134
|
+
/** Child descriptors */
|
|
135
|
+
children?: SkeletonDescriptor[];
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* A responsive skeleton descriptor — maps min-width breakpoints to
|
|
139
|
+
* structural variants. The layout engine picks the best match for
|
|
140
|
+
* the current container width.
|
|
141
|
+
*
|
|
142
|
+
* @example
|
|
143
|
+
* const card: ResponsiveDescriptor = {
|
|
144
|
+
* // Mobile: single column
|
|
145
|
+
* 0: { display: 'flex', flexDirection: 'column', ... },
|
|
146
|
+
* // Tablet+: row with sidebar
|
|
147
|
+
* 768: { display: 'flex', flexDirection: 'row', ... },
|
|
148
|
+
* }
|
|
149
|
+
*/
|
|
150
|
+
export type ResponsiveDescriptor = Record<number, SkeletonDescriptor>;
|
|
151
|
+
/**
|
|
152
|
+
* Responsive bones — a set of SkeletonResults captured at different viewport widths.
|
|
153
|
+
* Generated by `boneyard build`, passed as `initialBones` to `<Skeleton>`.
|
|
154
|
+
*
|
|
155
|
+
* `<Skeleton>` picks the nearest matching breakpoint for the current container width.
|
|
156
|
+
* Keys are the min-widths at which each snapshot was taken (e.g. 375, 768, 1280).
|
|
157
|
+
*
|
|
158
|
+
* @example
|
|
159
|
+
* // Generated by: npx boneyard capture http://localhost:3000 --out ./src/bones
|
|
160
|
+
* // Then import:
|
|
161
|
+
* import blogBones from './src/bones/blog-card.bones.json'
|
|
162
|
+
* // { "breakpoints": { "375": {...}, "768": {...}, "1280": {...} } }
|
|
163
|
+
*
|
|
164
|
+
* <Skeleton loading={isLoading} initialBones={blogBones}>
|
|
165
|
+
* <BlogCard />
|
|
166
|
+
* </Skeleton>
|
|
167
|
+
*/
|
|
168
|
+
export interface ResponsiveBones {
|
|
169
|
+
breakpoints: Record<number, SkeletonResult>;
|
|
170
|
+
}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@0xgf/boneyard",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Pixel-perfect skeleton loading screens. Wrap your component in <Skeleton> and boneyard snapshots the real DOM layout — no manual descriptors, no configuration.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js"
|
|
12
|
+
},
|
|
13
|
+
"./layout": {
|
|
14
|
+
"types": "./dist/layout.d.ts",
|
|
15
|
+
"import": "./dist/layout.js"
|
|
16
|
+
},
|
|
17
|
+
"./react": {
|
|
18
|
+
"types": "./dist/react.d.ts",
|
|
19
|
+
"import": "./dist/react.js"
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"bin": {
|
|
23
|
+
"boneyard": "./bin/boneyard.mjs"
|
|
24
|
+
},
|
|
25
|
+
"files": [
|
|
26
|
+
"dist",
|
|
27
|
+
"bin"
|
|
28
|
+
],
|
|
29
|
+
"scripts": {
|
|
30
|
+
"build": "tsc",
|
|
31
|
+
"test": "bun test",
|
|
32
|
+
"prepublishOnly": "tsc"
|
|
33
|
+
},
|
|
34
|
+
"keywords": [
|
|
35
|
+
"skeleton",
|
|
36
|
+
"skeleton-screen",
|
|
37
|
+
"loading",
|
|
38
|
+
"placeholder",
|
|
39
|
+
"react",
|
|
40
|
+
"zero-layout-shift"
|
|
41
|
+
],
|
|
42
|
+
"license": "MIT",
|
|
43
|
+
"repository": {
|
|
44
|
+
"type": "git",
|
|
45
|
+
"url": "https://github.com/0xGF/boneyard"
|
|
46
|
+
},
|
|
47
|
+
"homepage": "https://github.com/0xGF/boneyard",
|
|
48
|
+
"optionalDependencies": {
|
|
49
|
+
"@chenglou/pretext": "^0.0.3"
|
|
50
|
+
},
|
|
51
|
+
"peerDependencies": {
|
|
52
|
+
"react": ">=18"
|
|
53
|
+
},
|
|
54
|
+
"peerDependenciesMeta": {
|
|
55
|
+
"react": {
|
|
56
|
+
"optional": true
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
"devDependencies": {
|
|
60
|
+
"@types/node": "^22.19.15",
|
|
61
|
+
"@types/react": "^19.0.0",
|
|
62
|
+
"canvas": "^3.2.2",
|
|
63
|
+
"playwright": "^1.58.2",
|
|
64
|
+
"react": "^19.0.0",
|
|
65
|
+
"typescript": "^5.7.0"
|
|
66
|
+
}
|
|
67
|
+
}
|