@aejkatappaja/phantom-ui 0.5.1 → 0.6.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 +105 -56
- package/dist/phantom-ui.cdn.js +11 -7
- package/dist/phantom-ui.js +13 -9
- package/dist/ssr.css +27 -0
- package/package.json +7 -3
- package/src/cli/init.mjs +140 -42
package/README.md
CHANGED
|
@@ -59,6 +59,90 @@ Or drop in a script tag with no build step:
|
|
|
59
59
|
<script src="https://cdn.jsdelivr.net/npm/@aejkatappaja/phantom-ui/dist/phantom-ui.cdn.js"></script>
|
|
60
60
|
```
|
|
61
61
|
|
|
62
|
+
## Automatic setup
|
|
63
|
+
|
|
64
|
+
A `postinstall` script runs after installation and detects your project setup. It handles two things:
|
|
65
|
+
|
|
66
|
+
**JSX type declarations** — For React, Solid, and Qwik, it generates a `phantom-ui.d.ts` in your `src/` directory so `<phantom-ui>` is recognized in JSX. Vue, Svelte, and Angular work out of the box without any type declaration.
|
|
67
|
+
|
|
68
|
+
**SSR pre-hydration CSS** — For Next.js, Nuxt, SvelteKit, Remix, and Qwik, it adds `import "@aejkatappaja/phantom-ui/ssr.css"` to your layout file to prevent content flash before hydration (see [Pre-hydration CSS](#pre-hydration-css)).
|
|
69
|
+
|
|
70
|
+
If the postinstall did not run (CI, monorepos, `--ignore-scripts`), you can trigger it manually:
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
npx @aejkatappaja/phantom-ui init # npm
|
|
74
|
+
bunx @aejkatappaja/phantom-ui init # bun
|
|
75
|
+
pnpx @aejkatappaja/phantom-ui init # pnpm
|
|
76
|
+
yarn dlx @aejkatappaja/phantom-ui init # yarn
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
<details>
|
|
80
|
+
<summary>Manual JSX type declarations</summary>
|
|
81
|
+
|
|
82
|
+
**React / Next.js / Remix**
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
import type { PhantomUiAttributes } from "@aejkatappaja/phantom-ui";
|
|
86
|
+
|
|
87
|
+
declare module "react/jsx-runtime" {
|
|
88
|
+
export namespace JSX {
|
|
89
|
+
interface IntrinsicElements {
|
|
90
|
+
"phantom-ui": PhantomUiAttributes;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
**Solid**
|
|
97
|
+
|
|
98
|
+
```typescript
|
|
99
|
+
import type { SolidPhantomUiAttributes } from "@aejkatappaja/phantom-ui";
|
|
100
|
+
|
|
101
|
+
declare module "solid-js" {
|
|
102
|
+
namespace JSX {
|
|
103
|
+
interface IntrinsicElements {
|
|
104
|
+
"phantom-ui": SolidPhantomUiAttributes;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
**Qwik**
|
|
111
|
+
|
|
112
|
+
```typescript
|
|
113
|
+
import type { PhantomUiAttributes } from "@aejkatappaja/phantom-ui";
|
|
114
|
+
|
|
115
|
+
declare module "@builder.io/qwik" {
|
|
116
|
+
namespace QwikJSX {
|
|
117
|
+
interface IntrinsicElements {
|
|
118
|
+
"phantom-ui": PhantomUiAttributes & Record<string, unknown>;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
</details>
|
|
125
|
+
|
|
126
|
+
<details>
|
|
127
|
+
<summary>Manual SSR CSS import</summary>
|
|
128
|
+
|
|
129
|
+
Add this import to your root layout file:
|
|
130
|
+
|
|
131
|
+
```js
|
|
132
|
+
import "@aejkatappaja/phantom-ui/ssr.css";
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
| Framework | Layout file |
|
|
136
|
+
| --- | --- |
|
|
137
|
+
| Next.js (App Router) | `app/layout.tsx` |
|
|
138
|
+
| Next.js (Pages) | `pages/_app.tsx` |
|
|
139
|
+
| Nuxt | `app.vue` |
|
|
140
|
+
| SvelteKit | `src/routes/+layout.svelte` |
|
|
141
|
+
| Remix | `app/root.tsx` |
|
|
142
|
+
| Qwik | `src/root.tsx` |
|
|
143
|
+
|
|
144
|
+
</details>
|
|
145
|
+
|
|
62
146
|
## Quick start
|
|
63
147
|
|
|
64
148
|
```html
|
|
@@ -188,7 +272,7 @@ function ProfileCard() {
|
|
|
188
272
|
}
|
|
189
273
|
```
|
|
190
274
|
|
|
191
|
-
### SSR frameworks (Next.js, Nuxt, SvelteKit)
|
|
275
|
+
### SSR frameworks (Next.js, Nuxt, SvelteKit, Remix, Qwik)
|
|
192
276
|
|
|
193
277
|
The component needs browser APIs to measure the DOM. Import it client-side only:
|
|
194
278
|
|
|
@@ -226,69 +310,31 @@ onMounted(() => import("@aejkatappaja/phantom-ui"));
|
|
|
226
310
|
|
|
227
311
|
The `<phantom-ui>` tag can exist in server-rendered HTML. The browser treats it as an unknown element until hydration, then the Web Component activates and measures the DOM. Content renders normally on the server, which is good for SEO.
|
|
228
312
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
The package ships full type definitions. A `postinstall` script automatically detects your framework and generates a `phantom-ui.d.ts` in your `src/` directory. No extra step needed.
|
|
313
|
+
#### Pre-hydration CSS
|
|
232
314
|
|
|
233
|
-
|
|
315
|
+
Before JavaScript loads, content inside `<phantom-ui loading>` can briefly flash as visible text. The package ships a small CSS file that hides this content immediately, with no JS needed:
|
|
234
316
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
```bash
|
|
238
|
-
npx @aejkatappaja/phantom-ui init # npm
|
|
239
|
-
bunx @aejkatappaja/phantom-ui init # bun
|
|
240
|
-
pnpx @aejkatappaja/phantom-ui init # pnpm
|
|
241
|
-
yarn dlx @aejkatappaja/phantom-ui init # yarn
|
|
242
|
-
```
|
|
243
|
-
|
|
244
|
-
<details>
|
|
245
|
-
<summary>Or create the file yourself:</summary>
|
|
246
|
-
|
|
247
|
-
**React**
|
|
248
|
-
|
|
249
|
-
```typescript
|
|
250
|
-
import type { PhantomUiAttributes } from "@aejkatappaja/phantom-ui";
|
|
251
|
-
|
|
252
|
-
declare module "react/jsx-runtime" {
|
|
253
|
-
export namespace JSX {
|
|
254
|
-
interface IntrinsicElements {
|
|
255
|
-
"phantom-ui": PhantomUiAttributes;
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
}
|
|
317
|
+
```css
|
|
318
|
+
import "@aejkatappaja/phantom-ui/ssr.css";
|
|
259
319
|
```
|
|
260
320
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
```typescript
|
|
264
|
-
import type { SolidPhantomUiAttributes } from "@aejkatappaja/phantom-ui";
|
|
321
|
+
The `postinstall` script automatically detects SSR frameworks and adds this import to your layout file (e.g. `app/layout.tsx` for Next.js, `app.vue` for Nuxt, `+layout.svelte` for SvelteKit). If you use the CDN build, add the rules directly in your `<head>`:
|
|
265
322
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
323
|
+
```html
|
|
324
|
+
<style>
|
|
325
|
+
phantom-ui[loading] * {
|
|
326
|
+
-webkit-text-fill-color: transparent !important;
|
|
327
|
+
pointer-events: none;
|
|
328
|
+
user-select: none;
|
|
271
329
|
}
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
```typescript
|
|
278
|
-
import type { PhantomUiAttributes } from "@aejkatappaja/phantom-ui";
|
|
279
|
-
|
|
280
|
-
declare module "@builder.io/qwik" {
|
|
281
|
-
namespace QwikJSX {
|
|
282
|
-
interface IntrinsicElements {
|
|
283
|
-
"phantom-ui": PhantomUiAttributes & Record<string, unknown>;
|
|
284
|
-
}
|
|
330
|
+
phantom-ui[loading] img, phantom-ui[loading] svg,
|
|
331
|
+
phantom-ui[loading] video, phantom-ui[loading] canvas,
|
|
332
|
+
phantom-ui[loading] button, phantom-ui[loading] [role="button"] {
|
|
333
|
+
opacity: 0 !important;
|
|
285
334
|
}
|
|
286
|
-
|
|
335
|
+
</style>
|
|
287
336
|
```
|
|
288
337
|
|
|
289
|
-
|
|
290
|
-
</details>
|
|
291
|
-
|
|
292
338
|
## Attributes
|
|
293
339
|
|
|
294
340
|
| Attribute | Type | Default | Description |
|
|
@@ -306,12 +352,14 @@ declare module "@builder.io/qwik" {
|
|
|
306
352
|
|
|
307
353
|
## Fine-grained control
|
|
308
354
|
|
|
309
|
-
|
|
355
|
+
Data attributes let you control which elements get shimmer treatment and how they are measured:
|
|
310
356
|
|
|
311
357
|
**`data-shimmer-ignore`** keeps an element and all its descendants visible during loading. Useful for logos, brand marks, or live indicators that should always be shown.
|
|
312
358
|
|
|
313
359
|
**`data-shimmer-no-children`** captures the element as one single shimmer block instead of recursing into its children. Useful for dense metric groups that should appear as a single placeholder.
|
|
314
360
|
|
|
361
|
+
**`data-shimmer-width`** / **`data-shimmer-height`** override the measured dimensions (in pixels) of an element. Useful for dynamically sized elements that have no dimensions yet when the skeleton is generated (e.g. images without explicit `width`/`height`, containers filled by JS). Elements with zero dimensions are normally skipped — these attributes let you force a skeleton block.
|
|
362
|
+
|
|
315
363
|
```html
|
|
316
364
|
<phantom-ui loading>
|
|
317
365
|
<div class="dashboard">
|
|
@@ -321,6 +369,7 @@ Two data attributes let you control which elements get shimmer treatment:
|
|
|
321
369
|
<span>2,847 users</span>
|
|
322
370
|
<span>42ms p99</span>
|
|
323
371
|
</div>
|
|
372
|
+
<img src="/hero.jpg" data-shimmer-width="600" data-shimmer-height="400" />
|
|
324
373
|
<div class="content">
|
|
325
374
|
<p>Each leaf element here gets its own shimmer block.</p>
|
|
326
375
|
</div>
|
package/dist/phantom-ui.cdn.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
"use strict";(()=>{var Rt=Object.defineProperty;var kt=Object.getOwnPropertyDescriptor;var
|
|
2
|
-
\f\r]`,
|
|
3
|
-
\f\r"'\`<>=]|("|')|))|$)`,"g"),pt=/'/g,mt=/"/g,vt=/^(?:script|style|textarea|title)$/i,et=r=>(t,...e)=>({_$litType$:r,strings:t,values:e}),j=et(1),re=et(2),oe=et(3),v=Symbol.for("lit-noChange"),u=Symbol.for("lit-nothing"),ft=new WeakMap,E=S.createTreeWalker(S,129);function yt(r,t){if(!tt(r)||!r.hasOwnProperty("raw"))throw Error("invalid template strings array");return ct!==void 0?ct.createHTML(t):t}var zt=(r,t)=>{let e=r.length-1,s=[],i,o=t===2?"<svg>":t===3?"<math>":"",n=R;for(let l=0;l<e;l++){let a=r[l],h,d,c=-1,g=0;for(;g<a.length&&(n.lastIndex=g,d=n.exec(a),d!==null);)g=n.lastIndex,n===R?d[1]==="!--"?n=dt:d[1]!==void 0?n=ut:d[2]!==void 0?(vt.test(d[2])&&(i=RegExp("</"+d[2],"g")),n=A):d[3]!==void 0&&(n=A):n===A?d[0]===">"?(n=i??R,c=-1):d[1]===void 0?c=-2:(c=n.lastIndex-d[2].length,h=d[1],n=d[3]===void 0?A:d[3]==='"'?mt:pt):n===mt||n===pt?n=A:n===dt||n===ut?n=R:(n=A,i=void 0);let y=n===A&&r[l+1].startsWith("/>")?" ":"";o+=n===R?a+Bt:c>=0?(s.push(h),a.slice(0,c)+gt+a.slice(c)+$+y):a+$+(c===-2?l:y)}return[yt(r,o+(r[e]||"<?>")+(t===2?"</svg>":t===3?"</math>":"")),s]},N=class r{constructor({strings:t,_$litType$:e},s){let i;this.parts=[];let o=0,n=0,l=t.length-1,a=this.parts,[h,d]=zt(t,e);if(this.el=r.createElement(h,s),E.currentNode=this.el.content,e===2||e===3){let c=this.el.content.firstChild;c.replaceWith(...c.childNodes)}for(;(i=E.nextNode())!==null&&a.length<l;){if(i.nodeType===1){if(i.hasAttributes())for(let c of i.getAttributeNames())if(c.endsWith(gt)){let g=d[n++],y=i.getAttribute(c).split($),H=/([.?@])?(.*)/.exec(g);a.push({type:1,index:o,name:H[2],strings:y,ctor:H[1]==="."?J:H[1]==="?"?X:H[1]==="@"?Y:C}),i.removeAttribute(c)}else c.startsWith($)&&(a.push({type:6,index:o}),i.removeAttribute(c));if(vt.test(i.tagName)){let c=i.textContent.split($),g=c.length-1;if(g>0){i.textContent=B?B.emptyScript:"";for(let y=0;y<g;y++)i.append(c[y],k()),E.nextNode(),a.push({type:2,index:++o});i.append(c[g],k())}}}else if(i.nodeType===8)if(i.data===_t)a.push({type:2,index:o});else{let c=-1;for(;(c=i.data.indexOf($,c+1))!==-1;)a.push({type:7,index:o}),c+=$.length-1}o++}}static createElement(t,e){let s=S.createElement("template");return s.innerHTML=t,s}};function x(r,t,e=r,s){if(t===v)return t;let i=s!==void 0?e._$Co?.[s]:e._$Cl,o=M(t)?void 0:t._$litDirective$;return i?.constructor!==o&&(i?._$AO?.(!1),o===void 0?i=void 0:(i=new o(r),i._$AT(r,e,s)),s!==void 0?(e._$Co??=[])[s]=i:e._$Cl=i),i!==void 0&&(t=x(r,i._$AS(r,t.values),i,s)),t}var F=class{constructor(t,e){this._$AV=[],this._$AN=void 0,this._$AD=t,this._$AM=e}get parentNode(){return this._$AM.parentNode}get _$AU(){return this._$AM._$AU}u(t){let{el:{content:e},parts:s}=this._$AD,i=(t?.creationScope??S).importNode(e,!0);E.currentNode=i;let o=E.nextNode(),n=0,l=0,a=s[0];for(;a!==void 0;){if(n===a.index){let h;a.type===2?h=new P(o,o.nextSibling,this,t):a.type===1?h=new a.ctor(o,a.name,a.strings,this,t):a.type===6&&(h=new Z(o,this,t)),this._$AV.push(h),a=s[++l]}n!==a?.index&&(o=E.nextNode(),n++)}return E.currentNode=S,i}p(t){let e=0;for(let s of this._$AV)s!==void 0&&(s.strings!==void 0?(s._$AI(t,s,e),e+=s.strings.length-2):s._$AI(t[e])),e++}},P=class r{get _$AU(){return this._$AM?._$AU??this._$Cv}constructor(t,e,s,i){this.type=2,this._$AH=u,this._$AN=void 0,this._$AA=t,this._$AB=e,this._$AM=s,this.options=i,this._$Cv=i?.isConnected??!0}get parentNode(){let t=this._$AA.parentNode,e=this._$AM;return e!==void 0&&t?.nodeType===11&&(t=e.parentNode),t}get startNode(){return this._$AA}get endNode(){return this._$AB}_$AI(t,e=this){t=x(this,t,e),M(t)?t===u||t==null||t===""?(this._$AH!==u&&this._$AR(),this._$AH=u):t!==this._$AH&&t!==v&&this._(t):t._$litType$!==void 0?this.$(t):t.nodeType!==void 0?this.T(t):jt(t)?this.k(t):this._(t)}O(t){return this._$AA.parentNode.insertBefore(t,this._$AB)}T(t){this._$AH!==t&&(this._$AR(),this._$AH=this.O(t))}_(t){this._$AH!==u&&M(this._$AH)?this._$AA.nextSibling.data=t:this.T(S.createTextNode(t)),this._$AH=t}$(t){let{values:e,_$litType$:s}=t,i=typeof s=="number"?this._$AC(t):(s.el===void 0&&(s.el=N.createElement(yt(s.h,s.h[0]),this.options)),s);if(this._$AH?._$AD===i)this._$AH.p(e);else{let o=new F(i,this),n=o.u(this.options);o.p(e),this.T(n),this._$AH=o}}_$AC(t){let e=ft.get(t.strings);return e===void 0&&ft.set(t.strings,e=new N(t)),e}k(t){tt(this._$AH)||(this._$AH=[],this._$AR());let e=this._$AH,s,i=0;for(let o of t)i===e.length?e.push(s=new r(this.O(k()),this.O(k()),this,this.options)):s=e[i],s._$AI(o),i++;i<e.length&&(this._$AR(s&&s._$AB.nextSibling,i),e.length=i)}_$AR(t=this._$AA.nextSibling,e){for(this._$AP?.(!1,!0,e);t!==this._$AB;){let s=ht(t).nextSibling;ht(t).remove(),t=s}}setConnected(t){this._$AM===void 0&&(this._$Cv=t,this._$AP?.(t))}},C=class{get tagName(){return this.element.tagName}get _$AU(){return this._$AM._$AU}constructor(t,e,s,i,o){this.type=1,this._$AH=u,this._$AN=void 0,this.element=t,this.name=e,this._$AM=i,this.options=o,s.length>2||s[0]!==""||s[1]!==""?(this._$AH=Array(s.length-1).fill(new String),this.strings=s):this._$AH=u}_$AI(t,e=this,s,i){let o=this.strings,n=!1;if(o===void 0)t=x(this,t,e,0),n=!M(t)||t!==this._$AH&&t!==v,n&&(this._$AH=t);else{let l=t,a,h;for(t=o[0],a=0;a<o.length-1;a++)h=x(this,l[s+a],e,a),h===v&&(h=this._$AH[a]),n||=!M(h)||h!==this._$AH[a],h===u?t=u:t!==u&&(t+=(h??"")+o[a+1]),this._$AH[a]=h}n&&!i&&this.j(t)}j(t){t===u?this.element.removeAttribute(this.name):this.element.setAttribute(this.name,t??"")}},J=class extends C{constructor(){super(...arguments),this.type=3}j(t){this.element[this.name]=t===u?void 0:t}},X=class extends C{constructor(){super(...arguments),this.type=4}j(t){this.element.toggleAttribute(this.name,!!t&&t!==u)}},Y=class extends C{constructor(t,e,s,i,o){super(t,e,s,i,o),this.type=5}_$AI(t,e=this){if((t=x(this,t,e,0)??u)===v)return;let s=this._$AH,i=t===u&&s!==u||t.capture!==s.capture||t.once!==s.once||t.passive!==s.passive,o=t!==u&&(s===u||i);i&&this.element.removeEventListener(this.name,this,s),o&&this.element.addEventListener(this.name,this,t),this._$AH=t}handleEvent(t){typeof this._$AH=="function"?this._$AH.call(this.options?.host??this.element,t):this._$AH.handleEvent(t)}},Z=class{constructor(t,e,s){this.element=t,this.type=6,this._$AN=void 0,this._$AM=e,this.options=s}get _$AU(){return this._$AM._$AU}_$AI(t){x(this,t)}};var qt=Q.litHtmlPolyfillSupport;qt?.(N,P),(Q.litHtmlVersions??=[]).push("3.3.2");var $t=(r,t,e)=>{let s=e?.renderBefore??t,i=s._$litPart$;if(i===void 0){let o=e?.renderBefore??null;s._$litPart$=i=new P(t.insertBefore(k(),o),o,void 0,e??{})}return i._$AI(r),i};var st=globalThis,b=class extends _{constructor(){super(...arguments),this.renderOptions={host:this},this._$Do=void 0}createRenderRoot(){let t=super.createRenderRoot();return this.renderOptions.renderBefore??=t.firstChild,t}update(t){let e=this.render();this.hasUpdated||(this.renderOptions.isConnected=this.isConnected),super.update(t),this._$Do=$t(e,this.renderRoot,this.renderOptions)}connectedCallback(){super.connectedCallback(),this._$Do?.setConnected(!0)}disconnectedCallback(){super.disconnectedCallback(),this._$Do?.setConnected(!1)}render(){return v}};b._$litElement$=!0,b.finalized=!0,st.litElementHydrateSupport?.({LitElement:b});var Vt=st.litElementPolyfillSupport;Vt?.({LitElement:b});(st.litElementVersions??=[]).push("4.2.2");var bt=r=>(t,e)=>{e!==void 0?e.addInitializer(()=>{customElements.define(r,t)}):customElements.define(r,t)};var Wt={attribute:!0,type:String,converter:O,reflect:!1,hasChanged:D},Gt=(r=Wt,t,e)=>{let{kind:s,metadata:i}=e,o=globalThis.litPropertyMetadata.get(i);if(o===void 0&&globalThis.litPropertyMetadata.set(i,o=new Map),s==="setter"&&((r=Object.create(r)).wrapped=!0),o.set(e.name,r),s==="accessor"){let{name:n}=e;return{set(l){let a=t.get.call(this);t.set.call(this,l),this.requestUpdate(n,a,r,!0,l)},init(l){return l!==void 0&&this.C(n,void 0,r,l),l}}}if(s==="setter"){let{name:n}=e;return function(l){let a=this[n];t.call(this,l),this.requestUpdate(n,a,r,!0,l)}}throw Error("Unsupported decorator location: "+s)};function f(r){return(t,e)=>typeof e=="object"?Gt(r,t,e):((s,i,o)=>{let n=i.hasOwnProperty(o);return i.constructor.createProperty(o,s),n?Object.getOwnPropertyDescriptor(i,o):void 0})(r,t,e)}function it(r){return f({...r,state:!0,attribute:!1})}var At={ATTRIBUTE:1,CHILD:2,PROPERTY:3,BOOLEAN_ATTRIBUTE:4,EVENT:5,ELEMENT:6},Et=r=>(...t)=>({_$litDirective$:r,values:t}),q=class{constructor(t){}get _$AU(){return this._$AM._$AU}_$AT(t,e,s){this._$Ct=t,this._$AM=e,this._$Ci=s}_$AS(t,e){return this.update(t,e)}update(t,e){return this.render(...e)}};var St="important",Kt=" !"+St,xt=Et(class extends q{constructor(r){if(super(r),r.type!==At.ATTRIBUTE||r.name!=="style"||r.strings?.length>2)throw Error("The `styleMap` directive must be used in the `style` attribute and must be the only part in the attribute.")}render(r){return Object.keys(r).reduce((t,e)=>{let s=r[e];return s==null?t:t+`${e=e.includes("-")?e:e.replace(/(?:^(webkit|moz|ms|o)|)(?=[A-Z])/g,"-$&").toLowerCase()}:${s};`},"")}update(r,[t]){let{style:e}=r.element;if(this.ft===void 0)return this.ft=new Set(Object.keys(t)),this.render(t);for(let s of this.ft)t[s]==null&&(this.ft.delete(s),s.includes("-")?e.removeProperty(s):e[s]=null);for(let s in t){let i=t[s];if(i!=null){this.ft.add(s);let o=typeof i=="string"&&i.endsWith(Kt);s.includes("-")||o?e.setProperty(s,o?i.slice(0,-11):i,o?St:""):e[s]=i}}return v}});var Ft=new Set(["IMG","SVG","VIDEO","CANVAS","IFRAME","INPUT","TEXTAREA","BUTTON","HR"]),Jt=new Set(["BR","WBR","HR"]);function Xt(r){if(Ft.has(r.tagName))return!0;for(let t of r.children)if(!Jt.has(t.tagName))return!1;return!0}function Yt(r){for(let t of r.childNodes)if(t.nodeType===Node.TEXT_NODE&&t.textContent?.trim())return!0;return!1}function Ct(r,t){let e=[];function s(i){let o=i.getBoundingClientRect();if(o.width===0||o.height===0||i.hasAttribute("data-shimmer-ignore"))return;if(i.hasAttribute("data-shimmer-no-children")||Xt(i)){let a=getComputedStyle(i).borderRadius;if((i.tagName==="TD"||i.tagName==="TH")&&Yt(i)){let h=document.createElement("span");h.style.visibility="hidden",h.style.position="absolute",h.textContent=i.textContent,i.appendChild(h);let d=h.getBoundingClientRect();i.removeChild(h),e.push({x:o.left-t.left,y:o.top-t.top,width:Math.min(d.width,o.width),height:o.height,tag:i.tagName.toLowerCase(),borderRadius:a==="0px"?"":a});return}e.push({x:o.left-t.left,y:o.top-t.top,width:o.width,height:o.height,tag:i.tagName.toLowerCase(),borderRadius:a==="0px"?"":a});return}for(let l of i.children)s(l)}return s(r),e}function wt(r,t){let e=null,s=new ResizeObserver(()=>{e!==null&&cancelAnimationFrame(e),e=requestAnimationFrame(()=>{e=null,t()})});return s.observe(r),s}var Tt=W`
|
|
1
|
+
"use strict";(()=>{var Rt=Object.defineProperty;var kt=Object.getOwnPropertyDescriptor;var g=(r,t,e,s)=>{for(var i=s>1?void 0:s?kt(t,e):t,o=r.length-1,n;o>=0;o--)(n=r[o])&&(i=(s?n(t,e,i):n(i))||i);return s&&i&&Rt(t,e,i),i};var U=globalThis,L=U.ShadowRoot&&(U.ShadyCSS===void 0||U.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,V=Symbol(),rt=new WeakMap,T=class{constructor(t,e,s){if(this._$cssResult$=!0,s!==V)throw Error("CSSResult is not constructable. Use `unsafeCSS` or `css` instead.");this.cssText=t,this.t=e}get styleSheet(){let t=this.o,e=this.t;if(L&&t===void 0){let s=e!==void 0&&e.length===1;s&&(t=rt.get(e)),t===void 0&&((this.o=t=new CSSStyleSheet).replaceSync(this.cssText),s&&rt.set(e,t))}return t}toString(){return this.cssText}},ot=r=>new T(typeof r=="string"?r:r+"",void 0,V),W=(r,...t)=>{let e=r.length===1?r[0]:t.reduce((s,i,o)=>s+(n=>{if(n._$cssResult$===!0)return n.cssText;if(typeof n=="number")return n;throw Error("Value passed to 'css' function must be a 'css' function result: "+n+". Use 'unsafeCSS' to pass non-literal values, but take care to ensure page security.")})(i)+r[o+1],r[0]);return new T(e,r,V)},nt=(r,t)=>{if(L)r.adoptedStyleSheets=t.map(e=>e instanceof CSSStyleSheet?e:e.styleSheet);else for(let e of t){let s=document.createElement("style"),i=U.litNonce;i!==void 0&&s.setAttribute("nonce",i),s.textContent=e.cssText,r.appendChild(s)}},G=L?r=>r:r=>r instanceof CSSStyleSheet?(t=>{let e="";for(let s of t.cssRules)e+=s.cssText;return ot(e)})(r):r;var{is:Mt,defineProperty:Nt,getOwnPropertyDescriptor:Pt,getOwnPropertyNames:Ht,getOwnPropertySymbols:Ut,getPrototypeOf:Lt}=Object,I=globalThis,at=I.trustedTypes,It=at?at.emptyScript:"",Dt=I.reactiveElementPolyfillSupport,O=(r,t)=>r,R={toAttribute(r,t){switch(t){case Boolean:r=r?It:null;break;case Object:case Array:r=r==null?r:JSON.stringify(r)}return r},fromAttribute(r,t){let e=r;switch(t){case Boolean:e=r!==null;break;case Number:e=r===null?null:Number(r);break;case Object:case Array:try{e=JSON.parse(r)}catch{e=null}}return e}},D=(r,t)=>!Mt(r,t),lt={attribute:!0,type:String,converter:R,reflect:!1,useDefault:!1,hasChanged:D};Symbol.metadata??=Symbol("metadata"),I.litPropertyMetadata??=new WeakMap;var v=class extends HTMLElement{static addInitializer(t){this._$Ei(),(this.l??=[]).push(t)}static get observedAttributes(){return this.finalize(),this._$Eh&&[...this._$Eh.keys()]}static createProperty(t,e=lt){if(e.state&&(e.attribute=!1),this._$Ei(),this.prototype.hasOwnProperty(t)&&((e=Object.create(e)).wrapped=!0),this.elementProperties.set(t,e),!e.noAccessor){let s=Symbol(),i=this.getPropertyDescriptor(t,s,e);i!==void 0&&Nt(this.prototype,t,i)}}static getPropertyDescriptor(t,e,s){let{get:i,set:o}=Pt(this.prototype,t)??{get(){return this[e]},set(n){this[e]=n}};return{get:i,set(n){let l=i?.call(this);o?.call(this,n),this.requestUpdate(t,l,s)},configurable:!0,enumerable:!0}}static getPropertyOptions(t){return this.elementProperties.get(t)??lt}static _$Ei(){if(this.hasOwnProperty(O("elementProperties")))return;let t=Lt(this);t.finalize(),t.l!==void 0&&(this.l=[...t.l]),this.elementProperties=new Map(t.elementProperties)}static finalize(){if(this.hasOwnProperty(O("finalized")))return;if(this.finalized=!0,this._$Ei(),this.hasOwnProperty(O("properties"))){let e=this.properties,s=[...Ht(e),...Ut(e)];for(let i of s)this.createProperty(i,e[i])}let t=this[Symbol.metadata];if(t!==null){let e=litPropertyMetadata.get(t);if(e!==void 0)for(let[s,i]of e)this.elementProperties.set(s,i)}this._$Eh=new Map;for(let[e,s]of this.elementProperties){let i=this._$Eu(e,s);i!==void 0&&this._$Eh.set(i,e)}this.elementStyles=this.finalizeStyles(this.styles)}static finalizeStyles(t){let e=[];if(Array.isArray(t)){let s=new Set(t.flat(1/0).reverse());for(let i of s)e.unshift(G(i))}else t!==void 0&&e.push(G(t));return e}static _$Eu(t,e){let s=e.attribute;return s===!1?void 0:typeof s=="string"?s:typeof t=="string"?t.toLowerCase():void 0}constructor(){super(),this._$Ep=void 0,this.isUpdatePending=!1,this.hasUpdated=!1,this._$Em=null,this._$Ev()}_$Ev(){this._$ES=new Promise(t=>this.enableUpdating=t),this._$AL=new Map,this._$E_(),this.requestUpdate(),this.constructor.l?.forEach(t=>t(this))}addController(t){(this._$EO??=new Set).add(t),this.renderRoot!==void 0&&this.isConnected&&t.hostConnected?.()}removeController(t){this._$EO?.delete(t)}_$E_(){let t=new Map,e=this.constructor.elementProperties;for(let s of e.keys())this.hasOwnProperty(s)&&(t.set(s,this[s]),delete this[s]);t.size>0&&(this._$Ep=t)}createRenderRoot(){let t=this.shadowRoot??this.attachShadow(this.constructor.shadowRootOptions);return nt(t,this.constructor.elementStyles),t}connectedCallback(){this.renderRoot??=this.createRenderRoot(),this.enableUpdating(!0),this._$EO?.forEach(t=>t.hostConnected?.())}enableUpdating(t){}disconnectedCallback(){this._$EO?.forEach(t=>t.hostDisconnected?.())}attributeChangedCallback(t,e,s){this._$AK(t,s)}_$ET(t,e){let s=this.constructor.elementProperties.get(t),i=this.constructor._$Eu(t,s);if(i!==void 0&&s.reflect===!0){let o=(s.converter?.toAttribute!==void 0?s.converter:R).toAttribute(e,s.type);this._$Em=t,o==null?this.removeAttribute(i):this.setAttribute(i,o),this._$Em=null}}_$AK(t,e){let s=this.constructor,i=s._$Eh.get(t);if(i!==void 0&&this._$Em!==i){let o=s.getPropertyOptions(i),n=typeof o.converter=="function"?{fromAttribute:o.converter}:o.converter?.fromAttribute!==void 0?o.converter:R;this._$Em=i;let l=n.fromAttribute(e,o.type);this[i]=l??this._$Ej?.get(i)??l,this._$Em=null}}requestUpdate(t,e,s,i=!1,o){if(t!==void 0){let n=this.constructor;if(i===!1&&(o=this[t]),s??=n.getPropertyOptions(t),!((s.hasChanged??D)(o,e)||s.useDefault&&s.reflect&&o===this._$Ej?.get(t)&&!this.hasAttribute(n._$Eu(t,s))))return;this.C(t,e,s)}this.isUpdatePending===!1&&(this._$ES=this._$EP())}C(t,e,{useDefault:s,reflect:i,wrapped:o},n){s&&!(this._$Ej??=new Map).has(t)&&(this._$Ej.set(t,n??e??this[t]),o!==!0||n!==void 0)||(this._$AL.has(t)||(this.hasUpdated||s||(e=void 0),this._$AL.set(t,e)),i===!0&&this._$Em!==t&&(this._$Eq??=new Set).add(t))}async _$EP(){this.isUpdatePending=!0;try{await this._$ES}catch(e){Promise.reject(e)}let t=this.scheduleUpdate();return t!=null&&await t,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){if(!this.isUpdatePending)return;if(!this.hasUpdated){if(this.renderRoot??=this.createRenderRoot(),this._$Ep){for(let[i,o]of this._$Ep)this[i]=o;this._$Ep=void 0}let s=this.constructor.elementProperties;if(s.size>0)for(let[i,o]of s){let{wrapped:n}=o,l=this[i];n!==!0||this._$AL.has(i)||l===void 0||this.C(i,void 0,o,l)}}let t=!1,e=this._$AL;try{t=this.shouldUpdate(e),t?(this.willUpdate(e),this._$EO?.forEach(s=>s.hostUpdate?.()),this.update(e)):this._$EM()}catch(s){throw t=!1,this._$EM(),s}t&&this._$AE(e)}willUpdate(t){}_$AE(t){this._$EO?.forEach(e=>e.hostUpdated?.()),this.hasUpdated||(this.hasUpdated=!0,this.firstUpdated(t)),this.updated(t)}_$EM(){this._$AL=new Map,this.isUpdatePending=!1}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$ES}shouldUpdate(t){return!0}update(t){this._$Eq&&=this._$Eq.forEach(e=>this._$ET(e,this[e])),this._$EM()}updated(t){}firstUpdated(t){}};v.elementStyles=[],v.shadowRootOptions={mode:"open"},v[O("elementProperties")]=new Map,v[O("finalized")]=new Map,Dt?.({ReactiveElement:v}),(I.reactiveElementVersions??=[]).push("2.1.2");var Q=globalThis,ht=r=>r,B=Q.trustedTypes,ct=B?B.createPolicy("lit-html",{createHTML:r=>r}):void 0,gt="$lit$",$=`lit$${Math.random().toFixed(9).slice(2)}$`,_t="?"+$,Bt=`<${_t}>`,S=document,M=()=>S.createComment(""),N=r=>r===null||typeof r!="object"&&typeof r!="function",tt=Array.isArray,jt=r=>tt(r)||typeof r?.[Symbol.iterator]=="function",K=`[
|
|
2
|
+
\f\r]`,k=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,dt=/-->/g,ut=/>/g,A=RegExp(`>|${K}(?:([^\\s"'>=/]+)(${K}*=${K}*(?:[^
|
|
3
|
+
\f\r"'\`<>=]|("|')|))|$)`,"g"),pt=/'/g,mt=/"/g,vt=/^(?:script|style|textarea|title)$/i,et=r=>(t,...e)=>({_$litType$:r,strings:t,values:e}),j=et(1),re=et(2),oe=et(3),y=Symbol.for("lit-noChange"),u=Symbol.for("lit-nothing"),ft=new WeakMap,E=S.createTreeWalker(S,129);function yt(r,t){if(!tt(r)||!r.hasOwnProperty("raw"))throw Error("invalid template strings array");return ct!==void 0?ct.createHTML(t):t}var zt=(r,t)=>{let e=r.length-1,s=[],i,o=t===2?"<svg>":t===3?"<math>":"",n=k;for(let l=0;l<e;l++){let a=r[l],h,d,c=-1,f=0;for(;f<a.length&&(n.lastIndex=f,d=n.exec(a),d!==null);)f=n.lastIndex,n===k?d[1]==="!--"?n=dt:d[1]!==void 0?n=ut:d[2]!==void 0?(vt.test(d[2])&&(i=RegExp("</"+d[2],"g")),n=A):d[3]!==void 0&&(n=A):n===A?d[0]===">"?(n=i??k,c=-1):d[1]===void 0?c=-2:(c=n.lastIndex-d[2].length,h=d[1],n=d[3]===void 0?A:d[3]==='"'?mt:pt):n===mt||n===pt?n=A:n===dt||n===ut?n=k:(n=A,i=void 0);let m=n===A&&r[l+1].startsWith("/>")?" ":"";o+=n===k?a+Bt:c>=0?(s.push(h),a.slice(0,c)+gt+a.slice(c)+$+m):a+$+(c===-2?l:m)}return[yt(r,o+(r[e]||"<?>")+(t===2?"</svg>":t===3?"</math>":"")),s]},P=class r{constructor({strings:t,_$litType$:e},s){let i;this.parts=[];let o=0,n=0,l=t.length-1,a=this.parts,[h,d]=zt(t,e);if(this.el=r.createElement(h,s),E.currentNode=this.el.content,e===2||e===3){let c=this.el.content.firstChild;c.replaceWith(...c.childNodes)}for(;(i=E.nextNode())!==null&&a.length<l;){if(i.nodeType===1){if(i.hasAttributes())for(let c of i.getAttributeNames())if(c.endsWith(gt)){let f=d[n++],m=i.getAttribute(c).split($),x=/([.?@])?(.*)/.exec(f);a.push({type:1,index:o,name:x[2],strings:m,ctor:x[1]==="."?J:x[1]==="?"?X:x[1]==="@"?Y:C}),i.removeAttribute(c)}else c.startsWith($)&&(a.push({type:6,index:o}),i.removeAttribute(c));if(vt.test(i.tagName)){let c=i.textContent.split($),f=c.length-1;if(f>0){i.textContent=B?B.emptyScript:"";for(let m=0;m<f;m++)i.append(c[m],M()),E.nextNode(),a.push({type:2,index:++o});i.append(c[f],M())}}}else if(i.nodeType===8)if(i.data===_t)a.push({type:2,index:o});else{let c=-1;for(;(c=i.data.indexOf($,c+1))!==-1;)a.push({type:7,index:o}),c+=$.length-1}o++}}static createElement(t,e){let s=S.createElement("template");return s.innerHTML=t,s}};function w(r,t,e=r,s){if(t===y)return t;let i=s!==void 0?e._$Co?.[s]:e._$Cl,o=N(t)?void 0:t._$litDirective$;return i?.constructor!==o&&(i?._$AO?.(!1),o===void 0?i=void 0:(i=new o(r),i._$AT(r,e,s)),s!==void 0?(e._$Co??=[])[s]=i:e._$Cl=i),i!==void 0&&(t=w(r,i._$AS(r,t.values),i,s)),t}var F=class{constructor(t,e){this._$AV=[],this._$AN=void 0,this._$AD=t,this._$AM=e}get parentNode(){return this._$AM.parentNode}get _$AU(){return this._$AM._$AU}u(t){let{el:{content:e},parts:s}=this._$AD,i=(t?.creationScope??S).importNode(e,!0);E.currentNode=i;let o=E.nextNode(),n=0,l=0,a=s[0];for(;a!==void 0;){if(n===a.index){let h;a.type===2?h=new H(o,o.nextSibling,this,t):a.type===1?h=new a.ctor(o,a.name,a.strings,this,t):a.type===6&&(h=new Z(o,this,t)),this._$AV.push(h),a=s[++l]}n!==a?.index&&(o=E.nextNode(),n++)}return E.currentNode=S,i}p(t){let e=0;for(let s of this._$AV)s!==void 0&&(s.strings!==void 0?(s._$AI(t,s,e),e+=s.strings.length-2):s._$AI(t[e])),e++}},H=class r{get _$AU(){return this._$AM?._$AU??this._$Cv}constructor(t,e,s,i){this.type=2,this._$AH=u,this._$AN=void 0,this._$AA=t,this._$AB=e,this._$AM=s,this.options=i,this._$Cv=i?.isConnected??!0}get parentNode(){let t=this._$AA.parentNode,e=this._$AM;return e!==void 0&&t?.nodeType===11&&(t=e.parentNode),t}get startNode(){return this._$AA}get endNode(){return this._$AB}_$AI(t,e=this){t=w(this,t,e),N(t)?t===u||t==null||t===""?(this._$AH!==u&&this._$AR(),this._$AH=u):t!==this._$AH&&t!==y&&this._(t):t._$litType$!==void 0?this.$(t):t.nodeType!==void 0?this.T(t):jt(t)?this.k(t):this._(t)}O(t){return this._$AA.parentNode.insertBefore(t,this._$AB)}T(t){this._$AH!==t&&(this._$AR(),this._$AH=this.O(t))}_(t){this._$AH!==u&&N(this._$AH)?this._$AA.nextSibling.data=t:this.T(S.createTextNode(t)),this._$AH=t}$(t){let{values:e,_$litType$:s}=t,i=typeof s=="number"?this._$AC(t):(s.el===void 0&&(s.el=P.createElement(yt(s.h,s.h[0]),this.options)),s);if(this._$AH?._$AD===i)this._$AH.p(e);else{let o=new F(i,this),n=o.u(this.options);o.p(e),this.T(n),this._$AH=o}}_$AC(t){let e=ft.get(t.strings);return e===void 0&&ft.set(t.strings,e=new P(t)),e}k(t){tt(this._$AH)||(this._$AH=[],this._$AR());let e=this._$AH,s,i=0;for(let o of t)i===e.length?e.push(s=new r(this.O(M()),this.O(M()),this,this.options)):s=e[i],s._$AI(o),i++;i<e.length&&(this._$AR(s&&s._$AB.nextSibling,i),e.length=i)}_$AR(t=this._$AA.nextSibling,e){for(this._$AP?.(!1,!0,e);t!==this._$AB;){let s=ht(t).nextSibling;ht(t).remove(),t=s}}setConnected(t){this._$AM===void 0&&(this._$Cv=t,this._$AP?.(t))}},C=class{get tagName(){return this.element.tagName}get _$AU(){return this._$AM._$AU}constructor(t,e,s,i,o){this.type=1,this._$AH=u,this._$AN=void 0,this.element=t,this.name=e,this._$AM=i,this.options=o,s.length>2||s[0]!==""||s[1]!==""?(this._$AH=Array(s.length-1).fill(new String),this.strings=s):this._$AH=u}_$AI(t,e=this,s,i){let o=this.strings,n=!1;if(o===void 0)t=w(this,t,e,0),n=!N(t)||t!==this._$AH&&t!==y,n&&(this._$AH=t);else{let l=t,a,h;for(t=o[0],a=0;a<o.length-1;a++)h=w(this,l[s+a],e,a),h===y&&(h=this._$AH[a]),n||=!N(h)||h!==this._$AH[a],h===u?t=u:t!==u&&(t+=(h??"")+o[a+1]),this._$AH[a]=h}n&&!i&&this.j(t)}j(t){t===u?this.element.removeAttribute(this.name):this.element.setAttribute(this.name,t??"")}},J=class extends C{constructor(){super(...arguments),this.type=3}j(t){this.element[this.name]=t===u?void 0:t}},X=class extends C{constructor(){super(...arguments),this.type=4}j(t){this.element.toggleAttribute(this.name,!!t&&t!==u)}},Y=class extends C{constructor(t,e,s,i,o){super(t,e,s,i,o),this.type=5}_$AI(t,e=this){if((t=w(this,t,e,0)??u)===y)return;let s=this._$AH,i=t===u&&s!==u||t.capture!==s.capture||t.once!==s.once||t.passive!==s.passive,o=t!==u&&(s===u||i);i&&this.element.removeEventListener(this.name,this,s),o&&this.element.addEventListener(this.name,this,t),this._$AH=t}handleEvent(t){typeof this._$AH=="function"?this._$AH.call(this.options?.host??this.element,t):this._$AH.handleEvent(t)}},Z=class{constructor(t,e,s){this.element=t,this.type=6,this._$AN=void 0,this._$AM=e,this.options=s}get _$AU(){return this._$AM._$AU}_$AI(t){w(this,t)}};var qt=Q.litHtmlPolyfillSupport;qt?.(P,H),(Q.litHtmlVersions??=[]).push("3.3.2");var $t=(r,t,e)=>{let s=e?.renderBefore??t,i=s._$litPart$;if(i===void 0){let o=e?.renderBefore??null;s._$litPart$=i=new H(t.insertBefore(M(),o),o,void 0,e??{})}return i._$AI(r),i};var st=globalThis,b=class extends v{constructor(){super(...arguments),this.renderOptions={host:this},this._$Do=void 0}createRenderRoot(){let t=super.createRenderRoot();return this.renderOptions.renderBefore??=t.firstChild,t}update(t){let e=this.render();this.hasUpdated||(this.renderOptions.isConnected=this.isConnected),super.update(t),this._$Do=$t(e,this.renderRoot,this.renderOptions)}connectedCallback(){super.connectedCallback(),this._$Do?.setConnected(!0)}disconnectedCallback(){super.disconnectedCallback(),this._$Do?.setConnected(!1)}render(){return y}};b._$litElement$=!0,b.finalized=!0,st.litElementHydrateSupport?.({LitElement:b});var Vt=st.litElementPolyfillSupport;Vt?.({LitElement:b});(st.litElementVersions??=[]).push("4.2.2");var bt=r=>(t,e)=>{e!==void 0?e.addInitializer(()=>{customElements.define(r,t)}):customElements.define(r,t)};var Wt={attribute:!0,type:String,converter:R,reflect:!1,hasChanged:D},Gt=(r=Wt,t,e)=>{let{kind:s,metadata:i}=e,o=globalThis.litPropertyMetadata.get(i);if(o===void 0&&globalThis.litPropertyMetadata.set(i,o=new Map),s==="setter"&&((r=Object.create(r)).wrapped=!0),o.set(e.name,r),s==="accessor"){let{name:n}=e;return{set(l){let a=t.get.call(this);t.set.call(this,l),this.requestUpdate(n,a,r,!0,l)},init(l){return l!==void 0&&this.C(n,void 0,r,l),l}}}if(s==="setter"){let{name:n}=e;return function(l){let a=this[n];t.call(this,l),this.requestUpdate(n,a,r,!0,l)}}throw Error("Unsupported decorator location: "+s)};function _(r){return(t,e)=>typeof e=="object"?Gt(r,t,e):((s,i,o)=>{let n=i.hasOwnProperty(o);return i.constructor.createProperty(o,s),n?Object.getOwnPropertyDescriptor(i,o):void 0})(r,t,e)}function it(r){return _({...r,state:!0,attribute:!1})}var At={ATTRIBUTE:1,CHILD:2,PROPERTY:3,BOOLEAN_ATTRIBUTE:4,EVENT:5,ELEMENT:6},Et=r=>(...t)=>({_$litDirective$:r,values:t}),q=class{constructor(t){}get _$AU(){return this._$AM._$AU}_$AT(t,e,s){this._$Ct=t,this._$AM=e,this._$Ci=s}_$AS(t,e){return this.update(t,e)}update(t,e){return this.render(...e)}};var St="important",Kt=" !"+St,xt=Et(class extends q{constructor(r){if(super(r),r.type!==At.ATTRIBUTE||r.name!=="style"||r.strings?.length>2)throw Error("The `styleMap` directive must be used in the `style` attribute and must be the only part in the attribute.")}render(r){return Object.keys(r).reduce((t,e)=>{let s=r[e];return s==null?t:t+`${e=e.includes("-")?e:e.replace(/(?:^(webkit|moz|ms|o)|)(?=[A-Z])/g,"-$&").toLowerCase()}:${s};`},"")}update(r,[t]){let{style:e}=r.element;if(this.ft===void 0)return this.ft=new Set(Object.keys(t)),this.render(t);for(let s of this.ft)t[s]==null&&(this.ft.delete(s),s.includes("-")?e.removeProperty(s):e[s]=null);for(let s in t){let i=t[s];if(i!=null){this.ft.add(s);let o=typeof i=="string"&&i.endsWith(Kt);s.includes("-")||o?e.setProperty(s,o?i.slice(0,-11):i,o?St:""):e[s]=i}}return y}});var Ft=new Set(["IMG","SVG","VIDEO","CANVAS","IFRAME","INPUT","TEXTAREA","BUTTON","HR"]),Jt=new Set(["BR","WBR","HR"]);function Xt(r){if(Ft.has(r.tagName))return!0;for(let t of r.children)if(!Jt.has(t.tagName))return!1;return!0}function Yt(r){for(let t of r.childNodes)if(t.nodeType===Node.TEXT_NODE&&t.textContent?.trim())return!0;return!1}function wt(r,t){let e=[];function s(i){let o=i.getBoundingClientRect(),n=Number(i.getAttribute("data-shimmer-width"))||0,l=Number(i.getAttribute("data-shimmer-height"))||0,a=n||o.width,h=l||o.height;if(a===0||h===0||i.hasAttribute("data-shimmer-ignore"))return;if(i.hasAttribute("data-shimmer-no-children")||Xt(i)){let f=getComputedStyle(i).borderRadius;if((i.tagName==="TD"||i.tagName==="TH")&&Yt(i)&&!n){let m=document.createElement("span");m.style.visibility="hidden",m.style.position="absolute",m.textContent=i.textContent,i.appendChild(m);let x=m.getBoundingClientRect();i.removeChild(m),e.push({x:o.left-t.left,y:o.top-t.top,width:Math.min(x.width,o.width),height:h,tag:i.tagName.toLowerCase(),borderRadius:f==="0px"?"":f});return}e.push({x:o.left-t.left,y:o.top-t.top,width:a,height:h,tag:i.tagName.toLowerCase(),borderRadius:f==="0px"?"":f});return}for(let c of i.children)s(c)}return s(r),e}function Ct(r,t){let e=null,s=new ResizeObserver(()=>{e!==null&&cancelAnimationFrame(e),e=requestAnimationFrame(()=>{e=null,t()})});return s.observe(r),s}var Tt=W`
|
|
4
4
|
:host {
|
|
5
5
|
display: block;
|
|
6
6
|
position: relative;
|
|
@@ -19,7 +19,9 @@
|
|
|
19
19
|
:host([loading]) ::slotted(img),
|
|
20
20
|
:host([loading]) ::slotted(svg),
|
|
21
21
|
:host([loading]) ::slotted(video),
|
|
22
|
-
:host([loading]) ::slotted(canvas)
|
|
22
|
+
:host([loading]) ::slotted(canvas),
|
|
23
|
+
:host([loading]) ::slotted(button),
|
|
24
|
+
:host([loading]) ::slotted([role="button"]) {
|
|
23
25
|
opacity: 0 !important;
|
|
24
26
|
}
|
|
25
27
|
|
|
@@ -117,7 +119,9 @@
|
|
|
117
119
|
phantom-ui[loading] img,
|
|
118
120
|
phantom-ui[loading] svg,
|
|
119
121
|
phantom-ui[loading] video,
|
|
120
|
-
phantom-ui[loading] canvas
|
|
122
|
+
phantom-ui[loading] canvas,
|
|
123
|
+
phantom-ui[loading] button,
|
|
124
|
+
phantom-ui[loading] [role="button"] {
|
|
121
125
|
opacity: 0 !important;
|
|
122
126
|
}
|
|
123
127
|
`,document.head.appendChild(r)}var p=class extends b{constructor(){super(...arguments);this.loading=!1;this.shimmerColor="rgba(128, 128, 128, 0.3)";this.backgroundColor="rgba(128, 128, 128, 0.2)";this.duration=1.5;this.fallbackRadius=4;this.animation="shimmer";this.stagger=0;this.reveal=0;this.count=1;this.countGap=0;this._blocks=[];this._revealing=!1;this._resizeObserver=null;this._mutationObserver=null;this._loadHandler=null;this._measureScheduled=!1;this._revealTimeout=null}connectedCallback(){super.connectedCallback(),Zt()}disconnectedCallback(){super.disconnectedCallback(),this._teardownObservers(),this._clearRevealTimeout()}willUpdate(e){e.has("loading")&&!this.loading&&this.reveal>0&&this._blocks.length>0&&(this._revealing=!0)}updated(e){(e.has("count")||e.has("countGap"))&&this.loading&&this._scheduleMeasure(),e.has("loading")&&(this.setAttribute("aria-busy",String(this.loading)),this.loading?(this._revealing=!1,this._clearRevealTimeout(),this._scheduleMeasure(),this._setupObservers()):this._revealing?(this._teardownObservers(),this._revealTimeout=setTimeout(()=>{this._revealing=!1,this._blocks=[],this._revealTimeout=null,this.style.minHeight=""},this.reveal*1e3)):(this._blocks=[],this._teardownObservers(),this.style.minHeight=""))}render(){let e=xt({"--shimmer-color":this.shimmerColor,"--shimmer-duration":`${this.duration}s`,"--shimmer-bg":this.backgroundColor,"--reveal-duration":`${this.reveal}s`}),s=this.loading||this._revealing;return j`
|
|
@@ -131,7 +135,7 @@
|
|
|
131
135
|
${this._renderBlocks()}
|
|
132
136
|
</div>
|
|
133
137
|
`:""}
|
|
134
|
-
`}_scheduleMeasure(){this._measureScheduled||(this._measureScheduled=!0,requestAnimationFrame(()=>{this._measureScheduled=!1,this._measure()}))}_measure(){if(!this.loading)return;let e=this.getBoundingClientRect();if(e.width===0||e.height===0)return;let s=this.shadowRoot?.querySelector("slot");if(!s)return;let i=s.assignedElements({flatten:!0}),o=[];for(let n of i){let l=
|
|
138
|
+
`}_scheduleMeasure(){this._measureScheduled||(this._measureScheduled=!0,requestAnimationFrame(()=>{this._measureScheduled=!1,this._measure()}))}_measure(){if(!this.loading)return;let e=this.getBoundingClientRect();if(e.width===0||e.height===0)return;let s=this.shadowRoot?.querySelector("slot");if(!s)return;let i=s.assignedElements({flatten:!0}),o=[];for(let n of i){let l=wt(n,e);o.push(...l)}if(this.count>1&&o.length>0){let n=0;for(let h of i){let d=h.getBoundingClientRect();n=Math.max(n,d.bottom-e.top)}let l=[...o];for(let h=1;h<this.count;h++)for(let d of l)o.push({...d,y:d.y+h*(n+this.countGap)});let a=this.count*n+(this.count-1)*this.countGap;this.style.minHeight=`${a}px`}else this.style.minHeight="";this._blocks=o}_setupObservers(){this._teardownObservers(),this._resizeObserver=Ct(this,()=>{this._scheduleMeasure()}),this._mutationObserver=new MutationObserver(()=>{this._scheduleMeasure()}),this._mutationObserver.observe(this,{childList:!0,subtree:!0,attributes:!0}),this._loadHandler=()=>this._scheduleMeasure(),this.addEventListener("load",this._loadHandler,!0)}_teardownObservers(){this._resizeObserver&&(this._resizeObserver.disconnect(),this._resizeObserver=null),this._mutationObserver&&(this._mutationObserver.disconnect(),this._mutationObserver=null),this._loadHandler&&(this.removeEventListener("load",this._loadHandler,!0),this._loadHandler=null)}_clearRevealTimeout(){this._revealTimeout!==null&&(clearTimeout(this._revealTimeout),this._revealTimeout=null)}_renderBlocks(){return this._blocks.map((e,s)=>{let i=e.borderRadius||`${this.fallbackRadius}px`,o=this.stagger,n=o>0?`animation-delay: ${s*o}s;`:"";return j`
|
|
135
139
|
<div
|
|
136
140
|
class="shimmer-block"
|
|
137
141
|
style="
|
|
@@ -144,7 +148,7 @@
|
|
|
144
148
|
${n}
|
|
145
149
|
"
|
|
146
150
|
></div>
|
|
147
|
-
`})}};p.styles=Tt,
|
|
151
|
+
`})}};p.styles=Tt,g([_({type:Boolean,reflect:!0})],p.prototype,"loading",2),g([_({attribute:"shimmer-color"})],p.prototype,"shimmerColor",2),g([_({attribute:"background-color"})],p.prototype,"backgroundColor",2),g([_({type:Number})],p.prototype,"duration",2),g([_({type:Number,attribute:"fallback-radius"})],p.prototype,"fallbackRadius",2),g([_({reflect:!0})],p.prototype,"animation",2),g([_({type:Number})],p.prototype,"stagger",2),g([_({type:Number})],p.prototype,"reveal",2),g([_({type:Number,converter:e=>Math.max(1,Math.round(Number(e)||1))})],p.prototype,"count",2),g([_({type:Number,attribute:"count-gap",converter:e=>Math.max(0,Number(e)||0)})],p.prototype,"countGap",2),g([it()],p.prototype,"_blocks",2),g([it()],p.prototype,"_revealing",2),p=g([bt("phantom-ui")],p);})();
|
|
148
152
|
/*! Bundled license information:
|
|
149
153
|
|
|
150
154
|
@lit/reactive-element/css-tag.js:
|
package/dist/phantom-ui.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var
|
|
1
|
+
var x=Object.defineProperty;var O=Object.getOwnPropertyDescriptor;var l=(n,r,e,s)=>{for(var t=s>1?void 0:s?O(r,e):r,i=n.length-1,a;i>=0;i--)(a=n[i])&&(t=(s?a(r,e,t):a(t))||t);return s&&t&&x(r,e,t),t};import{LitElement as N,html as v}from"lit";import{customElement as M,property as u,state as k}from"lit/decorators.js";import{styleMap as H}from"lit/directives/style-map.js";var R=new Set(["IMG","SVG","VIDEO","CANVAS","IFRAME","INPUT","TEXTAREA","BUTTON","HR"]),T=new Set(["BR","WBR","HR"]);function C(n){if(R.has(n.tagName))return!0;for(let r of n.children)if(!T.has(r.tagName))return!1;return!0}function S(n){for(let r of n.childNodes)if(r.nodeType===Node.TEXT_NODE&&r.textContent?.trim())return!0;return!1}function f(n,r){let e=[];function s(t){let i=t.getBoundingClientRect(),a=Number(t.getAttribute("data-shimmer-width"))||0,d=Number(t.getAttribute("data-shimmer-height"))||0,p=a||i.width,m=d||i.height;if(p===0||m===0||t.hasAttribute("data-shimmer-ignore"))return;if(t.hasAttribute("data-shimmer-no-children")||C(t)){let b=getComputedStyle(t).borderRadius;if((t.tagName==="TD"||t.tagName==="TH")&&S(t)&&!a){let h=document.createElement("span");h.style.visibility="hidden",h.style.position="absolute",h.textContent=t.textContent,t.appendChild(h);let E=h.getBoundingClientRect();t.removeChild(h),e.push({x:i.left-r.left,y:i.top-r.top,width:Math.min(E.width,i.width),height:m,tag:t.tagName.toLowerCase(),borderRadius:b==="0px"?"":b});return}e.push({x:i.left-r.left,y:i.top-r.top,width:p,height:m,tag:t.tagName.toLowerCase(),borderRadius:b==="0px"?"":b});return}for(let g of t.children)s(g)}return s(n),e}function y(n,r){let e=null,s=new ResizeObserver(()=>{e!==null&&cancelAnimationFrame(e),e=requestAnimationFrame(()=>{e=null,r()})});return s.observe(n),s}import{css as A}from"lit";var _=A`
|
|
2
2
|
:host {
|
|
3
3
|
display: block;
|
|
4
4
|
position: relative;
|
|
@@ -17,7 +17,9 @@ var _=Object.defineProperty;var k=Object.getOwnPropertyDescriptor;var a=(n,r,e,s
|
|
|
17
17
|
:host([loading]) ::slotted(img),
|
|
18
18
|
:host([loading]) ::slotted(svg),
|
|
19
19
|
:host([loading]) ::slotted(video),
|
|
20
|
-
:host([loading]) ::slotted(canvas)
|
|
20
|
+
:host([loading]) ::slotted(canvas),
|
|
21
|
+
:host([loading]) ::slotted(button),
|
|
22
|
+
:host([loading]) ::slotted([role="button"]) {
|
|
21
23
|
opacity: 0 !important;
|
|
22
24
|
}
|
|
23
25
|
|
|
@@ -106,7 +108,7 @@ var _=Object.defineProperty;var k=Object.getOwnPropertyDescriptor;var a=(n,r,e,s
|
|
|
106
108
|
:host([animation="solid"]) .shimmer-block::after {
|
|
107
109
|
display: none;
|
|
108
110
|
}
|
|
109
|
-
`;var
|
|
111
|
+
`;var w="phantom-ui-loading-styles";function I(){if(document.getElementById(w))return;let n=document.createElement("style");n.id=w,n.textContent=`
|
|
110
112
|
phantom-ui[loading] * {
|
|
111
113
|
-webkit-text-fill-color: transparent !important;
|
|
112
114
|
pointer-events: none;
|
|
@@ -115,12 +117,14 @@ var _=Object.defineProperty;var k=Object.getOwnPropertyDescriptor;var a=(n,r,e,s
|
|
|
115
117
|
phantom-ui[loading] img,
|
|
116
118
|
phantom-ui[loading] svg,
|
|
117
119
|
phantom-ui[loading] video,
|
|
118
|
-
phantom-ui[loading] canvas
|
|
120
|
+
phantom-ui[loading] canvas,
|
|
121
|
+
phantom-ui[loading] button,
|
|
122
|
+
phantom-ui[loading] [role="button"] {
|
|
119
123
|
opacity: 0 !important;
|
|
120
124
|
}
|
|
121
|
-
`,document.head.appendChild(n)}var o=class extends
|
|
125
|
+
`,document.head.appendChild(n)}var o=class extends N{constructor(){super(...arguments);this.loading=!1;this.shimmerColor="rgba(128, 128, 128, 0.3)";this.backgroundColor="rgba(128, 128, 128, 0.2)";this.duration=1.5;this.fallbackRadius=4;this.animation="shimmer";this.stagger=0;this.reveal=0;this.count=1;this.countGap=0;this._blocks=[];this._revealing=!1;this._resizeObserver=null;this._mutationObserver=null;this._loadHandler=null;this._measureScheduled=!1;this._revealTimeout=null}connectedCallback(){super.connectedCallback(),I()}disconnectedCallback(){super.disconnectedCallback(),this._teardownObservers(),this._clearRevealTimeout()}willUpdate(e){e.has("loading")&&!this.loading&&this.reveal>0&&this._blocks.length>0&&(this._revealing=!0)}updated(e){(e.has("count")||e.has("countGap"))&&this.loading&&this._scheduleMeasure(),e.has("loading")&&(this.setAttribute("aria-busy",String(this.loading)),this.loading?(this._revealing=!1,this._clearRevealTimeout(),this._scheduleMeasure(),this._setupObservers()):this._revealing?(this._teardownObservers(),this._revealTimeout=setTimeout(()=>{this._revealing=!1,this._blocks=[],this._revealTimeout=null,this.style.minHeight=""},this.reveal*1e3)):(this._blocks=[],this._teardownObservers(),this.style.minHeight=""))}render(){let e=H({"--shimmer-color":this.shimmerColor,"--shimmer-duration":`${this.duration}s`,"--shimmer-bg":this.backgroundColor,"--reveal-duration":`${this.reveal}s`}),s=this.loading||this._revealing;return v`
|
|
122
126
|
<slot></slot>
|
|
123
|
-
${s?
|
|
127
|
+
${s?v`
|
|
124
128
|
<div
|
|
125
129
|
class="shimmer-overlay ${this._revealing?"revealing":""}"
|
|
126
130
|
style=${e}
|
|
@@ -129,7 +133,7 @@ var _=Object.defineProperty;var k=Object.getOwnPropertyDescriptor;var a=(n,r,e,s
|
|
|
129
133
|
${this._renderBlocks()}
|
|
130
134
|
</div>
|
|
131
135
|
`:""}
|
|
132
|
-
`}_scheduleMeasure(){this._measureScheduled||(this._measureScheduled=!0,requestAnimationFrame(()=>{this._measureScheduled=!1,this._measure()}))}_measure(){if(!this.loading)return;let e=this.getBoundingClientRect();if(e.width===0||e.height===0)return;let s=this.shadowRoot?.querySelector("slot");if(!s)return;let t=s.assignedElements({flatten:!0}),i=[];for(let
|
|
136
|
+
`}_scheduleMeasure(){this._measureScheduled||(this._measureScheduled=!0,requestAnimationFrame(()=>{this._measureScheduled=!1,this._measure()}))}_measure(){if(!this.loading)return;let e=this.getBoundingClientRect();if(e.width===0||e.height===0)return;let s=this.shadowRoot?.querySelector("slot");if(!s)return;let t=s.assignedElements({flatten:!0}),i=[];for(let a of t){let d=f(a,e);i.push(...d)}if(this.count>1&&i.length>0){let a=0;for(let m of t){let c=m.getBoundingClientRect();a=Math.max(a,c.bottom-e.top)}let d=[...i];for(let m=1;m<this.count;m++)for(let c of d)i.push({...c,y:c.y+m*(a+this.countGap)});let p=this.count*a+(this.count-1)*this.countGap;this.style.minHeight=`${p}px`}else this.style.minHeight="";this._blocks=i}_setupObservers(){this._teardownObservers(),this._resizeObserver=y(this,()=>{this._scheduleMeasure()}),this._mutationObserver=new MutationObserver(()=>{this._scheduleMeasure()}),this._mutationObserver.observe(this,{childList:!0,subtree:!0,attributes:!0}),this._loadHandler=()=>this._scheduleMeasure(),this.addEventListener("load",this._loadHandler,!0)}_teardownObservers(){this._resizeObserver&&(this._resizeObserver.disconnect(),this._resizeObserver=null),this._mutationObserver&&(this._mutationObserver.disconnect(),this._mutationObserver=null),this._loadHandler&&(this.removeEventListener("load",this._loadHandler,!0),this._loadHandler=null)}_clearRevealTimeout(){this._revealTimeout!==null&&(clearTimeout(this._revealTimeout),this._revealTimeout=null)}_renderBlocks(){return this._blocks.map((e,s)=>{let t=e.borderRadius||`${this.fallbackRadius}px`,i=this.stagger,a=i>0?`animation-delay: ${s*i}s;`:"";return v`
|
|
133
137
|
<div
|
|
134
138
|
class="shimmer-block"
|
|
135
139
|
style="
|
|
@@ -139,7 +143,7 @@ var _=Object.defineProperty;var k=Object.getOwnPropertyDescriptor;var a=(n,r,e,s
|
|
|
139
143
|
height: ${e.height}px;
|
|
140
144
|
border-radius: ${t};
|
|
141
145
|
background: var(--shimmer-bg, ${this.backgroundColor});
|
|
142
|
-
${
|
|
146
|
+
${a}
|
|
143
147
|
"
|
|
144
148
|
></div>
|
|
145
|
-
`})}};o.styles=
|
|
149
|
+
`})}};o.styles=_,l([u({type:Boolean,reflect:!0})],o.prototype,"loading",2),l([u({attribute:"shimmer-color"})],o.prototype,"shimmerColor",2),l([u({attribute:"background-color"})],o.prototype,"backgroundColor",2),l([u({type:Number})],o.prototype,"duration",2),l([u({type:Number,attribute:"fallback-radius"})],o.prototype,"fallbackRadius",2),l([u({reflect:!0})],o.prototype,"animation",2),l([u({type:Number})],o.prototype,"stagger",2),l([u({type:Number})],o.prototype,"reveal",2),l([u({type:Number,converter:e=>Math.max(1,Math.round(Number(e)||1))})],o.prototype,"count",2),l([u({type:Number,attribute:"count-gap",converter:e=>Math.max(0,Number(e)||0)})],o.prototype,"countGap",2),l([k()],o.prototype,"_blocks",2),l([k()],o.prototype,"_revealing",2),o=l([M("phantom-ui")],o);export{o as PhantomUi};
|
package/dist/ssr.css
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* phantom-ui SSR pre-hydration styles
|
|
3
|
+
*
|
|
4
|
+
* Import this file in your SSR layout/entry file to prevent content flash
|
|
5
|
+
* before the Web Component hydrates:
|
|
6
|
+
*
|
|
7
|
+
* import "@aejkatappaja/phantom-ui/ssr.css";
|
|
8
|
+
*
|
|
9
|
+
* These rules mirror the light-DOM styles that phantom-ui normally injects
|
|
10
|
+
* at runtime via connectedCallback(), ensuring content inside
|
|
11
|
+
* <phantom-ui loading> is hidden even before JavaScript executes.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
phantom-ui[loading] * {
|
|
15
|
+
-webkit-text-fill-color: transparent !important;
|
|
16
|
+
pointer-events: none;
|
|
17
|
+
user-select: none;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
phantom-ui[loading] img,
|
|
21
|
+
phantom-ui[loading] svg,
|
|
22
|
+
phantom-ui[loading] video,
|
|
23
|
+
phantom-ui[loading] canvas,
|
|
24
|
+
phantom-ui[loading] button,
|
|
25
|
+
phantom-ui[loading] [role="button"] {
|
|
26
|
+
opacity: 0 !important;
|
|
27
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aejkatappaja/phantom-ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Structure-aware shimmer skeleton loader as a universal Web Component built with Lit. Works with React, Vue, Svelte, Angular, Solid, or vanilla JS.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -14,7 +14,8 @@
|
|
|
14
14
|
".": {
|
|
15
15
|
"import": "./dist/phantom-ui.js",
|
|
16
16
|
"types": "./dist/phantom-ui.d.ts"
|
|
17
|
-
}
|
|
17
|
+
},
|
|
18
|
+
"./ssr.css": "./dist/ssr.css"
|
|
18
19
|
},
|
|
19
20
|
"bin": {
|
|
20
21
|
"phantom-ui": "./src/cli/init.mjs"
|
|
@@ -23,12 +24,14 @@
|
|
|
23
24
|
"dist/phantom-ui.js",
|
|
24
25
|
"dist/phantom-ui.cdn.js",
|
|
25
26
|
"dist/phantom-ui.d.ts",
|
|
27
|
+
"dist/ssr.css",
|
|
26
28
|
"src/cli/init.mjs",
|
|
27
29
|
"custom-elements.json"
|
|
28
30
|
],
|
|
29
31
|
"postinstall": "node ./src/cli/init.mjs || true",
|
|
30
32
|
"scripts": {
|
|
31
|
-
"build": "npm run build:esm && npm run build:cdn && npm run build:types && cem analyze",
|
|
33
|
+
"build": "npm run build:esm && npm run build:cdn && npm run build:types && npm run build:ssr && cem analyze",
|
|
34
|
+
"build:ssr": "cp src/ssr.css dist/ssr.css",
|
|
32
35
|
"build:esm": "esbuild src/phantom-ui.ts --bundle --format=esm --outfile=dist/phantom-ui.js --minify --target=es2022 --packages=external",
|
|
33
36
|
"build:cdn": "esbuild src/phantom-ui.ts --bundle --format=iife --outfile=dist/phantom-ui.cdn.js --minify --target=es2022",
|
|
34
37
|
"build:types": "tsc --emitDeclarationOnly --declaration --outDir dist",
|
|
@@ -40,6 +43,7 @@
|
|
|
40
43
|
"build-storybook": "storybook build",
|
|
41
44
|
"prepare": "husky",
|
|
42
45
|
"test": "web-test-runner",
|
|
46
|
+
"test:cli": "bun test test/cli/",
|
|
43
47
|
"test:watch": "web-test-runner --watch",
|
|
44
48
|
"test:all": "web-test-runner --all-browsers",
|
|
45
49
|
"playground": "bunx --bun serve -l 4444 --no-clipboard"
|
package/src/cli/init.mjs
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
4
|
-
import {
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
5
6
|
|
|
6
|
-
const
|
|
7
|
+
export const DTS_FILENAME = "phantom-ui.d.ts";
|
|
8
|
+
export const CSS_IMPORT = 'import "@aejkatappaja/phantom-ui/ssr.css";';
|
|
7
9
|
|
|
8
|
-
const
|
|
10
|
+
export const typeTemplates = {
|
|
9
11
|
react: `import type { PhantomUiAttributes } from "@aejkatappaja/phantom-ui";
|
|
10
12
|
|
|
11
13
|
declare module "react/jsx-runtime" {
|
|
@@ -38,14 +40,33 @@ declare module "@builder.io/qwik" {
|
|
|
38
40
|
`,
|
|
39
41
|
};
|
|
40
42
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
+
export const SSR_ENTRY_FILES = {
|
|
44
|
+
next: [
|
|
45
|
+
"app/layout.tsx",
|
|
46
|
+
"app/layout.jsx",
|
|
47
|
+
"app/layout.js",
|
|
48
|
+
"src/app/layout.tsx",
|
|
49
|
+
"src/app/layout.jsx",
|
|
50
|
+
"src/app/layout.js",
|
|
51
|
+
"pages/_app.tsx",
|
|
52
|
+
"pages/_app.jsx",
|
|
53
|
+
"pages/_app.js",
|
|
54
|
+
"src/pages/_app.tsx",
|
|
55
|
+
"src/pages/_app.jsx",
|
|
56
|
+
"src/pages/_app.js",
|
|
57
|
+
],
|
|
58
|
+
nuxt: ["app.vue", "layouts/default.vue"],
|
|
59
|
+
sveltekit: ["src/routes/+layout.svelte"],
|
|
60
|
+
remix: ["app/root.tsx", "app/root.jsx", "app/root.js"],
|
|
61
|
+
qwik: ["src/root.tsx", "src/root.jsx"],
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
export function findProjectRoot() {
|
|
43
65
|
if (process.env.INIT_CWD && existsSync(join(process.env.INIT_CWD, "package.json"))) {
|
|
44
66
|
return process.env.INIT_CWD;
|
|
45
67
|
}
|
|
46
68
|
|
|
47
69
|
let dir = process.cwd();
|
|
48
|
-
// If we're inside node_modules, walk up to the project root
|
|
49
70
|
if (dir.includes("node_modules")) {
|
|
50
71
|
dir = dir.slice(0, dir.indexOf("node_modules") - 1);
|
|
51
72
|
}
|
|
@@ -53,64 +74,141 @@ function findProjectRoot() {
|
|
|
53
74
|
return null;
|
|
54
75
|
}
|
|
55
76
|
|
|
56
|
-
function
|
|
77
|
+
export function readDeps(root) {
|
|
57
78
|
try {
|
|
58
79
|
const pkg = JSON.parse(readFileSync(join(root, "package.json"), "utf8"));
|
|
59
|
-
|
|
60
|
-
const has = (name) => deps.includes(name);
|
|
61
|
-
|
|
62
|
-
if (has("react") || has("next") || has("@remix-run/react")) return "react";
|
|
63
|
-
if (has("solid-js")) return "solid";
|
|
64
|
-
if (has("@builder.io/qwik")) return "qwik";
|
|
65
|
-
if (has("vue") || has("nuxt")) return "vue";
|
|
66
|
-
if (has("svelte") || has("@sveltejs/kit")) return "svelte";
|
|
67
|
-
if (has("@angular/core")) return "angular";
|
|
80
|
+
return Object.keys({ ...pkg.dependencies, ...pkg.devDependencies });
|
|
68
81
|
} catch {
|
|
69
|
-
|
|
82
|
+
return [];
|
|
70
83
|
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export function detectFramework(deps) {
|
|
87
|
+
const has = (name) => deps.includes(name);
|
|
88
|
+
if (has("react") || has("next") || has("@remix-run/react")) return "react";
|
|
89
|
+
if (has("solid-js")) return "solid";
|
|
90
|
+
if (has("@builder.io/qwik")) return "qwik";
|
|
91
|
+
if (has("vue") || has("nuxt")) return "vue";
|
|
92
|
+
if (has("svelte") || has("@sveltejs/kit")) return "svelte";
|
|
93
|
+
if (has("@angular/core")) return "angular";
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export function detectSSRFramework(deps) {
|
|
98
|
+
const has = (name) => deps.includes(name);
|
|
99
|
+
if (has("next")) return "next";
|
|
100
|
+
if (has("@remix-run/react")) return "remix";
|
|
101
|
+
if (has("nuxt")) return "nuxt";
|
|
102
|
+
if (has("@sveltejs/kit")) return "sveltekit";
|
|
103
|
+
if (has("@builder.io/qwik")) return "qwik";
|
|
71
104
|
return null;
|
|
72
105
|
}
|
|
73
106
|
|
|
74
|
-
function findSrcDir(root) {
|
|
107
|
+
export function findSrcDir(root) {
|
|
75
108
|
for (const dir of ["src", "app"]) {
|
|
76
109
|
if (existsSync(join(root, dir))) return join(root, dir);
|
|
77
110
|
}
|
|
78
111
|
return root;
|
|
79
112
|
}
|
|
80
113
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
114
|
+
export function findEntryFile(root, ssrFramework) {
|
|
115
|
+
const candidates = SSR_ENTRY_FILES[ssrFramework] || [];
|
|
116
|
+
for (const file of candidates) {
|
|
117
|
+
const fullPath = join(root, file);
|
|
118
|
+
if (existsSync(fullPath)) return fullPath;
|
|
119
|
+
}
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export function injectCSSImport(filePath) {
|
|
124
|
+
const content = readFileSync(filePath, "utf8");
|
|
125
|
+
if (content.includes("phantom-ui/ssr.css")) return false;
|
|
126
|
+
|
|
127
|
+
const ext = filePath.split(".").pop();
|
|
128
|
+
|
|
129
|
+
if (ext === "vue" || ext === "svelte") {
|
|
130
|
+
return injectIntoSFC(filePath, content, ext);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
return injectIntoJS(filePath, content);
|
|
85
134
|
}
|
|
86
135
|
|
|
87
|
-
|
|
136
|
+
export function injectIntoSFC(filePath, content, ext) {
|
|
137
|
+
const scriptMatch = content.match(/<script[^>]*>/);
|
|
138
|
+
if (scriptMatch) {
|
|
139
|
+
const insertPos = scriptMatch.index + scriptMatch[0].length;
|
|
140
|
+
const afterScript = content.slice(insertPos);
|
|
141
|
+
const indentMatch = afterScript.match(/\n(\s+)\S/);
|
|
142
|
+
const indent = indentMatch ? indentMatch[1] : "";
|
|
143
|
+
const newContent = `${content.slice(0, insertPos)}\n${indent}${CSS_IMPORT}${content.slice(insertPos)}`;
|
|
144
|
+
writeFileSync(filePath, newContent);
|
|
145
|
+
return true;
|
|
146
|
+
}
|
|
88
147
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
console.log("Run this command from your project root.");
|
|
94
|
-
process.exit(1);
|
|
148
|
+
// No <script> block — create one
|
|
149
|
+
const tag = ext === "vue" ? "<script setup>" : "<script>";
|
|
150
|
+
writeFileSync(filePath, `${tag}\n${CSS_IMPORT}\n</script>\n\n${content}`);
|
|
151
|
+
return true;
|
|
95
152
|
}
|
|
96
153
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
154
|
+
export function injectIntoJS(filePath, content) {
|
|
155
|
+
const lines = content.split("\n");
|
|
156
|
+
|
|
157
|
+
let insertAt = 0;
|
|
158
|
+
for (let i = 0; i < lines.length; i++) {
|
|
159
|
+
if (/\bfrom\s+["']|^\s*import\s+["']/.test(lines[i])) {
|
|
160
|
+
insertAt = i + 1;
|
|
161
|
+
}
|
|
100
162
|
}
|
|
101
|
-
|
|
163
|
+
|
|
164
|
+
lines.splice(insertAt, 0, CSS_IMPORT);
|
|
165
|
+
writeFileSync(filePath, lines.join("\n"));
|
|
166
|
+
return true;
|
|
102
167
|
}
|
|
103
168
|
|
|
104
|
-
|
|
105
|
-
const
|
|
106
|
-
|
|
169
|
+
function main() {
|
|
170
|
+
const root = findProjectRoot();
|
|
171
|
+
if (!root) process.exit(0);
|
|
107
172
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
173
|
+
const isPostinstall = process.env.npm_lifecycle_event === "postinstall";
|
|
174
|
+
const deps = readDeps(root);
|
|
175
|
+
const framework = detectFramework(deps);
|
|
176
|
+
|
|
177
|
+
if (!framework) {
|
|
178
|
+
if (isPostinstall) process.exit(0);
|
|
179
|
+
console.log("Could not detect framework from package.json.");
|
|
180
|
+
console.log("Run this command from your project root.");
|
|
181
|
+
process.exit(1);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
const template = typeTemplates[framework];
|
|
185
|
+
if (template) {
|
|
186
|
+
const srcDir = findSrcDir(root);
|
|
187
|
+
const outPath = join(srcDir, DTS_FILENAME);
|
|
188
|
+
if (!existsSync(outPath)) {
|
|
189
|
+
writeFileSync(outPath, template);
|
|
190
|
+
console.log(`phantom-ui: created ${outPath} (${framework} JSX types)`);
|
|
191
|
+
} else if (!isPostinstall) {
|
|
192
|
+
console.log(`${outPath} already exists. Skipping.`);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
const ssrFramework = detectSSRFramework(deps);
|
|
197
|
+
if (ssrFramework) {
|
|
198
|
+
const entryFile = findEntryFile(root, ssrFramework);
|
|
199
|
+
if (entryFile) {
|
|
200
|
+
if (injectCSSImport(entryFile)) {
|
|
201
|
+
console.log(`phantom-ui: added SSR styles import in ${entryFile}`);
|
|
202
|
+
} else if (!isPostinstall) {
|
|
203
|
+
console.log("phantom-ui: SSR styles import already present. Skipping.");
|
|
204
|
+
}
|
|
205
|
+
} else if (!isPostinstall) {
|
|
206
|
+
console.log(`phantom-ui: detected ${ssrFramework} but could not find layout entry file.`);
|
|
207
|
+
console.log(`Add this to your layout/root file: ${CSS_IMPORT}`);
|
|
208
|
+
}
|
|
111
209
|
}
|
|
112
|
-
process.exit(0);
|
|
113
210
|
}
|
|
114
211
|
|
|
115
|
-
|
|
116
|
-
|
|
212
|
+
if (process.argv[1] === fileURLToPath(import.meta.url)) {
|
|
213
|
+
main();
|
|
214
|
+
}
|