@alikhalilll/a-skeleton 1.0.0 → 1.1.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 +15 -12
- package/dist/index.cjs +28 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +7 -3
- package/dist/index.d.ts +7 -3
- package/dist/index.js +29 -6
- package/dist/index.js.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +1 -1
- package/src/components/ASkeleton.vue +21 -2
- package/src/composables/useSkeletonCache.ts +35 -6
- package/src/types.ts +6 -3
- package/web-types.json +2 -2
package/dist/index.d.cts
CHANGED
|
@@ -39,9 +39,12 @@ interface ASkeletonProps {
|
|
|
39
39
|
/** When true, render the captured skeleton (or `fallback` slot) instead of the default slot. */
|
|
40
40
|
loading: boolean;
|
|
41
41
|
/**
|
|
42
|
-
* Identifier used to look up + persist the captured shape.
|
|
43
|
-
* slot
|
|
44
|
-
*
|
|
42
|
+
* Identifier used to look up + persist the captured shape. Defaults to
|
|
43
|
+
* `"<slot-fingerprint>:<useId()>"` so every `<ASkeleton>` instance gets its
|
|
44
|
+
* own cache slot automatically — two `<ASkeleton><UserCard/></ASkeleton>` on
|
|
45
|
+
* the same page never collide. Pass explicitly when you *want* multiple
|
|
46
|
+
* instances to share a captured shape (e.g. a list of identical cards), or
|
|
47
|
+
* when one instance renders different shapes depending on a prop.
|
|
45
48
|
*/
|
|
46
49
|
cacheKey?: string;
|
|
47
50
|
/** Max recursion depth during shape capture. Default 6. */
|
|
@@ -280,6 +283,7 @@ declare function useShapeProbe(getTarget: () => HTMLElement | null, options: Sha
|
|
|
280
283
|
* `persist` is enabled. SSR-safe — bypasses `window` access on the server.
|
|
281
284
|
* Rehydrates pre-computed styles for shapes deserialized from older sessions
|
|
282
285
|
* (Object.freeze + style/lineStyles don't survive `JSON.stringify` round-trip).
|
|
286
|
+
* Drops the entry if it was written by a different schema version.
|
|
283
287
|
*/
|
|
284
288
|
declare function getCached(key: string, persist: boolean): CachedShape | undefined;
|
|
285
289
|
/** Store a captured shape. `persist=true` mirrors to `localStorage`. */
|
package/dist/index.d.ts
CHANGED
|
@@ -39,9 +39,12 @@ interface ASkeletonProps {
|
|
|
39
39
|
/** When true, render the captured skeleton (or `fallback` slot) instead of the default slot. */
|
|
40
40
|
loading: boolean;
|
|
41
41
|
/**
|
|
42
|
-
* Identifier used to look up + persist the captured shape.
|
|
43
|
-
* slot
|
|
44
|
-
*
|
|
42
|
+
* Identifier used to look up + persist the captured shape. Defaults to
|
|
43
|
+
* `"<slot-fingerprint>:<useId()>"` so every `<ASkeleton>` instance gets its
|
|
44
|
+
* own cache slot automatically — two `<ASkeleton><UserCard/></ASkeleton>` on
|
|
45
|
+
* the same page never collide. Pass explicitly when you *want* multiple
|
|
46
|
+
* instances to share a captured shape (e.g. a list of identical cards), or
|
|
47
|
+
* when one instance renders different shapes depending on a prop.
|
|
45
48
|
*/
|
|
46
49
|
cacheKey?: string;
|
|
47
50
|
/** Max recursion depth during shape capture. Default 6. */
|
|
@@ -280,6 +283,7 @@ declare function useShapeProbe(getTarget: () => HTMLElement | null, options: Sha
|
|
|
280
283
|
* `persist` is enabled. SSR-safe — bypasses `window` access on the server.
|
|
281
284
|
* Rehydrates pre-computed styles for shapes deserialized from older sessions
|
|
282
285
|
* (Object.freeze + style/lineStyles don't survive `JSON.stringify` round-trip).
|
|
286
|
+
* Drops the entry if it was written by a different schema version.
|
|
283
287
|
*/
|
|
284
288
|
declare function getCached(key: string, persist: boolean): CachedShape | undefined;
|
|
285
289
|
/** Store a captured shape. `persist=true` mirrors to `localStorage`. */
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Comment, Fragment, Text, computed, createCommentVNode, createElementBlock, createElementVNode, createVNode, defineComponent, h, normalizeClass, normalizeStyle, onBeforeUnmount, openBlock, ref, renderList, renderSlot, shallowRef, useSlots, watch } from "vue";
|
|
1
|
+
import { Comment, Fragment, Text, computed, createCommentVNode, createElementBlock, createElementVNode, createVNode, defineComponent, h, normalizeClass, normalizeStyle, onBeforeUnmount, openBlock, ref, renderList, renderSlot, shallowRef, useId, useSlots, watch } from "vue";
|
|
2
2
|
//#region ../../../node_modules/.pnpm/clsx@2.1.1/node_modules/clsx/dist/clsx.mjs
|
|
3
3
|
function r(e) {
|
|
4
4
|
var t, f, n = "";
|
|
@@ -3652,19 +3652,32 @@ function useShapeProbe(getTarget, options) {
|
|
|
3652
3652
|
const memory = /* @__PURE__ */ new Map();
|
|
3653
3653
|
const STORAGE_PREFIX = "a-skeleton:";
|
|
3654
3654
|
/**
|
|
3655
|
+
* Schema version for persisted entries. Bump whenever the `ShapeNode` /
|
|
3656
|
+
* `CachedShape` field set changes so stale localStorage payloads from older
|
|
3657
|
+
* releases get dropped on read instead of rehydrating into a wrong layout.
|
|
3658
|
+
*/
|
|
3659
|
+
const SCHEMA_VERSION = 1;
|
|
3660
|
+
/**
|
|
3655
3661
|
* Lookup a captured shape by key. Reads in-memory first, then `localStorage` if
|
|
3656
3662
|
* `persist` is enabled. SSR-safe — bypasses `window` access on the server.
|
|
3657
3663
|
* Rehydrates pre-computed styles for shapes deserialized from older sessions
|
|
3658
3664
|
* (Object.freeze + style/lineStyles don't survive `JSON.stringify` round-trip).
|
|
3665
|
+
* Drops the entry if it was written by a different schema version.
|
|
3659
3666
|
*/
|
|
3660
3667
|
function getCached(key, persist) {
|
|
3661
3668
|
const hit = memory.get(key);
|
|
3662
3669
|
if (hit) return hit;
|
|
3663
3670
|
if (!persist || typeof window === "undefined") return void 0;
|
|
3664
3671
|
try {
|
|
3665
|
-
const
|
|
3672
|
+
const storageKey = STORAGE_PREFIX + key;
|
|
3673
|
+
const raw = window.localStorage.getItem(storageKey);
|
|
3666
3674
|
if (!raw) return void 0;
|
|
3667
|
-
const
|
|
3675
|
+
const parsed = JSON.parse(raw);
|
|
3676
|
+
if (parsed.v !== SCHEMA_VERSION) {
|
|
3677
|
+
window.localStorage.removeItem(storageKey);
|
|
3678
|
+
return;
|
|
3679
|
+
}
|
|
3680
|
+
const rehydrated = rehydrateShape(parsed);
|
|
3668
3681
|
memory.set(key, rehydrated);
|
|
3669
3682
|
return rehydrated;
|
|
3670
3683
|
} catch {
|
|
@@ -3677,9 +3690,11 @@ function setCached(key, value, persist) {
|
|
|
3677
3690
|
if (!persist || typeof window === "undefined") return;
|
|
3678
3691
|
try {
|
|
3679
3692
|
const lean = {
|
|
3693
|
+
v: SCHEMA_VERSION,
|
|
3680
3694
|
width: value.width,
|
|
3681
3695
|
height: value.height,
|
|
3682
|
-
nodes: leanNodes(value.nodes)
|
|
3696
|
+
nodes: leanNodes(value.nodes),
|
|
3697
|
+
truncated: value.truncated
|
|
3683
3698
|
};
|
|
3684
3699
|
window.localStorage.setItem(STORAGE_PREFIX + key, JSON.stringify(lean));
|
|
3685
3700
|
} catch {}
|
|
@@ -3706,7 +3721,7 @@ function clearCached(key) {
|
|
|
3706
3721
|
* path stays allocation-free.
|
|
3707
3722
|
*/
|
|
3708
3723
|
function rehydrateShape(shape) {
|
|
3709
|
-
const nodes = shape.nodes.map((n) =>
|
|
3724
|
+
const nodes = shape.nodes.map((n) => freezeNodeStyles(n));
|
|
3710
3725
|
return Object.freeze({
|
|
3711
3726
|
nodes: Object.freeze(nodes),
|
|
3712
3727
|
width: shape.width,
|
|
@@ -4131,7 +4146,9 @@ const _sfc_main$2 = /* @__PURE__ */ defineComponent({
|
|
|
4131
4146
|
__expose();
|
|
4132
4147
|
const props = __props;
|
|
4133
4148
|
const slots = useSlots();
|
|
4134
|
-
const
|
|
4149
|
+
const instanceId = useId();
|
|
4150
|
+
const resolvedKey = computed(() => props.cacheKey ?? `${fingerprintSlot(slots.default?.())}:${instanceId}`);
|
|
4151
|
+
const warnedKeys = /* @__PURE__ */ new Set();
|
|
4135
4152
|
const cached = shallowRef(getCached(resolvedKey.value, props.persist));
|
|
4136
4153
|
watch(resolvedKey, (key) => {
|
|
4137
4154
|
cached.value = getCached(key, props.persist);
|
|
@@ -4144,6 +4161,10 @@ const _sfc_main$2 = /* @__PURE__ */ defineComponent({
|
|
|
4144
4161
|
onCapture: (shape) => {
|
|
4145
4162
|
setCached(resolvedKey.value, shape, props.persist);
|
|
4146
4163
|
cached.value = shape;
|
|
4164
|
+
if (shape.truncated && !warnedKeys.has(resolvedKey.value)) {
|
|
4165
|
+
warnedKeys.add(resolvedKey.value);
|
|
4166
|
+
console.warn(`[ASkeleton] Capture truncated at maxNodes=${props.maxNodes} for cacheKey="${resolvedKey.value}". The replayed skeleton will be missing nodes. Raise \`max-nodes\` or mark dense subtrees with \`data-skeleton-stop\` to collapse them into a single block.`);
|
|
4167
|
+
}
|
|
4147
4168
|
}
|
|
4148
4169
|
});
|
|
4149
4170
|
const animationClass = computed(() => props.animation === "none" ? null : `a-skel-block--anim-${props.animation}`);
|
|
@@ -4165,7 +4186,9 @@ const _sfc_main$2 = /* @__PURE__ */ defineComponent({
|
|
|
4165
4186
|
const __returned__ = {
|
|
4166
4187
|
props,
|
|
4167
4188
|
slots,
|
|
4189
|
+
instanceId,
|
|
4168
4190
|
resolvedKey,
|
|
4191
|
+
warnedKeys,
|
|
4169
4192
|
cached,
|
|
4170
4193
|
wrapperRef,
|
|
4171
4194
|
animationClass,
|