@aejkatappaja/phantom-ui 0.5.2 → 0.6.1

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 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
@@ -73,6 +157,88 @@ Or drop in a script tag with no build step:
73
157
 
74
158
  Set `loading` to show the shimmer. Remove it to reveal the real content. All child elements (including deeply nested images and media) are automatically hidden during loading.
75
159
 
160
+ ## Data fetching
161
+
162
+ phantom-ui works with any data fetching approach. The pattern: render placeholder content while loading, real content when done. The placeholder text is invisible (CSS transparent) and only used to generate the skeleton shape.
163
+
164
+ ### TanStack Query
165
+
166
+ ```tsx
167
+ import { useQuery } from "@tanstack/react-query";
168
+ import "@aejkatappaja/phantom-ui";
169
+
170
+ function UserProfile({ userId }: { userId: string }) {
171
+ const { data: user, isLoading } = useQuery({
172
+ queryKey: ["user", userId],
173
+ queryFn: () => fetch(`/api/users/${userId}`).then((r) => r.json()),
174
+ });
175
+
176
+ return (
177
+ <phantom-ui loading={isLoading || undefined}>
178
+ <div className="card">
179
+ <img src={user?.avatar ?? "/placeholder.png"} width="48" height="48" />
180
+ <h3>{user?.name ?? "Placeholder Name"}</h3>
181
+ <p>{user?.bio ?? "A short bio goes here."}</p>
182
+ </div>
183
+ </phantom-ui>
184
+ );
185
+ }
186
+ ```
187
+
188
+ While `isLoading` is true, the placeholder text (`"Placeholder Name"`, `"A short bio goes here."`) is rendered invisibly and phantom-ui generates shimmer blocks matching their exact position and size. When the query resolves, `loading` is removed and the real content appears.
189
+
190
+ ### SWR
191
+
192
+ ```tsx
193
+ import useSWR from "swr";
194
+ import "@aejkatappaja/phantom-ui";
195
+
196
+ function UserProfile({ userId }: { userId: string }) {
197
+ const { data: user, isLoading } = useSWR(`/api/users/${userId}`);
198
+
199
+ return (
200
+ <phantom-ui loading={isLoading || undefined}>
201
+ <div className="card">
202
+ <img src={user?.avatar ?? "/placeholder.png"} width="48" height="48" />
203
+ <h3>{user?.name ?? "Placeholder Name"}</h3>
204
+ <p>{user?.bio ?? "A short bio goes here."}</p>
205
+ </div>
206
+ </phantom-ui>
207
+ );
208
+ }
209
+ ```
210
+
211
+ ### Lists
212
+
213
+ For dynamic lists where the data hasn't loaded yet, use `count` to repeat a single template row:
214
+
215
+ ```tsx
216
+ const { data: users, isLoading } = useQuery({
217
+ queryKey: ["users"],
218
+ queryFn: () => fetch("/api/users").then((r) => r.json()),
219
+ });
220
+
221
+ return (
222
+ <phantom-ui loading={isLoading || undefined} count={5} count-gap={8}>
223
+ {isLoading ? (
224
+ <div className="row">
225
+ <img src="/placeholder.png" width="32" height="32" />
226
+ <span>Placeholder Name</span>
227
+ <span>placeholder@email.com</span>
228
+ </div>
229
+ ) : (
230
+ users?.map((u) => (
231
+ <div key={u.id} className="row">
232
+ <img src={u.avatar} width="32" height="32" />
233
+ <span>{u.name}</span>
234
+ <span>{u.email}</span>
235
+ </div>
236
+ ))
237
+ )}
238
+ </phantom-ui>
239
+ );
240
+ ```
241
+
76
242
  ## Framework examples
77
243
 
78
244
  ### React
@@ -188,7 +354,7 @@ function ProfileCard() {
188
354
  }
