nano-skeleton 0.4.0 → 0.5.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/CHANGELOG.md CHANGED
@@ -1,5 +1,23 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.5.0
4
+
5
+ ### Minor Changes
6
+
7
+ - refactor: get rid of data attributes
8
+
9
+ BREAKING CHANGES:
10
+
11
+ - use `inline` attribute instead of `text` attribute
12
+ - `data-text` attribute is no more
13
+ - `data-loading` attribute is no more as well
14
+
15
+ ## 0.4.1
16
+
17
+ ### Patch Changes
18
+
19
+ - fix: link's skeleton and link's underline have different widths
20
+
3
21
  ## 0.4.0
4
22
 
5
23
  ### Minor Changes
@@ -2,12 +2,14 @@
2
2
  export declare class Skeleton extends HTMLElement {
3
3
  #private;
4
4
  static observedAttributes: string[];
5
+ get loading(): boolean;
6
+ set loading(value: boolean);
5
7
  /** Keeps the content focusable and clickable while loading */
6
8
  get interactive(): boolean;
7
9
  set interactive(value: boolean);
8
10
  /** Forces text mode, even when the text is wrapped in elements */
9
- get text(): boolean;
10
- set text(value: boolean);
11
+ get inline(): boolean;
12
+ set inline(value: boolean);
11
13
  attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void;
12
14
  connectedCallback(): void;
13
15
  disconnectedCallback(): void;
package/dist/Skeleton.js CHANGED
@@ -1,2 +1,2 @@
1
- import{SKELETON_CONTEXT as e}from"./constants.js";import{ContextRequestEvent as t}from"./ContextRequestEvent.js";import{adoptStyles as n}from"./styles.js";function r(e){return`adoptedStyleSheets`in e}var i=class extends HTMLElement{static observedAttributes=[`interactive`,`text`];#e=!1;#t;#n=new MutationObserver(()=>this.#r());get interactive(){return this.hasAttribute(`interactive`)}set interactive(e){this.toggleAttribute(`interactive`,!!e)}get text(){return this.hasAttribute(`text`)}set text(e){this.toggleAttribute(`text`,!!e)}attributeChangedCallback(e,t,n){t!==n&&(e===`text`?this.#r():this.#i(this.#e))}connectedCallback(){let i=this.getRootNode();r(i)&&n(i),this.#r(),this.#i(!1),this.dispatchEvent(new t(e,(e,t)=>{t&&(this.#t=t),this.#i(e)},!0)),this.#n.observe(this,{childList:!0,characterData:!0,subtree:!0})}disconnectedCallback(){this.#t?.(),this.#t=void 0,this.#n.disconnect()}#r(){let e=this.text;for(let t of this.childNodes){if(e)break;t instanceof Text&&t.data.trim()!==``&&(e=!0)}this.toggleAttribute(`data-text`,e)}#i(e){this.#e=e,this.toggleAttribute(`inert`,e&&!this.interactive),this.toggleAttribute(`data-loading`,e)}};export{i as Skeleton};
1
+ import{SKELETON_CONTEXT as e}from"./constants.js";import{ContextRequestEvent as t}from"./ContextRequestEvent.js";import{adoptStyles as n}from"./styles.js";function r(e){return`adoptedStyleSheets`in e}var i=class extends HTMLElement{static observedAttributes=[`interactive`,`inline`];#e;#t=new MutationObserver(()=>this.#n());get loading(){return this.hasAttribute(`loading`)}set loading(e){this.toggleAttribute(`loading`,!!e)}get interactive(){return this.hasAttribute(`interactive`)}set interactive(e){this.toggleAttribute(`interactive`,!!e)}get inline(){return this.hasAttribute(`inline`)}set inline(e){this.toggleAttribute(`inline`,!!e)}attributeChangedCallback(e,t,n){t!==n&&(e===`inline`?this.#n():this.#r(this.loading))}connectedCallback(){let i=this.getRootNode();r(i)&&n(i),this.#n(),this.#r(!1),this.dispatchEvent(new t(e,(e,t)=>{t&&(this.#e=t),this.#r(e)},!0)),this.#t.observe(this,{childList:!0,characterData:!0,subtree:!0})}disconnectedCallback(){this.#e?.(),this.#e=void 0,this.#t.disconnect()}#n(){let e=this.inline;for(let t of this.childNodes){if(e)break;t instanceof Text&&t.data.trim()!==``&&(e=!0)}this.toggleAttribute(`inline`,e)}#r(e){this.toggleAttribute(`loading`,e),this.toggleAttribute(`inert`,e&&!this.interactive)}};export{i as Skeleton};
2
2
  //# sourceMappingURL=Skeleton.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Skeleton.js","names":["isDocumentOrShadowRoot","node","Skeleton","#update","value","oldValue","newValue","name","#render","#loading","root","adoptStyles","ContextRequestEvent","SKELETON_CONTEXT","unsubscribe","#unsubscribe","loading","#observer","isText"],"sources":["../src/Skeleton.ts"],"sourcesContent":["import { SKELETON_CONTEXT } from \"#root/constants.js\";\nimport { ContextRequestEvent } from \"#root/ContextRequestEvent.js\";\nimport { adoptStyles } from \"#root/styles.js\";\nimport { type Unsubscribe } from \"#root/types.js\";\n\nfunction isDocumentOrShadowRoot(\n node: Node | Document | ShadowRoot,\n): node is Document | ShadowRoot {\n return \"adoptedStyleSheets\" in node;\n}\n\nexport class Skeleton extends HTMLElement {\n static observedAttributes = [\"interactive\", \"text\"];\n\n #loading = false;\n #unsubscribe?: Unsubscribe | undefined;\n #observer = new MutationObserver(() => this.#update());\n\n /** Keeps the content focusable and clickable while loading */\n get interactive() {\n return this.hasAttribute(\"interactive\");\n }\n\n set interactive(value: boolean) {\n this.toggleAttribute(\"interactive\", Boolean(value));\n }\n\n /** Forces text mode, even when the text is wrapped in elements */\n get text() {\n return this.hasAttribute(\"text\");\n }\n\n set text(value: boolean) {\n this.toggleAttribute(\"text\", Boolean(value));\n }\n\n attributeChangedCallback(\n name: string,\n oldValue: string | null,\n newValue: string | null,\n ) {\n if (oldValue === newValue) return;\n if (name === \"text\") this.#update();\n else this.#render(this.#loading);\n }\n\n connectedCallback() {\n const root = this.getRootNode();\n\n if (isDocumentOrShadowRoot(root)) {\n adoptStyles(root);\n }\n\n this.#update();\n this.#render(false);\n\n this.dispatchEvent(\n new ContextRequestEvent(\n SKELETON_CONTEXT,\n (loading, unsubscribe) => {\n if (unsubscribe) this.#unsubscribe = unsubscribe;\n this.#render(loading);\n },\n true,\n ),\n );\n\n this.#observer.observe(this, {\n childList: true,\n characterData: true,\n subtree: true,\n });\n }\n\n disconnectedCallback() {\n this.#unsubscribe?.();\n this.#unsubscribe = undefined;\n this.#observer.disconnect();\n }\n\n #update() {\n let isText = this.text;\n for (const node of this.childNodes) {\n if (isText) break;\n if (node instanceof Text && node.data.trim() !== \"\") {\n isText = true;\n }\n }\n this.toggleAttribute(\"data-text\", isText);\n }\n\n #render(loading: boolean) {\n this.#loading = loading;\n this.toggleAttribute(\"inert\", loading && !this.interactive);\n this.toggleAttribute(\"data-loading\", loading);\n }\n}\n"],"mappings":"A,2JAKA,SAASA,EACP,EAC+B,CAC/B,MAAO,uBAAwBC,CACjC,CAEA,IAAaC,EAAb,cAA8B,WAAY,CACxC,OAAO,mBAAqB,CAAC,cAAe,MAAM,EAElD,GAAW,GACX,GACA,GAAY,IAAI,qBAAuB,KAAKC,GAAQ,CAAC,EAGrD,IAAI,aAAc,CAChB,OAAO,KAAK,aAAa,aAAa,CACxC,CAEA,IAAI,YAAY,EAAgB,CAC9B,KAAK,gBAAgB,cAAe,EAAQC,CAAM,CACpD,CAGA,IAAI,MAAO,CACT,OAAO,KAAK,aAAa,MAAM,CACjC,CAEA,IAAI,KAAK,EAAgB,CACvB,KAAK,gBAAgB,OAAQ,EAAQA,CAAM,CAC7C,CAEA,yBACE,EACA,EACA,EACA,CACIC,IAAaC,IACbC,IAAS,OAAQ,KAAKJ,GAAQ,EAC7B,KAAKK,GAAQ,KAAKC,EAAQ,EACjC,CAEA,mBAAoB,CAClB,IAAMC,EAAO,KAAK,YAAY,EAE1BV,EAAuBU,CAAI,GAC7BC,EAAYD,CAAI,EAGlB,KAAKP,GAAQ,EACb,KAAKK,GAAQ,EAAK,EAElB,KAAK,cACH,IAAII,EACFC,GACC,EAAS,IAAgB,CACpBC,IAAa,KAAKC,GAAeD,GACrC,KAAKN,GAAQQ,CAAO,CACtB,EACA,EACF,CACF,EAEA,KAAKC,GAAU,QAAQ,KAAM,CAC3B,UAAW,GACX,cAAe,GACf,QAAS,EACX,CAAC,CACH,CAEA,sBAAuB,CACrB,KAAKF,KAAe,EACpB,KAAKA,GAAe,IAAA,GACpB,KAAKE,GAAU,WAAW,CAC5B,CAEA,IAAU,CACR,IAAIC,EAAS,KAAK,KAClB,IAAK,IAAMjB,KAAQ,KAAK,WAAY,CAClC,GAAIiB,EAAQ,MACRjB,aAAgB,MAAQA,EAAK,KAAK,KAAK,IAAM,KAC/C,EAAS,GAEb,CACA,KAAK,gBAAgB,YAAaiB,CAAM,CAC1C,CAEA,GAAQ,EAAkB,CACxB,KAAKT,GAAWO,EAChB,KAAK,gBAAgB,QAASA,GAAW,CAAC,KAAK,WAAW,EAC1D,KAAK,gBAAgB,eAAgBA,CAAO,CAC9C,CACF,E"}
1
+ {"version":3,"file":"Skeleton.js","names":["isDocumentOrShadowRoot","node","Skeleton","#update","value","oldValue","newValue","name","#render","root","adoptStyles","ContextRequestEvent","SKELETON_CONTEXT","unsubscribe","#unsubscribe","loading","#observer","isInline"],"sources":["../src/Skeleton.ts"],"sourcesContent":["import { SKELETON_CONTEXT } from \"#root/constants.js\";\nimport { ContextRequestEvent } from \"#root/ContextRequestEvent.js\";\nimport { adoptStyles } from \"#root/styles.js\";\nimport { type Unsubscribe } from \"#root/types.js\";\n\nfunction isDocumentOrShadowRoot(\n node: Node | Document | ShadowRoot,\n): node is Document | ShadowRoot {\n return \"adoptedStyleSheets\" in node;\n}\n\nexport class Skeleton extends HTMLElement {\n static observedAttributes = [\"interactive\", \"inline\"];\n\n #unsubscribe?: Unsubscribe | undefined;\n #observer = new MutationObserver(() => this.#update());\n\n get loading() {\n return this.hasAttribute(\"loading\");\n }\n\n set loading(value: boolean) {\n this.toggleAttribute(\"loading\", Boolean(value));\n }\n\n /** Keeps the content focusable and clickable while loading */\n get interactive() {\n return this.hasAttribute(\"interactive\");\n }\n\n set interactive(value: boolean) {\n this.toggleAttribute(\"interactive\", Boolean(value));\n }\n\n /** Forces text mode, even when the text is wrapped in elements */\n get inline() {\n return this.hasAttribute(\"inline\");\n }\n\n set inline(value: boolean) {\n this.toggleAttribute(\"inline\", Boolean(value));\n }\n\n attributeChangedCallback(\n name: string,\n oldValue: string | null,\n newValue: string | null,\n ) {\n if (oldValue === newValue) return;\n if (name === \"inline\") this.#update();\n else this.#render(this.loading);\n }\n\n connectedCallback() {\n const root = this.getRootNode();\n\n if (isDocumentOrShadowRoot(root)) {\n adoptStyles(root);\n }\n\n this.#update();\n this.#render(false);\n\n this.dispatchEvent(\n new ContextRequestEvent(\n SKELETON_CONTEXT,\n (loading, unsubscribe) => {\n if (unsubscribe) this.#unsubscribe = unsubscribe;\n this.#render(loading);\n },\n true,\n ),\n );\n\n this.#observer.observe(this, {\n childList: true,\n characterData: true,\n subtree: true,\n });\n }\n\n disconnectedCallback() {\n this.#unsubscribe?.();\n this.#unsubscribe = undefined;\n this.#observer.disconnect();\n }\n\n #update() {\n let isInline = this.inline;\n for (const node of this.childNodes) {\n if (isInline) break;\n if (node instanceof Text && node.data.trim() !== \"\") {\n isInline = true;\n }\n }\n this.toggleAttribute(\"inline\", isInline);\n }\n\n #render(loading: boolean) {\n this.toggleAttribute(\"loading\", loading);\n this.toggleAttribute(\"inert\", loading && !this.interactive);\n }\n}\n"],"mappings":"A,2JAKA,SAASA,EACP,EAC+B,CAC/B,MAAO,uBAAwBC,CACjC,CAEA,IAAaC,EAAb,cAA8B,WAAY,CACxC,OAAO,mBAAqB,CAAC,cAAe,QAAQ,EAEpD,GACA,GAAY,IAAI,qBAAuB,KAAKC,GAAQ,CAAC,EAErD,IAAI,SAAU,CACZ,OAAO,KAAK,aAAa,SAAS,CACpC,CAEA,IAAI,QAAQ,EAAgB,CAC1B,KAAK,gBAAgB,UAAW,EAAQC,CAAM,CAChD,CAGA,IAAI,aAAc,CAChB,OAAO,KAAK,aAAa,aAAa,CACxC,CAEA,IAAI,YAAY,EAAgB,CAC9B,KAAK,gBAAgB,cAAe,EAAQA,CAAM,CACpD,CAGA,IAAI,QAAS,CACX,OAAO,KAAK,aAAa,QAAQ,CACnC,CAEA,IAAI,OAAO,EAAgB,CACzB,KAAK,gBAAgB,SAAU,EAAQA,CAAM,CAC/C,CAEA,yBACE,EACA,EACA,EACA,CACIC,IAAaC,IACbC,IAAS,SAAU,KAAKJ,GAAQ,EAC/B,KAAKK,GAAQ,KAAK,OAAO,EAChC,CAEA,mBAAoB,CAClB,IAAMC,EAAO,KAAK,YAAY,EAE1BT,EAAuBS,CAAI,GAC7BC,EAAYD,CAAI,EAGlB,KAAKN,GAAQ,EACb,KAAKK,GAAQ,EAAK,EAElB,KAAK,cACH,IAAIG,EACFC,GACC,EAAS,IAAgB,CACpBC,IAAa,KAAKC,GAAeD,GACrC,KAAKL,GAAQO,CAAO,CACtB,EACA,EACF,CACF,EAEA,KAAKC,GAAU,QAAQ,KAAM,CAC3B,UAAW,GACX,cAAe,GACf,QAAS,EACX,CAAC,CACH,CAEA,sBAAuB,CACrB,KAAKF,KAAe,EACpB,KAAKA,GAAe,IAAA,GACpB,KAAKE,GAAU,WAAW,CAC5B,CAEA,IAAU,CACR,IAAIC,EAAW,KAAK,OACpB,IAAK,IAAMhB,KAAQ,KAAK,WAAY,CAClC,GAAIgB,EAAU,MACVhB,aAAgB,MAAQA,EAAK,KAAK,KAAK,IAAM,KAC/C,EAAW,GAEf,CACA,KAAK,gBAAgB,SAAUgB,CAAQ,CACzC,CAEA,GAAQ,EAAkB,CACxB,KAAK,gBAAgB,UAAWF,CAAO,EACvC,KAAK,gBAAgB,QAASA,GAAW,CAAC,KAAK,WAAW,CAC5D,CACF,E"}
package/dist/constants.js CHANGED
@@ -15,7 +15,7 @@ const e=`nano-skeleton`,t=`${e}-provider`,{default:n}={default:`:scope {
15
15
  );
16
16
  }
17
17
 
18
- :scope:not([data-text]) {
18
+ :scope:not([inline]) {
19
19
  display: contents;
20
20
  }
21
21
 
@@ -24,20 +24,21 @@ const e=`nano-skeleton`,t=`${e}-provider`,{default:n}={default:`:scope {
24
24
  * as layout is intact. Hidden visually only: focus and accessibility are
25
25
  * handled by inert, so interactive skeletons keep both.
26
26
  */
27
- :scope[data-loading] > * > * {
27
+ :scope[loading] > * > * {
28
28
  opacity: 0 !important;
29
29
  }
30
30
 
31
31
  /**
32
32
  * Skeleton's content is just an inline text
33
33
  */
34
- :scope[data-loading][data-text] {
34
+ :scope[loading][inline] {
35
35
  display: inline;
36
36
  border-radius: var(
37
37
  --nano-skeleton-text-border-radius,
38
38
  var(--nano-skeleton-text-border-radius-default)
39
39
  );
40
40
  box-decoration-break: clone;
41
+ text-decoration-skip-ink: none;
41
42
  text-box: cap alphabetic;
42
43
  /**
43
44
  * This ensures the ellipsis on truncated text is also hidden.
@@ -54,18 +55,18 @@ const e=`nano-skeleton`,t=`${e}-provider`,{default:n}={default:`:scope {
54
55
  * Children and grandchildren need to inherit these styles
55
56
  * for consistent outlines
56
57
  */
57
- :scope[data-loading][data-text] > *,
58
- :scope[data-loading][data-text] > * > * {
58
+ :scope[loading][inline] > *,
59
+ :scope[loading][inline] > * > * {
59
60
  border-radius: inherit;
60
61
  text-box: inherit;
61
62
  }
62
63
 
63
- :scope[data-loading] > :is(video, img):only-child {
64
+ :scope[loading] > :is(video, img):only-child {
64
65
  content: url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7") !important;
65
66
  }
66
67
 
67
- :scope[data-loading][data-text],
68
- :scope[data-loading]:not([data-text]) > * {
68
+ :scope[loading][inline],
69
+ :scope[loading]:not([inline]) > * {
69
70
  background-image: var(
70
71
  --nano-skeleton-background-image,
71
72
  var(--nano-skeleton-background-image-default)
@@ -77,8 +78,8 @@ const e=`nano-skeleton`,t=`${e}-provider`,{default:n}={default:`:scope {
77
78
  }
78
79
 
79
80
  @media not (prefers-reduced-motion: reduce) {
80
- :scope[data-loading][data-text],
81
- :scope[data-loading]:not([data-text]) > * {
81
+ :scope[loading][inline],
82
+ :scope[loading]:not([inline]) > * {
82
83
  animation: var(
83
84
  --nano-skeleton-animation,
84
85
  var(--nano-skeleton-animation-default)
@@ -89,8 +90,8 @@ const e=`nano-skeleton`,t=`${e}-provider`,{default:n}={default:`:scope {
89
90
  /**
90
91
  * The shimmer follows the reading direction
91
92
  */
92
- :scope[data-loading][data-text]:dir(rtl),
93
- :scope[data-loading]:not([data-text]) > :dir(rtl) {
93
+ :scope[loading][inline]:dir(rtl),
94
+ :scope[loading]:not([inline]) > :dir(rtl) {
94
95
  --nano-skeleton-shimmer-from: 0%;
95
96
  --nano-skeleton-shimmer-to: 100%;
96
97
  }
@@ -1 +1 @@
1
- {"version":3,"file":"constants.js","names":["COMPONENT_NAME","PROVIDER_NAME","CSS_CONTENT","SKELETON_CONTEXT"],"sources":["../src/constants.ts"],"sourcesContent":["const isDev = import.meta.env.MODE !== \"production\";\n\nexport const COMPONENT_NAME = \"nano-skeleton\" as const;\n\nexport const PROVIDER_NAME = `${COMPONENT_NAME}-provider` as const;\n\nconst { default: CSS_CONTENT } = isDev\n ? await import(\"./styles.css?inline\")\n : { default: `__CSS_CONTENT__` };\n\nexport { CSS_CONTENT };\n\nexport const SKELETON_CONTEXT = Symbol.for(`${COMPONENT_NAME}-context`);\n"],"mappings":"AAEA,MAAaA,EAAiB,gBAEjBC,EAAgB,GAAGD,EAAe,WAEzC,CAAE,QAASE,GAEb,CAAE,QAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyGb,EAIWC,EAAmB,OAAO,IAAI,GAAGH,EAAe,SAAS,E"}
1
+ {"version":3,"file":"constants.js","names":["COMPONENT_NAME","PROVIDER_NAME","CSS_CONTENT","SKELETON_CONTEXT"],"sources":["../src/constants.ts"],"sourcesContent":["const isDev = import.meta.env.MODE !== \"production\";\n\nexport const COMPONENT_NAME = \"nano-skeleton\" as const;\n\nexport const PROVIDER_NAME = `${COMPONENT_NAME}-provider` as const;\n\nconst { default: CSS_CONTENT } = isDev\n ? await import(\"./styles.css?inline\")\n : { default: `__CSS_CONTENT__` };\n\nexport { CSS_CONTENT };\n\nexport const SKELETON_CONTEXT = Symbol.for(`${COMPONENT_NAME}-context`);\n"],"mappings":"AAEA,MAAaA,EAAiB,gBAEjBC,EAAgB,GAAGD,EAAe,WAEzC,CAAE,QAASE,GAEb,CAAE,QAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0Gb,EAIWC,EAAmB,OAAO,IAAI,GAAGH,EAAe,SAAS,E"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nano-skeleton",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "The perfect skeleton component",
5
5
  "homepage": "https://smashercosmo.github.io/nano-skeleton/",
6
6
  "bugs": {