@alikhalilll/a-skeleton 1.0.0 → 1.2.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/.media/hero.png +0 -0
- package/.media/hero.svg +232 -0
- package/README.md +459 -170
- package/dist/index.cjs +3696 -828
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +534 -43
- package/dist/index.d.ts +534 -43
- package/dist/index.js +3677 -830
- package/dist/index.js.map +1 -1
- package/dist/nuxt/index.cjs +16 -1
- package/dist/nuxt/index.cjs.map +1 -1
- package/dist/nuxt/index.js +16 -1
- package/dist/nuxt/index.js.map +1 -1
- package/dist/resolver/index.cjs +16 -1
- package/dist/resolver/index.cjs.map +1 -1
- package/dist/resolver/index.js +16 -1
- package/dist/resolver/index.js.map +1 -1
- package/dist/styles.css +56 -11
- package/package.json +8 -2
- package/src/components/ASkeleton.vue +216 -98
- package/src/components/ASkeletonClone.vue +106 -0
- package/src/components/ASkeletonLayer.vue +20 -32
- package/src/components/CloneNode.ts +161 -0
- package/src/components/StructuralLayerNode.ts +157 -0
- package/src/components/icons.ts +45 -0
- package/src/components/variants/ASkeletonArticle.vue +33 -0
- package/src/components/variants/ASkeletonAvatar.vue +42 -0
- package/src/components/variants/ASkeletonButton.vue +37 -0
- package/src/components/variants/ASkeletonCard.vue +47 -0
- package/src/components/variants/ASkeletonChart.vue +56 -0
- package/src/components/variants/ASkeletonChip.vue +32 -0
- package/src/components/variants/ASkeletonDivider.vue +26 -0
- package/src/components/variants/ASkeletonForm.vue +32 -0
- package/src/components/variants/ASkeletonHeading.vue +47 -0
- package/src/components/variants/ASkeletonImage.vue +57 -0
- package/src/components/variants/ASkeletonInput.vue +33 -0
- package/src/components/variants/ASkeletonListItem.vue +40 -0
- package/src/components/variants/ASkeletonTable.vue +49 -0
- package/src/components/variants/ASkeletonText.vue +49 -0
- package/src/components/variants/ASkeletonVideo.vue +55 -0
- package/src/composables/useShapeProbe.ts +33 -9
- package/src/composables/useSkeleton.ts +33 -21
- package/src/composables/useSkeletonCache.ts +282 -24
- package/src/index.ts +48 -2
- package/src/nuxt/index.ts +16 -0
- package/src/resolver/index.ts +16 -0
- package/src/types.ts +124 -5
- package/src/utils/buildStructuralSkeleton.ts +400 -103
- package/src/utils/captureStyles.ts +378 -0
- package/src/utils/domRead.ts +143 -0
- package/src/utils/walkDom.ts +261 -16
- package/src/utils/walkStructural.ts +418 -0
- package/web-types.json +10 -4
package/dist/index.d.ts
CHANGED
|
@@ -2,6 +2,13 @@ import { CSSProperties, HTMLAttributes, PropType, Ref, VNode, VNodeArrayChildren
|
|
|
2
2
|
|
|
3
3
|
//#region src/types.d.ts
|
|
4
4
|
type ShapeNodeType = 'block' | 'text' | 'image' | 'circle';
|
|
5
|
+
/** A single per-line text rect captured via the `Range` API — root-relative. */
|
|
6
|
+
interface TextLineRect$1 {
|
|
7
|
+
x: number;
|
|
8
|
+
y: number;
|
|
9
|
+
w: number;
|
|
10
|
+
h: number;
|
|
11
|
+
}
|
|
5
12
|
/** A single shimmer block in a captured skeleton — positioned absolutely inside the layer. */
|
|
6
13
|
interface ShapeNode {
|
|
7
14
|
type: ShapeNodeType;
|
|
@@ -14,6 +21,23 @@ interface ShapeNode {
|
|
|
14
21
|
lines?: number;
|
|
15
22
|
/** Line-height used when expanding `lines` into stacked bars. */
|
|
16
23
|
lineHeight?: number;
|
|
24
|
+
/**
|
|
25
|
+
* Per-line text rects captured via `Range.getClientRects()` — when present, each
|
|
26
|
+
* rendered text line gets its own bar at the exact position and width of the
|
|
27
|
+
* actual rendered text, so wrapped/centered/RTL/short-last-line all replay correctly
|
|
28
|
+
* without heuristics. Supersedes `lines` + `lineHeight` for text nodes.
|
|
29
|
+
*/
|
|
30
|
+
textRects?: ReadonlyArray<TextLineRect$1>;
|
|
31
|
+
/** Background colour captured via `getComputedStyle()` — applied inline so e.g. a white button stays white. */
|
|
32
|
+
bg?: string;
|
|
33
|
+
/** Shorthand border (`"<width>px solid <color>"`) — captured when the element has a visible border. */
|
|
34
|
+
border?: string;
|
|
35
|
+
/** Box-shadow captured verbatim when non-trivial — preserves elevation on cards. */
|
|
36
|
+
boxShadow?: string;
|
|
37
|
+
/** Element opacity when < 1 — captured so semi-transparent surfaces replay correctly. */
|
|
38
|
+
opacity?: number;
|
|
39
|
+
/** Resolved `text-align` (only meaningful for `type='text'`). */
|
|
40
|
+
textAlign?: 'left' | 'right' | 'center' | 'justify' | 'start' | 'end';
|
|
17
41
|
/**
|
|
18
42
|
* Pre-computed (and frozen) inline style for the block. Built once during
|
|
19
43
|
* capture so the render path never allocates a style object per node per
|
|
@@ -33,15 +57,81 @@ interface CachedShape {
|
|
|
33
57
|
/** Was the walk cut short by `maxNodes`? Surface so consumers can tune the budget. */
|
|
34
58
|
truncated?: boolean;
|
|
35
59
|
}
|
|
60
|
+
/** Per-line text rect on a text leaf — coordinates are leaf-relative. */
|
|
61
|
+
interface StructuralTextLineRect {
|
|
62
|
+
x: number;
|
|
63
|
+
y: number;
|
|
64
|
+
w: number;
|
|
65
|
+
h: number;
|
|
66
|
+
}
|
|
67
|
+
type StructuralNode = ContainerNode | LeafNode;
|
|
68
|
+
interface ContainerNode {
|
|
69
|
+
kind: 'container';
|
|
70
|
+
/** Lowercased tag — preserved so semantic CSS / a11y still applies. */
|
|
71
|
+
tag: string;
|
|
72
|
+
/** Original `class` attribute, verbatim. Empty string when the element has no class. */
|
|
73
|
+
className: string;
|
|
74
|
+
/** Captured layout + visual CSS (frozen). Layout props belong on containers; visual signals optional. */
|
|
75
|
+
style: Readonly<CSSProperties>;
|
|
76
|
+
children: ReadonlyArray<StructuralNode>;
|
|
77
|
+
}
|
|
78
|
+
type LeafKind = 'block' | 'text' | 'image' | 'media';
|
|
79
|
+
interface LeafNode {
|
|
80
|
+
kind: 'leaf';
|
|
81
|
+
leafKind: LeafKind;
|
|
82
|
+
/** Original `class` attribute of the real element, verbatim. Empty string when absent. */
|
|
83
|
+
className: string;
|
|
84
|
+
/**
|
|
85
|
+
* Captured inline style: width, height, plus the same comprehensive
|
|
86
|
+
* layout + visual capture used on containers (display, margin, padding,
|
|
87
|
+
* border, background, transform, …). Frozen.
|
|
88
|
+
*/
|
|
89
|
+
style: Readonly<CSSProperties>;
|
|
90
|
+
/**
|
|
91
|
+
* Per-line rects for text leaves (`leafKind === 'text'`), captured via
|
|
92
|
+
* `Range.getClientRects()`. Coordinates are relative to the leaf's own box,
|
|
93
|
+
* so the renderer can lay them out with `position: absolute` inside a
|
|
94
|
+
* normal-flow text host.
|
|
95
|
+
*/
|
|
96
|
+
textLines?: ReadonlyArray<StructuralTextLineRect>;
|
|
97
|
+
}
|
|
98
|
+
interface StructuralShape {
|
|
99
|
+
/** Captured root rect — used by consumers for sanity checks; not for replay sizing. */
|
|
100
|
+
width: number;
|
|
101
|
+
height: number;
|
|
102
|
+
nodes: ReadonlyArray<StructuralNode>;
|
|
103
|
+
/** Was the walk cut short by `maxNodes`? */
|
|
104
|
+
truncated: boolean;
|
|
105
|
+
/** ms since epoch — useful for cache invalidation policies. */
|
|
106
|
+
capturedAt: number;
|
|
107
|
+
/** Persisted-shape schema version. Currently 3. */
|
|
108
|
+
v: 3;
|
|
109
|
+
}
|
|
36
110
|
type SkeletonAnimation = 'shimmer' | 'pulse' | 'none';
|
|
37
111
|
type SkeletonFallback = 'shimmer' | 'block';
|
|
112
|
+
type ASkeletonMode = 'mirror' | 'clone';
|
|
38
113
|
interface ASkeletonProps {
|
|
39
114
|
/** When true, render the captured skeleton (or `fallback` slot) instead of the default slot. */
|
|
40
115
|
loading: boolean;
|
|
41
116
|
/**
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
117
|
+
* Rendering strategy. Default `'mirror'`.
|
|
118
|
+
* - `'mirror'`: walks the slot's vnode tree and preserves every element
|
|
119
|
+
* with its real class / inline style. Pure-Vue, SSR-safe, no DOM read.
|
|
120
|
+
* - `'clone'`: mounts the slot off-screen once, takes a comprehensive
|
|
121
|
+
* `getComputedStyle()` snapshot of every leaf, then replays the
|
|
122
|
+
* snapshot as positioned divs carrying every captured CSS property.
|
|
123
|
+
* Pixel-identical to the real render, regardless of styling system
|
|
124
|
+
* (Tailwind, CSS-in-JS, DaisyUI, computed inline styles). Requires
|
|
125
|
+
* a DOM (client-side only).
|
|
126
|
+
*/
|
|
127
|
+
mode?: ASkeletonMode;
|
|
128
|
+
/**
|
|
129
|
+
* Identifier used to look up + persist the captured shape. Defaults to
|
|
130
|
+
* `"<slot-fingerprint>:<useId()>"` so every `<ASkeleton>` instance gets its
|
|
131
|
+
* own cache slot automatically — two `<ASkeleton><UserCard/></ASkeleton>` on
|
|
132
|
+
* the same page never collide. Pass explicitly when you *want* multiple
|
|
133
|
+
* instances to share a captured shape (e.g. a list of identical cards), or
|
|
134
|
+
* when one instance renders different shapes depending on a prop.
|
|
45
135
|
*/
|
|
46
136
|
cacheKey?: string;
|
|
47
137
|
/** Max recursion depth during shape capture. Default 6. */
|
|
@@ -74,8 +164,14 @@ interface ASkeletonSlots {
|
|
|
74
164
|
fallback?: () => unknown;
|
|
75
165
|
}
|
|
76
166
|
interface ASkeletonLayerProps {
|
|
77
|
-
/**
|
|
78
|
-
|
|
167
|
+
/**
|
|
168
|
+
* Structural shape captured by `useSkeleton()` (Recipe 3) or `walkStructural()`
|
|
169
|
+
* directly. Renders nothing when `undefined`. The layer drops into the
|
|
170
|
+
* consumer's container as a transparent shell — captured containers preserve
|
|
171
|
+
* their tag/class/layout so the skeleton flows naturally inside the
|
|
172
|
+
* surrounding layout rather than being absolutely positioned.
|
|
173
|
+
*/
|
|
174
|
+
shape?: StructuralShape;
|
|
79
175
|
/** Animation variant. Default `'shimmer'`. */
|
|
80
176
|
animation?: SkeletonAnimation;
|
|
81
177
|
/** Class on the layer wrapper. */
|
|
@@ -105,28 +201,131 @@ interface ASkeletonBlockProps {
|
|
|
105
201
|
type __VLS_Slots = ASkeletonSlots;
|
|
106
202
|
declare const __VLS_base: import("vue").DefineComponent<ASkeletonProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<ASkeletonProps> & Readonly<{}>, {
|
|
107
203
|
animation: SkeletonAnimation;
|
|
204
|
+
mode: ASkeletonMode;
|
|
108
205
|
maxDepth: number;
|
|
109
206
|
maxNodes: number;
|
|
110
207
|
minNodeSize: number;
|
|
111
208
|
persist: boolean;
|
|
112
209
|
fallback: SkeletonFallback;
|
|
113
210
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
114
|
-
declare const __VLS_export$
|
|
115
|
-
declare const _default: typeof __VLS_export$
|
|
211
|
+
declare const __VLS_export$18: typeof __VLS_base;
|
|
212
|
+
declare const _default: typeof __VLS_export$18;
|
|
116
213
|
//#endregion
|
|
117
214
|
//#region src/components/ASkeletonLayer.vue.d.ts
|
|
118
|
-
declare const __VLS_export$
|
|
215
|
+
declare const __VLS_export$17: import("vue").DefineComponent<ASkeletonLayerProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<ASkeletonLayerProps> & Readonly<{}>, {
|
|
119
216
|
animation: SkeletonAnimation;
|
|
120
217
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
121
|
-
declare const _default$
|
|
218
|
+
declare const _default$14: typeof __VLS_export$17;
|
|
122
219
|
//#endregion
|
|
123
220
|
//#region src/components/ASkeletonBlock.vue.d.ts
|
|
124
|
-
declare const __VLS_export: import("vue").DefineComponent<ASkeletonBlockProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<ASkeletonBlockProps> & Readonly<{}>, {
|
|
221
|
+
declare const __VLS_export$16: import("vue").DefineComponent<ASkeletonBlockProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<ASkeletonBlockProps> & Readonly<{}>, {
|
|
125
222
|
type: ShapeNodeType;
|
|
126
223
|
lines: number;
|
|
127
224
|
animation: SkeletonAnimation;
|
|
128
225
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
129
|
-
declare const _default$
|
|
226
|
+
declare const _default$3: typeof __VLS_export$16;
|
|
227
|
+
//#endregion
|
|
228
|
+
//#region src/utils/domRead.d.ts
|
|
229
|
+
/**
|
|
230
|
+
* Shared DOM-read helpers used by both capture strategies:
|
|
231
|
+
* - `captureStyles.ts` (clone-mode comprehensive style snapshot)
|
|
232
|
+
* - `walkStructural.ts` (Recipe 3 tree-shaped capture)
|
|
233
|
+
*
|
|
234
|
+
* One source of truth for "what counts as a default CSS value", how to read a
|
|
235
|
+
* computed-style subset into a frozen camelCased object, and how to measure
|
|
236
|
+
* per-line text rectangles. Keeping both walkers behind these helpers prevents
|
|
237
|
+
* silent drift between the two pipelines.
|
|
238
|
+
*/
|
|
239
|
+
/** A single rendered text-line rectangle, expressed in root-relative pixels. */
|
|
240
|
+
interface TextLineRect {
|
|
241
|
+
x: number;
|
|
242
|
+
y: number;
|
|
243
|
+
w: number;
|
|
244
|
+
h: number;
|
|
245
|
+
}
|
|
246
|
+
//#endregion
|
|
247
|
+
//#region src/utils/captureStyles.d.ts
|
|
248
|
+
/** A captured element — geometry + comprehensive style snapshot + children. */
|
|
249
|
+
interface CapturedNode {
|
|
250
|
+
/** Tag name lowercased — used by the replay to decide content-type treatment. */
|
|
251
|
+
tag: string;
|
|
252
|
+
/** Root-relative position + size in CSS pixels. */
|
|
253
|
+
x: number;
|
|
254
|
+
y: number;
|
|
255
|
+
w: number;
|
|
256
|
+
h: number;
|
|
257
|
+
/**
|
|
258
|
+
* Frozen, ready-to-apply `style` object. Only non-default visual
|
|
259
|
+
* properties are included — the snapshot for a default `<div>` is tiny.
|
|
260
|
+
*/
|
|
261
|
+
style: Readonly<Record<string, string>>;
|
|
262
|
+
/**
|
|
263
|
+
* Content classification — drives how `<ASkeletonClone>` renders the leaf:
|
|
264
|
+
* - `text` → shimmer text bar (optionally with per-line rects)
|
|
265
|
+
* - `image` → solid surface with image-placeholder icon
|
|
266
|
+
* - `video` → solid surface with play-icon
|
|
267
|
+
* - `media` → atomic block (svg/canvas/iframe — no icon)
|
|
268
|
+
* - `block` → opaque shimmer block (default for unrecognised leaves)
|
|
269
|
+
* - `container` → has children; rendered as a positioned wrapper
|
|
270
|
+
*/
|
|
271
|
+
kind: 'text' | 'image' | 'video' | 'media' | 'block' | 'container';
|
|
272
|
+
/**
|
|
273
|
+
* Per-line text rects (only set when `kind === 'text'`). Replaces the
|
|
274
|
+
* single-rect bar with one bar per rendered text line at the exact width
|
|
275
|
+
* of that line — handles wrapping, RTL, centered headings 1:1.
|
|
276
|
+
*/
|
|
277
|
+
textLines?: ReadonlyArray<TextLineRect>;
|
|
278
|
+
/** Children (only set when `kind === 'container'`). */
|
|
279
|
+
children?: ReadonlyArray<CapturedNode>;
|
|
280
|
+
}
|
|
281
|
+
interface CaptureSnapshot {
|
|
282
|
+
/** Overall bounding box. */
|
|
283
|
+
width: number;
|
|
284
|
+
height: number;
|
|
285
|
+
/** Top-level captured nodes (siblings of the root's direct children). */
|
|
286
|
+
nodes: ReadonlyArray<CapturedNode>;
|
|
287
|
+
/** True if `maxNodes` was hit and the walk bailed out early. */
|
|
288
|
+
truncated: boolean;
|
|
289
|
+
/** When the snapshot was taken (ms since epoch). For cache invalidation policies. */
|
|
290
|
+
capturedAt: number;
|
|
291
|
+
}
|
|
292
|
+
interface CaptureOptions {
|
|
293
|
+
/** Max recursion depth. Default 12. */
|
|
294
|
+
maxDepth?: number;
|
|
295
|
+
/** Hard cap on captured nodes. Default 800. */
|
|
296
|
+
maxNodes?: number;
|
|
297
|
+
/** Skip elements smaller than this many CSS pixels (either axis). Default 4. */
|
|
298
|
+
minSize?: number;
|
|
299
|
+
/**
|
|
300
|
+
* When true, capture child elements even inside leaves that we'd normally
|
|
301
|
+
* treat atomically. Default false (atomic = single block).
|
|
302
|
+
*/
|
|
303
|
+
walkAtomic?: boolean;
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* Snapshot the rendered DOM under `root`, returning a frozen tree of every
|
|
307
|
+
* visible element + its computed visual styles. Replaying the snapshot
|
|
308
|
+
* produces a surface visually identical to `root`.
|
|
309
|
+
*/
|
|
310
|
+
declare function captureSnapshot(root: HTMLElement, options?: CaptureOptions): CaptureSnapshot;
|
|
311
|
+
//#endregion
|
|
312
|
+
//#region src/components/ASkeletonClone.vue.d.ts
|
|
313
|
+
/**
|
|
314
|
+
* `<ASkeletonClone>` — replays a `CaptureSnapshot` produced by
|
|
315
|
+
* `captureSnapshot()` as a tree of positioned divs each carrying its
|
|
316
|
+
* captured inline style. Pure render component; the recursive per-node
|
|
317
|
+
* rendering lives in `CloneNode` to keep the strategy table isolated from
|
|
318
|
+
* the layer-level concerns (sizing, animation, a11y).
|
|
319
|
+
*/
|
|
320
|
+
interface Props$15 {
|
|
321
|
+
shape: CaptureSnapshot;
|
|
322
|
+
animation?: 'pulse' | 'shimmer' | 'wave' | 'none';
|
|
323
|
+
class?: string | string[] | Record<string, boolean>;
|
|
324
|
+
}
|
|
325
|
+
declare const __VLS_export$15: import("vue").DefineComponent<Props$15, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<Props$15> & Readonly<{}>, {
|
|
326
|
+
animation: "pulse" | "shimmer" | "wave" | "none";
|
|
327
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
328
|
+
declare const _default$8: typeof __VLS_export$15;
|
|
130
329
|
//#endregion
|
|
131
330
|
//#region src/components/StructuralSkeleton.d.ts
|
|
132
331
|
/**
|
|
@@ -178,6 +377,232 @@ declare const StructuralSkeleton: import("vue").DefineComponent<import("vue").Ex
|
|
|
178
377
|
maxNodes: number;
|
|
179
378
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
180
379
|
//#endregion
|
|
380
|
+
//#region src/components/variants/ASkeletonText.vue.d.ts
|
|
381
|
+
interface Props$14 {
|
|
382
|
+
lines?: number;
|
|
383
|
+
width?: number | string;
|
|
384
|
+
/** Animation variant. Default `'pulse'`. */
|
|
385
|
+
animation?: 'pulse' | 'shimmer' | 'wave' | 'none';
|
|
386
|
+
class?: HTMLAttributes['class'];
|
|
387
|
+
}
|
|
388
|
+
declare const __VLS_export$14: import("vue").DefineComponent<Props$14, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<Props$14> & Readonly<{}>, {
|
|
389
|
+
lines: number;
|
|
390
|
+
animation: "pulse" | "shimmer" | "wave" | "none";
|
|
391
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
392
|
+
declare const _default$17: typeof __VLS_export$14;
|
|
393
|
+
//#endregion
|
|
394
|
+
//#region src/components/variants/ASkeletonHeading.vue.d.ts
|
|
395
|
+
interface Props$13 {
|
|
396
|
+
level?: 1 | 2 | 3 | 4 | 5 | 6;
|
|
397
|
+
width?: number | string;
|
|
398
|
+
animation?: 'pulse' | 'shimmer' | 'wave' | 'none';
|
|
399
|
+
class?: HTMLAttributes['class'];
|
|
400
|
+
}
|
|
401
|
+
declare const __VLS_export$13: import("vue").DefineComponent<Props$13, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<Props$13> & Readonly<{}>, {
|
|
402
|
+
animation: "pulse" | "shimmer" | "wave" | "none";
|
|
403
|
+
level: 1 | 2 | 3 | 4 | 5 | 6;
|
|
404
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
405
|
+
declare const _default$11: typeof __VLS_export$13;
|
|
406
|
+
//#endregion
|
|
407
|
+
//#region src/components/variants/ASkeletonAvatar.vue.d.ts
|
|
408
|
+
interface Props$12 {
|
|
409
|
+
size?: number | string;
|
|
410
|
+
shape?: 'circle' | 'square' | 'rounded';
|
|
411
|
+
animation?: 'pulse' | 'shimmer' | 'wave' | 'none';
|
|
412
|
+
class?: HTMLAttributes['class'];
|
|
413
|
+
}
|
|
414
|
+
declare const __VLS_export$12: import("vue").DefineComponent<Props$12, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<Props$12> & Readonly<{}>, {
|
|
415
|
+
animation: "pulse" | "shimmer" | "wave" | "none";
|
|
416
|
+
shape: "circle" | "square" | "rounded";
|
|
417
|
+
size: number | string;
|
|
418
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
419
|
+
declare const _default$2: typeof __VLS_export$12;
|
|
420
|
+
//#endregion
|
|
421
|
+
//#region src/components/variants/ASkeletonImage.vue.d.ts
|
|
422
|
+
interface Props$11 {
|
|
423
|
+
ratio?: string;
|
|
424
|
+
width?: number | string;
|
|
425
|
+
height?: number | string;
|
|
426
|
+
showIcon?: boolean;
|
|
427
|
+
animation?: 'pulse' | 'shimmer' | 'wave' | 'none';
|
|
428
|
+
class?: HTMLAttributes['class'];
|
|
429
|
+
}
|
|
430
|
+
declare const __VLS_export$11: import("vue").DefineComponent<Props$11, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<Props$11> & Readonly<{}>, {
|
|
431
|
+
animation: "pulse" | "shimmer" | "wave" | "none";
|
|
432
|
+
ratio: string;
|
|
433
|
+
showIcon: boolean;
|
|
434
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
435
|
+
declare const _default$12: typeof __VLS_export$11;
|
|
436
|
+
//#endregion
|
|
437
|
+
//#region src/components/variants/ASkeletonVideo.vue.d.ts
|
|
438
|
+
interface Props$10 {
|
|
439
|
+
ratio?: string;
|
|
440
|
+
width?: number | string;
|
|
441
|
+
height?: number | string;
|
|
442
|
+
showIcon?: boolean;
|
|
443
|
+
animation?: 'pulse' | 'shimmer' | 'wave' | 'none';
|
|
444
|
+
class?: HTMLAttributes['class'];
|
|
445
|
+
}
|
|
446
|
+
declare const __VLS_export$10: import("vue").DefineComponent<Props$10, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<Props$10> & Readonly<{}>, {
|
|
447
|
+
animation: "pulse" | "shimmer" | "wave" | "none";
|
|
448
|
+
ratio: string;
|
|
449
|
+
showIcon: boolean;
|
|
450
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
451
|
+
declare const _default$18: typeof __VLS_export$10;
|
|
452
|
+
//#endregion
|
|
453
|
+
//#region src/components/variants/ASkeletonButton.vue.d.ts
|
|
454
|
+
interface Props$9 {
|
|
455
|
+
width?: number | string;
|
|
456
|
+
height?: number | string;
|
|
457
|
+
outlined?: boolean;
|
|
458
|
+
animation?: 'pulse' | 'shimmer' | 'wave' | 'none';
|
|
459
|
+
class?: HTMLAttributes['class'];
|
|
460
|
+
}
|
|
461
|
+
declare const __VLS_export$9: import("vue").DefineComponent<Props$9, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<Props$9> & Readonly<{}>, {
|
|
462
|
+
animation: "pulse" | "shimmer" | "wave" | "none";
|
|
463
|
+
width: number | string;
|
|
464
|
+
height: number | string;
|
|
465
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
466
|
+
declare const _default$4: typeof __VLS_export$9;
|
|
467
|
+
//#endregion
|
|
468
|
+
//#region src/components/variants/ASkeletonInput.vue.d.ts
|
|
469
|
+
interface Props$8 {
|
|
470
|
+
width?: number | string;
|
|
471
|
+
height?: number | string;
|
|
472
|
+
animation?: 'pulse' | 'shimmer' | 'wave' | 'none';
|
|
473
|
+
class?: HTMLAttributes['class'];
|
|
474
|
+
}
|
|
475
|
+
declare const __VLS_export$8: import("vue").DefineComponent<Props$8, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<Props$8> & Readonly<{}>, {
|
|
476
|
+
animation: "pulse" | "shimmer" | "wave" | "none";
|
|
477
|
+
width: number | string;
|
|
478
|
+
height: number | string;
|
|
479
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
480
|
+
declare const _default$13: typeof __VLS_export$8;
|
|
481
|
+
//#endregion
|
|
482
|
+
//#region src/components/variants/ASkeletonListItem.vue.d.ts
|
|
483
|
+
interface Props$7 {
|
|
484
|
+
avatar?: boolean;
|
|
485
|
+
lines?: 1 | 2 | 3;
|
|
486
|
+
trailing?: boolean;
|
|
487
|
+
animation?: 'pulse' | 'shimmer' | 'wave' | 'none';
|
|
488
|
+
class?: HTMLAttributes['class'];
|
|
489
|
+
}
|
|
490
|
+
declare const __VLS_export$7: import("vue").DefineComponent<Props$7, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<Props$7> & Readonly<{}>, {
|
|
491
|
+
lines: 1 | 2 | 3;
|
|
492
|
+
animation: "pulse" | "shimmer" | "wave" | "none";
|
|
493
|
+
avatar: boolean;
|
|
494
|
+
trailing: boolean;
|
|
495
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
496
|
+
declare const _default$15: typeof __VLS_export$7;
|
|
497
|
+
//#endregion
|
|
498
|
+
//#region src/components/variants/ASkeletonCard.vue.d.ts
|
|
499
|
+
interface Props$6 {
|
|
500
|
+
media?: boolean;
|
|
501
|
+
heading?: boolean;
|
|
502
|
+
lines?: number;
|
|
503
|
+
actions?: boolean;
|
|
504
|
+
footerAvatar?: boolean;
|
|
505
|
+
animation?: 'pulse' | 'shimmer' | 'wave' | 'none';
|
|
506
|
+
class?: HTMLAttributes['class'];
|
|
507
|
+
}
|
|
508
|
+
declare const __VLS_export$6: import("vue").DefineComponent<Props$6, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<Props$6> & Readonly<{}>, {
|
|
509
|
+
lines: number;
|
|
510
|
+
animation: "pulse" | "shimmer" | "wave" | "none";
|
|
511
|
+
media: boolean;
|
|
512
|
+
heading: boolean;
|
|
513
|
+
actions: boolean;
|
|
514
|
+
footerAvatar: boolean;
|
|
515
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
516
|
+
declare const _default$5: typeof __VLS_export$6;
|
|
517
|
+
//#endregion
|
|
518
|
+
//#region src/components/variants/ASkeletonTable.vue.d.ts
|
|
519
|
+
interface Props$5 {
|
|
520
|
+
rows?: number;
|
|
521
|
+
columns?: number;
|
|
522
|
+
showHeader?: boolean;
|
|
523
|
+
animation?: 'pulse' | 'shimmer' | 'wave' | 'none';
|
|
524
|
+
class?: HTMLAttributes['class'];
|
|
525
|
+
}
|
|
526
|
+
declare const __VLS_export$5: import("vue").DefineComponent<Props$5, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<Props$5> & Readonly<{}>, {
|
|
527
|
+
animation: "pulse" | "shimmer" | "wave" | "none";
|
|
528
|
+
rows: number;
|
|
529
|
+
columns: number;
|
|
530
|
+
showHeader: boolean;
|
|
531
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
532
|
+
declare const _default$16: typeof __VLS_export$5;
|
|
533
|
+
//#endregion
|
|
534
|
+
//#region src/components/variants/ASkeletonChart.vue.d.ts
|
|
535
|
+
interface Props$4 {
|
|
536
|
+
bars?: number;
|
|
537
|
+
height?: number | string;
|
|
538
|
+
showHeader?: boolean;
|
|
539
|
+
animation?: 'pulse' | 'shimmer' | 'wave' | 'none';
|
|
540
|
+
class?: HTMLAttributes['class'];
|
|
541
|
+
}
|
|
542
|
+
declare const __VLS_export$4: import("vue").DefineComponent<Props$4, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<Props$4> & Readonly<{}>, {
|
|
543
|
+
animation: "pulse" | "shimmer" | "wave" | "none";
|
|
544
|
+
height: number | string;
|
|
545
|
+
showHeader: boolean;
|
|
546
|
+
bars: number;
|
|
547
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
548
|
+
declare const _default$6: typeof __VLS_export$4;
|
|
549
|
+
//#endregion
|
|
550
|
+
//#region src/components/variants/ASkeletonForm.vue.d.ts
|
|
551
|
+
interface Props$3 {
|
|
552
|
+
fields?: number;
|
|
553
|
+
showSubmit?: boolean;
|
|
554
|
+
animation?: 'pulse' | 'shimmer' | 'wave' | 'none';
|
|
555
|
+
class?: HTMLAttributes['class'];
|
|
556
|
+
}
|
|
557
|
+
declare const __VLS_export$3: import("vue").DefineComponent<Props$3, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<Props$3> & Readonly<{}>, {
|
|
558
|
+
animation: "pulse" | "shimmer" | "wave" | "none";
|
|
559
|
+
fields: number;
|
|
560
|
+
showSubmit: boolean;
|
|
561
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
562
|
+
declare const _default$10: typeof __VLS_export$3;
|
|
563
|
+
//#endregion
|
|
564
|
+
//#region src/components/variants/ASkeletonArticle.vue.d.ts
|
|
565
|
+
interface Props$2 {
|
|
566
|
+
media?: boolean;
|
|
567
|
+
paragraphs?: number;
|
|
568
|
+
linesPerParagraph?: number;
|
|
569
|
+
animation?: 'pulse' | 'shimmer' | 'wave' | 'none';
|
|
570
|
+
class?: HTMLAttributes['class'];
|
|
571
|
+
}
|
|
572
|
+
declare const __VLS_export$2: import("vue").DefineComponent<Props$2, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<Props$2> & Readonly<{}>, {
|
|
573
|
+
animation: "pulse" | "shimmer" | "wave" | "none";
|
|
574
|
+
media: boolean;
|
|
575
|
+
paragraphs: number;
|
|
576
|
+
linesPerParagraph: number;
|
|
577
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
578
|
+
declare const _default$1: typeof __VLS_export$2;
|
|
579
|
+
//#endregion
|
|
580
|
+
//#region src/components/variants/ASkeletonDivider.vue.d.ts
|
|
581
|
+
interface Props$1 {
|
|
582
|
+
thickness?: number;
|
|
583
|
+
animation?: 'pulse' | 'shimmer' | 'wave' | 'none';
|
|
584
|
+
class?: HTMLAttributes['class'];
|
|
585
|
+
}
|
|
586
|
+
declare const __VLS_export$1: import("vue").DefineComponent<Props$1, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<Props$1> & Readonly<{}>, {
|
|
587
|
+
animation: "pulse" | "shimmer" | "wave" | "none";
|
|
588
|
+
thickness: number;
|
|
589
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
590
|
+
declare const _default$9: typeof __VLS_export$1;
|
|
591
|
+
//#endregion
|
|
592
|
+
//#region src/components/variants/ASkeletonChip.vue.d.ts
|
|
593
|
+
interface Props {
|
|
594
|
+
width?: number | string;
|
|
595
|
+
height?: number | string;
|
|
596
|
+
animation?: 'pulse' | 'shimmer' | 'wave' | 'none';
|
|
597
|
+
class?: HTMLAttributes['class'];
|
|
598
|
+
}
|
|
599
|
+
declare const __VLS_export: import("vue").DefineComponent<Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<Props> & Readonly<{}>, {
|
|
600
|
+
animation: "pulse" | "shimmer" | "wave" | "none";
|
|
601
|
+
width: number | string;
|
|
602
|
+
height: number | string;
|
|
603
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
604
|
+
declare const _default$7: typeof __VLS_export;
|
|
605
|
+
//#endregion
|
|
181
606
|
//#region src/composables/useSkeleton.d.ts
|
|
182
607
|
interface UseSkeletonOptions {
|
|
183
608
|
/**
|
|
@@ -197,31 +622,33 @@ interface UseSkeletonOptions {
|
|
|
197
622
|
target?: () => HTMLElement | null;
|
|
198
623
|
/** Persist to `localStorage` so first-paint after reload skips the cold start. Default false. */
|
|
199
624
|
persist?: boolean;
|
|
200
|
-
/** Forwarded to `
|
|
625
|
+
/** Forwarded to `walkStructural`. Default 12. */
|
|
201
626
|
maxDepth?: number;
|
|
202
|
-
/** Forwarded to `
|
|
627
|
+
/** Forwarded to `walkStructural`. Default 500. */
|
|
203
628
|
maxNodes?: number;
|
|
204
|
-
/** Forwarded to `
|
|
629
|
+
/** Forwarded to `walkStructural`. Default 4. */
|
|
205
630
|
minSize?: number;
|
|
206
631
|
/** Forwarded to `useShapeProbe`. Default 150 ms. */
|
|
207
632
|
resizeDebounceMs?: number;
|
|
208
633
|
}
|
|
209
634
|
interface UseSkeletonReturn {
|
|
210
|
-
/** Reactive captured shape — `undefined` on cache miss.
|
|
211
|
-
shape: Readonly<Ref<
|
|
635
|
+
/** Reactive captured shape — `undefined` on cache miss. Feed it to `<ASkeletonLayer>`. */
|
|
636
|
+
shape: Readonly<Ref<StructuralShape | undefined>>;
|
|
212
637
|
/**
|
|
213
638
|
* Synchronously measure the current target and write to cache. Returns the
|
|
214
639
|
* captured shape, or `undefined` if the target wasn't available / nothing
|
|
215
640
|
* worth measuring was rendered. Use when you want to force a capture outside
|
|
216
641
|
* the automatic `ResizeObserver` flow (e.g. after an animation settles).
|
|
217
642
|
*/
|
|
218
|
-
captureNow: () =>
|
|
643
|
+
captureNow: () => StructuralShape | undefined;
|
|
219
644
|
/** Drop the cache entry for this `cacheKey`. The reactive `shape` flips to `undefined`. */
|
|
220
645
|
clear: () => void;
|
|
221
646
|
}
|
|
222
647
|
/**
|
|
223
|
-
* High-level building block for
|
|
224
|
-
* + reactivity
|
|
648
|
+
* High-level building block for Recipe 3 — wires the structural capture +
|
|
649
|
+
* cache + reactivity around a target element. The reactive `shape` is fed to
|
|
650
|
+
* `<ASkeletonLayer>` which renders it in normal flow inside the consumer's
|
|
651
|
+
* container.
|
|
225
652
|
*
|
|
226
653
|
* ```ts
|
|
227
654
|
* const containerRef = ref<HTMLElement | null>(null);
|
|
@@ -238,17 +665,29 @@ interface UseSkeletonReturn {
|
|
|
238
665
|
* </div>
|
|
239
666
|
* ```
|
|
240
667
|
*
|
|
241
|
-
* For more control, drop down to `useShapeProbe`
|
|
242
|
-
*
|
|
668
|
+
* For more control, drop down to `useShapeProbe` (pass `walkStructural` as the
|
|
669
|
+
* capture strategy) + `getCachedStructural` / `setCachedStructural` and compose
|
|
670
|
+
* your own orchestration.
|
|
243
671
|
*/
|
|
244
672
|
declare function useSkeleton(options: UseSkeletonOptions): UseSkeletonReturn;
|
|
245
673
|
//#endregion
|
|
246
674
|
//#region src/composables/useShapeProbe.d.ts
|
|
247
|
-
|
|
675
|
+
type ProbeShape = CachedShape | StructuralShape;
|
|
676
|
+
/**
|
|
677
|
+
* Pluggable capture strategy. `walkDom` is the default (flat, absolute-
|
|
678
|
+
* positioned `CachedShape`). Recipe 3 passes `walkStructural` to produce a
|
|
679
|
+
* tree-shaped `StructuralShape` instead.
|
|
680
|
+
*/
|
|
681
|
+
type CaptureStrategy<S extends ProbeShape> = (el: HTMLElement, options: {
|
|
682
|
+
maxDepth: number;
|
|
683
|
+
maxNodes?: number;
|
|
684
|
+
minSize?: number;
|
|
685
|
+
}) => S;
|
|
686
|
+
interface ShapeProbeOptions<S extends ProbeShape = CachedShape> {
|
|
248
687
|
maxDepth: number;
|
|
249
|
-
/** Forwarded to
|
|
688
|
+
/** Forwarded to the capture strategy. Default 500. */
|
|
250
689
|
maxNodes?: number;
|
|
251
|
-
/** Forwarded to
|
|
690
|
+
/** Forwarded to the capture strategy. Default 4. */
|
|
252
691
|
minSize?: number;
|
|
253
692
|
/**
|
|
254
693
|
* Debounce window for `ResizeObserver`-triggered re-captures, in ms.
|
|
@@ -257,7 +696,12 @@ interface ShapeProbeOptions {
|
|
|
257
696
|
* always immediate via `requestAnimationFrame`.
|
|
258
697
|
*/
|
|
259
698
|
resizeDebounceMs?: number;
|
|
260
|
-
|
|
699
|
+
/**
|
|
700
|
+
* Capture strategy. Default: `walkDom` (flat positioned-block model).
|
|
701
|
+
* Pass `walkStructural` for the tree-shaped Recipe 3 model.
|
|
702
|
+
*/
|
|
703
|
+
capture?: CaptureStrategy<S>;
|
|
704
|
+
onCapture: (shape: S) => void;
|
|
261
705
|
}
|
|
262
706
|
/**
|
|
263
707
|
* Observe `getTarget()` and capture its rendered shape whenever the element
|
|
@@ -269,10 +713,10 @@ interface ShapeProbeOptions {
|
|
|
269
713
|
* render queue.
|
|
270
714
|
* - Subsequent `ResizeObserver` callbacks are debounced (default 150 ms) so a
|
|
271
715
|
* drag-resize doesn't trigger a fresh DOM walk per frame.
|
|
272
|
-
* -
|
|
273
|
-
* descendants) returns in bounded time.
|
|
716
|
+
* - The capture strategy itself enforces `maxNodes` so even a worst-case
|
|
717
|
+
* capture (10k descendants) returns in bounded time.
|
|
274
718
|
*/
|
|
275
|
-
declare function useShapeProbe(getTarget: () => HTMLElement | null, options: ShapeProbeOptions): void;
|
|
719
|
+
declare function useShapeProbe<S extends ProbeShape = CachedShape>(getTarget: () => HTMLElement | null, options: ShapeProbeOptions<S>): void;
|
|
276
720
|
//#endregion
|
|
277
721
|
//#region src/composables/useSkeletonCache.d.ts
|
|
278
722
|
/**
|
|
@@ -280,12 +724,29 @@ declare function useShapeProbe(getTarget: () => HTMLElement | null, options: Sha
|
|
|
280
724
|
* `persist` is enabled. SSR-safe — bypasses `window` access on the server.
|
|
281
725
|
* Rehydrates pre-computed styles for shapes deserialized from older sessions
|
|
282
726
|
* (Object.freeze + style/lineStyles don't survive `JSON.stringify` round-trip).
|
|
727
|
+
* Drops the entry if it was written by a different schema version.
|
|
283
728
|
*/
|
|
284
729
|
declare function getCached(key: string, persist: boolean): CachedShape | undefined;
|
|
285
730
|
/** Store a captured shape. `persist=true` mirrors to `localStorage`. */
|
|
286
731
|
declare function setCached(key: string, value: CachedShape, persist: boolean): void;
|
|
287
|
-
/**
|
|
732
|
+
/**
|
|
733
|
+
* Drop a single entry (or all entries when no key) — wipes both the flat-shape
|
|
734
|
+
* and the structural-shape namespaces. Exposed for tests + manual invalidation.
|
|
735
|
+
*/
|
|
288
736
|
declare function clearCached(key?: string): void;
|
|
737
|
+
/**
|
|
738
|
+
* Drop a single structural-shape entry (or all when no key). Kept separate
|
|
739
|
+
* from `clearCached` so callers that only manage structural shapes don't have
|
|
740
|
+
* to reach across namespaces.
|
|
741
|
+
*/
|
|
742
|
+
declare function clearCachedStructural(key?: string): void;
|
|
743
|
+
/**
|
|
744
|
+
* Lookup a structural shape by key. Reads in-memory first, then `localStorage`
|
|
745
|
+
* when `persist` is enabled. Stale schema versions get purged on read.
|
|
746
|
+
*/
|
|
747
|
+
declare function getCachedStructural(key: string, persist: boolean): StructuralShape | undefined;
|
|
748
|
+
/** Store a structural shape. `persist=true` mirrors to `localStorage`. */
|
|
749
|
+
declare function setCachedStructural(key: string, value: StructuralShape, persist: boolean): void;
|
|
289
750
|
//#endregion
|
|
290
751
|
//#region src/utils/walkDom.d.ts
|
|
291
752
|
interface WalkOptions {
|
|
@@ -312,29 +773,59 @@ interface WalkOptions {
|
|
|
312
773
|
*/
|
|
313
774
|
declare function walkDom(root: HTMLElement, options: WalkOptions): CachedShape;
|
|
314
775
|
//#endregion
|
|
776
|
+
//#region src/utils/walkStructural.d.ts
|
|
777
|
+
interface WalkStructuralOptions {
|
|
778
|
+
/** Max recursion depth. Default 12. */
|
|
779
|
+
maxDepth?: number;
|
|
780
|
+
/** Hard cap on captured nodes. Default 500. */
|
|
781
|
+
maxNodes?: number;
|
|
782
|
+
/** Skip elements smaller than this many CSS pixels (either axis). Default 4. */
|
|
783
|
+
minSize?: number;
|
|
784
|
+
}
|
|
785
|
+
/**
|
|
786
|
+
* Walk `root`'s descendants and produce a frozen tree-shaped capture.
|
|
787
|
+
* Direct children of `root` become top-level `nodes`; recursive children
|
|
788
|
+
* live on their respective `ContainerNode`s.
|
|
789
|
+
*/
|
|
790
|
+
declare function walkStructural(root: HTMLElement, options?: WalkStructuralOptions): StructuralShape;
|
|
791
|
+
//#endregion
|
|
315
792
|
//#region src/utils/buildStructuralSkeleton.d.ts
|
|
316
793
|
interface BuildOptions {
|
|
794
|
+
/** Animation class applied to every emitted shimmer surface. `null` disables animation. */
|
|
317
795
|
animationClass: string | null;
|
|
318
|
-
/** Max recursion depth — guards runaway templates. Default
|
|
796
|
+
/** Max recursion depth — guards runaway templates. Default 16. */
|
|
319
797
|
maxDepth?: number;
|
|
320
798
|
/**
|
|
321
|
-
* Hard cap on emitted skeleton nodes. Default
|
|
322
|
-
*
|
|
799
|
+
* Hard cap on emitted skeleton nodes. Default 600. The walk stops emitting
|
|
800
|
+
* past this cap; the partial tree is still valid (it just won't include the
|
|
801
|
+
* leaves beyond the budget).
|
|
323
802
|
*/
|
|
324
803
|
maxNodes?: number;
|
|
325
804
|
}
|
|
326
805
|
/**
|
|
327
|
-
* Walk a slot's vnode tree and produce a skeleton
|
|
328
|
-
*
|
|
329
|
-
*
|
|
330
|
-
*
|
|
331
|
-
*
|
|
332
|
-
*
|
|
806
|
+
* Walk a slot's vnode tree and produce a **DOM-mirror skeleton**: every element
|
|
807
|
+
* is preserved (same tag, same `class`, same inline `style`), and only the
|
|
808
|
+
* content is replaced. The output is structurally identical to what the real
|
|
809
|
+
* component would render — Tailwind utilities for layout, spacing, sizing,
|
|
810
|
+
* backgrounds and shadows all carry through. The CSS does the work of making
|
|
811
|
+
* it *look* like a skeleton.
|
|
333
812
|
*
|
|
334
|
-
*
|
|
335
|
-
*
|
|
336
|
-
*
|
|
337
|
-
*
|
|
813
|
+
* Replacement rules:
|
|
814
|
+
* - **Raw text** (e.g. interpolations, static strings) is wrapped in
|
|
815
|
+
* `<span class="a-skel-text-content">…the real text…</span>`. The text is
|
|
816
|
+
* kept as the span's children so the inline layout reserves its real
|
|
817
|
+
* rendered width — but the glyphs are painted transparent and a skeleton
|
|
818
|
+
* gradient is painted in their place. Multi-line text wraps naturally,
|
|
819
|
+
* producing one shimmer rect per visual line at the exact rendered position.
|
|
820
|
+
* - **Atomic / interactive tags** (`img`, `svg`, `button`, `input`, …) are
|
|
821
|
+
* replaced by a `<div class="a-skel-block">` carrying the original element's
|
|
822
|
+
* `class` and `style`, so dimensions and shapes (size, border-radius, etc.)
|
|
823
|
+
* still drive the layout.
|
|
824
|
+
* - **Container elements** (`div`, `section`, `h1`, `p`, `a`, `span`, …) are
|
|
825
|
+
* preserved as the same tag with the same `class` and `style`; we recurse
|
|
826
|
+
* into their children.
|
|
827
|
+
* - **Component vnodes** can't be introspected at render time, so we emit a
|
|
828
|
+
* single `<div class="a-skel-block">` carrying their outer `class` / `style`.
|
|
338
829
|
*/
|
|
339
830
|
declare function buildStructuralSkeleton(vnodes: VNodeChild | VNodeArrayChildren | undefined | null, opts: BuildOptions): VNode[];
|
|
340
831
|
//#endregion
|
|
@@ -347,5 +838,5 @@ declare function buildStructuralSkeleton(vnodes: VNodeChild | VNodeArrayChildren
|
|
|
347
838
|
*/
|
|
348
839
|
declare function fingerprintSlot(vnodes: VNode[] | undefined): string;
|
|
349
840
|
//#endregion
|
|
350
|
-
export { _default as ASkeleton, _default$1 as ASkeletonBlock, type ASkeletonBlockProps, _default$
|
|
841
|
+
export { _default as ASkeleton, _default$1 as ASkeletonArticle, _default$2 as ASkeletonAvatar, _default$3 as ASkeletonBlock, type ASkeletonBlockProps, _default$4 as ASkeletonButton, _default$5 as ASkeletonCard, _default$6 as ASkeletonChart, _default$7 as ASkeletonChip, _default$8 as ASkeletonClone, _default$9 as ASkeletonDivider, _default$10 as ASkeletonForm, _default$11 as ASkeletonHeading, _default$12 as ASkeletonImage, _default$13 as ASkeletonInput, _default$14 as ASkeletonLayer, type ASkeletonLayerProps, _default$15 as ASkeletonListItem, type ASkeletonProps, type ASkeletonSlots, _default$16 as ASkeletonTable, _default$17 as ASkeletonText, _default$18 as ASkeletonVideo, type BuildOptions, type CachedShape, type CaptureOptions, type CaptureSnapshot, type CaptureStrategy, type CapturedNode, type ContainerNode, type LeafKind, type LeafNode, type ProbeShape, type ShapeNode, type ShapeNodeType, type ShapeProbeOptions, type SkeletonAnimation, type SkeletonFallback, type StructuralNode, type StructuralShape, StructuralSkeleton, type StructuralTextLineRect, type TextLineRect, type UseSkeletonOptions, type UseSkeletonReturn, type WalkOptions, type WalkStructuralOptions, buildStructuralSkeleton, captureSnapshot, clearCached, clearCachedStructural, fingerprintSlot, getCached, getCachedStructural, setCached, setCachedStructural, useShapeProbe, useSkeleton, walkDom, walkStructural };
|
|
351
842
|
//# sourceMappingURL=index.d.ts.map
|