189
355
  ```
190
356
 
191
- ### SSR frameworks (Next.js, Nuxt, SvelteKit)
357
+ ### SSR frameworks (Next.js, Nuxt, SvelteKit, Remix, Qwik)
192
358
 
193
359
  The component needs browser APIs to measure the DOM. Import it client-side only:
194
360
 
@@ -226,77 +392,39 @@ onMounted(() => import("@aejkatappaja/phantom-ui"));
226
392
 
227
393
  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
394
 
229
- ## TypeScript
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.
232
-
233
- Vue, Svelte, and Angular work out of the box without any type declaration.
234
-
235
- If the postinstall did not run (CI, monorepos, `--ignore-scripts`), you can generate it manually:
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**
395
+ #### Pre-hydration CSS
248
396
 
249
- ```typescript
250
- import type { PhantomUiAttributes } from "@aejkatappaja/phantom-ui";
397
+ 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:
251
398
 
252
- declare module "react/jsx-runtime" {
253
- export namespace JSX {
254
- interface IntrinsicElements {
255
- "phantom-ui": PhantomUiAttributes;
256
- }
257
- }
258
- }
399
+ ```css
400
+ import "@aejkatappaja/phantom-ui/ssr.css";
259
401
  ```
260
402
 
261
- **Solid**
262
-
263
- ```typescript
264
- import type { SolidPhantomUiAttributes } from "@aejkatappaja/phantom-ui";
403
+ 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
404
 
266
- declare module "solid-js" {
267
- namespace JSX {
268
- interface IntrinsicElements {
269
- "phantom-ui": SolidPhantomUiAttributes;
270
- }
405
+ ```html
406
+ <style>
407
+ phantom-ui[loading] * {
408
+ -webkit-text-fill-color: transparent !important;
409
+ pointer-events: none;
410
+ user-select: none;
271
411
  }
272
- }
273
- ```
274
-
275
- **Qwik**
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
- }
412
+ phantom-ui[loading] img, phantom-ui[loading] svg,
413
+ phantom-ui[loading] video, phantom-ui[loading] canvas,
414
+ phantom-ui[loading] button, phantom-ui[loading] [role="button"] {
415
+ opacity: 0 !important;
285
416
  }
286
- }
417
+ </style>
287
418
  ```
288
419
 
289
-
290
- </details>
291
-
292
420
  ## Attributes
293
421
 
294
422
  | Attribute | Type | Default | Description |
295
423
  | --- | --- | --- | --- |
296
424
  | `loading` | `boolean` | `false` | Show shimmer overlay or real content |
297
425
  | `animation` | `string` | `shimmer` | Animation mode: `shimmer`, `pulse`, `breathe`, or `solid` |
298
- | `shimmer-color` | `string` | `rgba(255,255,255,0.3)` | Color of the animated gradient sweep |
299
- | `background-color` | `string` | `rgba(255,255,255,0.08)` | Background of each shimmer block |
426
+ | `shimmer-color` | `string` | `rgba(128,128,128,0.3)` | Color of the animated gradient sweep |
427
+ | `background-color` | `string` | `rgba(128,128,128,0.2)` | Background of each shimmer block |
300
428
  | `duration` | `number` | `1.5` | Animation cycle in seconds |
301
429
  | `stagger` | `number` | `0` | Delay in seconds between each block's animation start |
302
430
  | `reveal` | `number` | `0` | Fade-out duration in seconds when loading ends |
@@ -306,12 +434,14 @@ declare module "@builder.io/qwik" {
306
434
 
307
435
  ## Fine-grained control
308
436
 
309
- Two data attributes let you control which elements get shimmer treatment:
437
+ Data attributes let you control which elements get shimmer treatment and how they are measured:
310
438
 
311
439
  **`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
440
 
313
441
  **`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
442
 
443
+ **`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.
444
+
315
445
  ```html
316
446
  <phantom-ui loading>
317
447
  <div class="dashboard">
@@ -321,6 +451,7 @@ Two data attributes let you control which elements get shimmer treatment:
321
451
  <span>2,847 users</span>
322
452
  <span>42ms p99</span>
323
453
  </div>
454
+ <img src="/hero.jpg" data-shimmer-width="600" data-shimmer-height="400" />
324
455
  <div class="content">
325
456
  <p>Each leaf element here gets its own shimmer block.</p>
326
457
  </div>
@@ -1,6 +1,6 @@
1
- "use strict";(()=>{var Rt=Object.defineProperty;var kt=Object.getOwnPropertyDescriptor;var m=(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,w=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 w(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 w(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,T=(r,t)=>r,O={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:O,reflect:!1,useDefault:!1,hasChanged:D};Symbol.metadata??=Symbol("metadata"),I.litPropertyMetadata??=new WeakMap;var _=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(T("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(T("finalized")))return;if(this.finalized=!0,this._$Ei(),this.hasOwnProperty(T("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:O).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:O;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){}};_.elementStyles=[],_.shadowRootOptions={mode:"open"},_[T("elementProperties")]=new Map,_[T("finalized")]=new Map,Dt?.({ReactiveElement:_}),(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,k=()=>S.createComment(""),M=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]`,R=/<(?:(!--|\/[^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),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$",y=`lit$${Math.random().toFixed(9).slice(2)}$`,_t="?"+y,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),b=Symbol.for("lit-noChange"),u=Symbol.for("lit-nothing"),ft=new WeakMap,E=S.createTreeWalker(S,129);function bt(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)+y+m):a+y+(c===-2?l:m)}return[bt(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(y),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(y)&&(a.push({type:6,index:o}),i.removeAttribute(c));if(vt.test(i.tagName)){let c=i.textContent.split(y),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(y,c+1))!==-1;)a.push({type:7,index:o}),c+=y.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===b)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!==b&&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(bt(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!==b,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===b&&(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)===b)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 yt=(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,$=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=yt(e,this.renderRoot,this.renderOptions)}connectedCallback(){super.connectedCallback(),this._$Do?.setConnected(!0)}disconnectedCallback(){super.disconnectedCallback(),this._$Do?.setConnected(!1)}render(){return b}};$._$litElement$=!0,$.finalized=!0,st.litElementHydrateSupport?.({LitElement:$});var Vt=st.litElementPolyfillSupport;Vt?.({LitElement:$});(st.litElementVersions??=[]).push("4.2.2");var $t=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 b}});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;
@@ -124,7 +124,21 @@
124
124
  phantom-ui[loading] [role="button"] {
125
125
  opacity: 0 !important;
126
126
  }
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`
127
+ phantom-ui[loading] [data-shimmer-ignore],
128
+ phantom-ui[loading] [data-shimmer-ignore] * {
129
+ -webkit-text-fill-color: initial !important;
130
+ pointer-events: auto;
131
+ user-select: auto;
132
+ }
133
+ phantom-ui[loading] [data-shimmer-ignore] img,
134
+ phantom-ui[loading] [data-shimmer-ignore] svg,
135
+ phantom-ui[loading] [data-shimmer-ignore] video,
136
+ phantom-ui[loading] [data-shimmer-ignore] canvas,
137
+ phantom-ui[loading] [data-shimmer-ignore] button,
138
+ phantom-ui[loading] [data-shimmer-ignore] [role="button"] {
139
+ opacity: 1 !important;
140
+ }
141
+ `,document.head.appendChild(r)}var p=class extends ${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`
128
142
  <slot></slot>
129
143
  ${s?j`
130
144
  <div
@@ -135,7 +149,7 @@
135
149
  ${this._renderBlocks()}
136
150
  </div>
137
151
  `:""}
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=Ct(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=wt(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`
152
+ `}_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`
139
153
  <div
140
154
  class="shimmer-block"
141
155
  style="
@@ -148,7 +162,7 @@
148
162
  ${n}
149
163
  "
150
164
  ></div>
151
- `})}};p.styles=Tt,m([f({type:Boolean,reflect:!0})],p.prototype,"loading",2),m([f({attribute:"shimmer-color"})],p.prototype,"shimmerColor",2),m([f({attribute:"background-color"})],p.prototype,"backgroundColor",2),m([f({type:Number})],p.prototype,"duration",2),m([f({type:Number,attribute:"fallback-radius"})],p.prototype,"fallbackRadius",2),m([f({reflect:!0})],p.prototype,"animation",2),m([f({type:Number})],p.prototype,"stagger",2),m([f({type:Number})],p.prototype,"reveal",2),m([f({type:Number,converter:e=>Math.max(1,Math.round(Number(e)||1))})],p.prototype,"count",2),m([f({type:Number,attribute:"count-gap",converter:e=>Math.max(0,Number(e)||0)})],p.prototype,"countGap",2),m([it()],p.prototype,"_blocks",2),m([it()],p.prototype,"_revealing",2),p=m([bt("phantom-ui")],p);})();
165
+ `})}};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([$t("phantom-ui")],p);})();
152
166
  /*! Bundled license information:
153
167
 
154
168
  @lit/reactive-element/css-tag.js:
@@ -1,4 +1,4 @@
1
- var _=Object.defineProperty;var k=Object.getOwnPropertyDescriptor;var a=(n,r,e,s)=>{for(var t=s>1?void 0:s?k(r,e):r,i=n.length-1,l;i>=0;i--)(l=n[i])&&(t=(s?l(r,e,t):l(t))||t);return s&&t&&_(r,e,t),t};import{LitElement as T,html as p}from"lit";import{customElement as C,property as h,state as f}from"lit/decorators.js";import{styleMap as S}from"lit/directives/style-map.js";var w=new Set(["IMG","SVG","VIDEO","CANVAS","IFRAME","INPUT","TEXTAREA","BUTTON","HR"]),E=new Set(["BR","WBR","HR"]);function x(n){if(w.has(n.tagName))return!0;for(let r of n.children)if(!E.has(r.tagName))return!1;return!0}function O(n){for(let r of n.childNodes)if(r.nodeType===Node.TEXT_NODE&&r.textContent?.trim())return!0;return!1}function b(n,r){let e=[];function s(t){let i=t.getBoundingClientRect();if(i.width===0||i.height===0||t.hasAttribute("data-shimmer-ignore"))return;if(t.hasAttribute("data-shimmer-no-children")||x(t)){let d=getComputedStyle(t).borderRadius;if((t.tagName==="TD"||t.tagName==="TH")&&O(t)){let u=document.createElement("span");u.style.visibility="hidden",u.style.position="absolute",u.textContent=t.textContent,t.appendChild(u);let c=u.getBoundingClientRect();t.removeChild(u),e.push({x:i.left-r.left,y:i.top-r.top,width:Math.min(c.width,i.width),height:i.height,tag:t.tagName.toLowerCase(),borderRadius:d==="0px"?"":d});return}e.push({x:i.left-r.left,y:i.top-r.top,width:i.width,height:i.height,tag:t.tagName.toLowerCase(),borderRadius:d==="0px"?"":d});return}for(let m of t.children)s(m)}return s(n),e}function v(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 R}from"lit";var g=R`
1
+ var E=Object.defineProperty;var O=Object.getOwnPropertyDescriptor;var l=(n,r,e,o)=>{for(var t=o>1?void 0:o?O(r,e):r,i=n.length-1,a;i>=0;i--)(a=n[i])&&(t=(o?a(r,e,t):a(t))||t);return o&&t&&E(r,e,t),t};import{LitElement as N,html as g}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 o(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 x=h.getBoundingClientRect();t.removeChild(h),e.push({x:i.left-r.left,y:i.top-r.top,width:Math.min(x.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 v of t.children)o(v)}return o(n),e}function y(n,r){let e=null,o=new ResizeObserver(()=>{e!==null&&cancelAnimationFrame(e),e=requestAnimationFrame(()=>{e=null,r()})});return o.observe(n),o}import{css as A}from"lit";var _=A`
2
2
  :host {
3
3
  display: block;
4
4
  position: relative;
@@ -108,7 +108,7 @@ var _=Object.defineProperty;var k=Object.getOwnPropertyDescriptor;var a=(n,r,e,s
108
108
  :host([animation="solid"]) .shimmer-block::after {
109
109
  display: none;
110
110
  }
111
- `;var y="phantom-ui-loading-styles";function A(){if(document.getElementById(y))return;let n=document.createElement("style");n.id=y,n.textContent=`
111
+ `;var w="phantom-ui-loading-styles";function I(){if(document.getElementById(w))return;let n=document.createElement("style");n.id=w,n.textContent=`
112
112
  phantom-ui[loading] * {
113
113
  -webkit-text-fill-color: transparent !important;
114
114
  pointer-events: none;
@@ -122,9 +122,23 @@ var _=Object.defineProperty;var k=Object.getOwnPropertyDescriptor;var a=(n,r,e,s
122
122
  phantom-ui[loading] [role="button"] {
123
123
  opacity: 0 !important;
124
124
  }
125
- `,document.head.appendChild(n)}var o=class extends T{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(),A()}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=S({"--shimmer-color":this.shimmerColor,"--shimmer-duration":`${this.duration}s`,"--shimmer-bg":this.backgroundColor,"--reveal-duration":`${this.reveal}s`}),s=this.loading||this._revealing;return p`
125
+ phantom-ui[loading] [data-shimmer-ignore],
126
+ phantom-ui[loading] [data-shimmer-ignore] * {
127
+ -webkit-text-fill-color: initial !important;
128
+ pointer-events: auto;
129
+ user-select: auto;
130
+ }
131
+ phantom-ui[loading] [data-shimmer-ignore] img,
132
+ phantom-ui[loading] [data-shimmer-ignore] svg,
133
+ phantom-ui[loading] [data-shimmer-ignore] video,
134
+ phantom-ui[loading] [data-shimmer-ignore] canvas,
135
+ phantom-ui[loading] [data-shimmer-ignore] button,
136
+ phantom-ui[loading] [data-shimmer-ignore] [role="button"] {
137
+ opacity: 1 !important;
138
+ }
139
+ `,document.head.appendChild(n)}var s=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`}),o=this.loading||this._revealing;return g`
126
140
  <slot></slot>
127
- ${s?p`
141
+ ${o?g`
128
142
  <div
129
143
  class="shimmer-overlay ${this._revealing?"revealing":""}"
130
144
  style=${e}
@@ -133,7 +147,7 @@ var _=Object.defineProperty;var k=Object.getOwnPropertyDescriptor;var a=(n,r,e,s
133
147
  ${this._renderBlocks()}
134
148
  </div>
135
149
  `:""}
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 l of t){let m=b(l,e);i.push(...m)}if(this.count>1&&i.length>0){let l=0;for(let u of t){let c=u.getBoundingClientRect();l=Math.max(l,c.bottom-e.top)}let m=[...i];for(let u=1;u<this.count;u++)for(let c of m)i.push({...c,y:c.y+u*(l+this.countGap)});let d=this.count*l+(this.count-1)*this.countGap;this.style.minHeight=`${d}px`}else this.style.minHeight="";this._blocks=i}_setupObservers(){this._teardownObservers(),this._resizeObserver=v(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,l=i>0?`animation-delay: ${s*i}s;`:"";return p`
150
+ `}_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 o=this.shadowRoot?.querySelector("slot");if(!o)return;let t=o.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,o)=>{let t=e.borderRadius||`${this.fallbackRadius}px`,i=this.stagger,a=i>0?`animation-delay: ${o*i}s;`:"";return g`
137
151
  <div
138
152
  class="shimmer-block"
139
153
  style="
@@ -143,7 +157,7 @@ var _=Object.defineProperty;var k=Object.getOwnPropertyDescriptor;var a=(n,r,e,s
143
157
  height: ${e.height}px;
144
158
  border-radius: ${t};
145
159
  background: var(--shimmer-bg, ${this.backgroundColor});
146
- ${l}
160
+ ${a}
147
161
  "
148
162
  ></div>
149
- `})}};o.styles=g,a([h({type:Boolean,reflect:!0})],o.prototype,"loading",2),a([h({attribute:"shimmer-color"})],o.prototype,"shimmerColor",2),a([h({attribute:"background-color"})],o.prototype,"backgroundColor",2),a([h({type:Number})],o.prototype,"duration",2),a([h({type:Number,attribute:"fallback-radius"})],o.prototype,"fallbackRadius",2),a([h({reflect:!0})],o.prototype,"animation",2),a([h({type:Number})],o.prototype,"stagger",2),a([h({type:Number})],o.prototype,"reveal",2),a([h({type:Number,converter:e=>Math.max(1,Math.round(Number(e)||1))})],o.prototype,"count",2),a([h({type:Number,attribute:"count-gap",converter:e=>Math.max(0,Number(e)||0)})],o.prototype,"countGap",2),a([f()],o.prototype,"_blocks",2),a([f()],o.prototype,"_revealing",2),o=a([C("phantom-ui")],o);export{o as PhantomUi};
163
+ `})}};s.styles=_,l([u({type:Boolean,reflect:!0})],s.prototype,"loading",2),l([u({attribute:"shimmer-color"})],s.prototype,"shimmerColor",2),l([u({attribute:"background-color"})],s.prototype,"backgroundColor",2),l([u({type:Number})],s.prototype,"duration",2),l([u({type:Number,attribute:"fallback-radius"})],s.prototype,"fallbackRadius",2),l([u({reflect:!0})],s.prototype,"animation",2),l([u({type:Number})],s.prototype,"stagger",2),l([u({type:Number})],s.prototype,"reveal",2),l([u({type:Number,converter:e=>Math.max(1,Math.round(Number(e)||1))})],s.prototype,"count",2),l([u({type:Number,attribute:"count-gap",converter:e=>Math.max(0,Number(e)||0)})],s.prototype,"countGap",2),l([k()],s.prototype,"_blocks",2),l([k()],s.prototype,"_revealing",2),s=l([M("phantom-ui")],s);export{s as PhantomUi};
package/dist/ssr.css ADDED
@@ -0,0 +1,43 @@
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
+ }
28
+
29
+ phantom-ui[loading] [data-shimmer-ignore],
30
+ phantom-ui[loading] [data-shimmer-ignore] * {
31
+ -webkit-text-fill-color: initial !important;
32
+ pointer-events: auto;
33
+ user-select: auto;
34
+ }
35
+
36
+ phantom-ui[loading] [data-shimmer-ignore] img,
37
+ phantom-ui[loading] [data-shimmer-ignore] svg,
38
+ phantom-ui[loading] [data-shimmer-ignore] video,
39
+ phantom-ui[loading] [data-shimmer-ignore] canvas,
40
+ phantom-ui[loading] [data-shimmer-ignore] button,
41
+ phantom-ui[loading] [data-shimmer-ignore] [role="button"] {
42
+ opacity: 1 !important;
43
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aejkatappaja/phantom-ui",
3
- "version": "0.5.2",
3
+ "version": "0.6.1",
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 { dirname, join, resolve } from "node:path";
4
+ import { join } from "node:path";
5
+ import { fileURLToPath } from "node:url";
5
6
 
6
- const FILENAME = "phantom-ui.d.ts";
7
+ export const DTS_FILENAME = "phantom-ui.d.ts";
8
+ export const CSS_IMPORT = 'import "@aejkatappaja/phantom-ui/ssr.css";';
7
9
 
8
- const templates = {
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
- function findProjectRoot() {
42
- // During postinstall, INIT_CWD is set to the directory where `npm install` was run
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 detectFramework(root) {
77
+ export function readDeps(root) {
57
78
  try {
58
79
  const pkg = JSON.parse(readFileSync(join(root, "package.json"), "utf8"));
59
- const deps = Object.keys({ ...pkg.dependencies, ...pkg.devDependencies });
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
- // no package.json
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
- const root = findProjectRoot();
82
- if (!root) {
83
- // Silent exit during postinstall if we can't find the project
84
- process.exit(0);
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
- const framework = detectFramework(root);
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
- if (!framework) {
90
- // Silent exit during postinstall if framework is unknown
91
- if (process.env.npm_lifecycle_event === "postinstall") process.exit(0);
92
- console.log("Could not detect framework from package.json.");
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
- if (framework === "vue" || framework === "svelte" || framework === "angular") {
98
- if (process.env.npm_lifecycle_event !== "postinstall") {
99
- console.log(`Detected ${framework}. No type declaration needed - types work automatically.`);
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
- process.exit(0);
163
+
164
+ lines.splice(insertAt, 0, CSS_IMPORT);
165
+ writeFileSync(filePath, lines.join("\n"));
166
+ return true;
102
167
  }
103
168
 
104
- const template = templates[framework];
105
- const srcDir = findSrcDir(root);
106
- const outPath = join(srcDir, FILENAME);
169
+ function main() {
170
+ const root = findProjectRoot();
171
+ if (!root) process.exit(0);
107
172
 
108
- if (existsSync(outPath)) {
109
- if (process.env.npm_lifecycle_event !== "postinstall") {
110
- console.log(`${outPath} already exists. Skipping.`);
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
- writeFileSync(outPath, template);
116
- console.log(`phantom-ui: created ${outPath} (${framework} JSX types)`);
212
+ if (process.argv[1] === fileURLToPath(import.meta.url)) {
213
+ main();
214
+ }