@dismissible/react-client 0.3.0 β 0.3.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 +125 -5
- package/dist/dismissible-client.es.js +1 -1
- package/dist/dismissible-client.umd.js +1 -1
- package/dist/root.d.ts +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
A React component library for creating dismissible UI elements with persistent state management.
|
|
4
4
|
|
|
5
|
+
π **[dismissible.io](https://dismissible.io)** | π° **[View Pricing](https://dismissible.io/pricing)** | π **[Documentation](https://docs.dismissible.io)**
|
|
6
|
+
|
|
5
7
|
[](https://badge.fury.io/js/@dismissible%2Freact-client)
|
|
6
8
|
[](https://opensource.org/licenses/MIT)
|
|
7
9
|
|
|
@@ -9,7 +11,7 @@ A React component library for creating dismissible UI elements with persistent s
|
|
|
9
11
|
|
|
10
12
|
- π― **Easy to use** - Simple component API for dismissible content
|
|
11
13
|
- πΎ **Persistent state** - Dismissal state is saved and restored across sessions
|
|
12
|
-
- π **JWT Authentication** - Built-in support for JWT-based user authentication
|
|
14
|
+
- π **JWT Authentication** - Built-in support for JWT-based user authentication (Enterprise only)
|
|
13
15
|
- π¨ **Customizable** - Custom loading, error, and dismiss button components
|
|
14
16
|
- βΏ **Accessible** - Built with accessibility best practices
|
|
15
17
|
- πͺ **Hook-based** - Includes `useDismissibleItem` hook for custom implementations
|
|
@@ -54,11 +56,13 @@ function App() {
|
|
|
54
56
|
|
|
55
57
|
Context provider for JWT authentication and configuration. Wrap your app or components that need JWT authentication.
|
|
56
58
|
|
|
59
|
+
> **Note:** JWT authentication is only available for **Enterprise customers**. For standard usage, you can use the `<Dismissible>` component directly without a provider. [View pricing β](https://dismissible.io/pricing)
|
|
60
|
+
|
|
57
61
|
#### Props
|
|
58
62
|
|
|
59
63
|
| Prop | Type | Required | Description |
|
|
60
64
|
|------|------|----------|-------------|
|
|
61
|
-
| `jwt` | `string \| (() => string)` | β | JWT token
|
|
65
|
+
| `jwt` | `string \| (() => string) \| (() => Promise<string>)` | β | JWT token for user-specific dismissals (**Enterprise only**) |
|
|
62
66
|
| `baseUrl` | `string` | β | Custom API base URL override |
|
|
63
67
|
| `children` | `ReactNode` | β
| Components that will use the dismissible functionality |
|
|
64
68
|
|
|
@@ -85,6 +89,15 @@ function AppWithDynamicAuth() {
|
|
|
85
89
|
);
|
|
86
90
|
}
|
|
87
91
|
|
|
92
|
+
// With async JWT function
|
|
93
|
+
function AppWithAsyncAuth() {
|
|
94
|
+
return (
|
|
95
|
+
<DismissibleProvider jwt={async () => await fetchAccessToken()}>
|
|
96
|
+
<YourApp />
|
|
97
|
+
</DismissibleProvider>
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
|
|
88
101
|
// Without JWT (anonymous/backwards compatible)
|
|
89
102
|
function AppWithoutAuth() {
|
|
90
103
|
return (
|
|
@@ -109,6 +122,7 @@ The main component for creating dismissible content.
|
|
|
109
122
|
| `LoadingComponent` | `ComponentType<{id: string}>` | β | Custom loading component |
|
|
110
123
|
| `ErrorComponent` | `ComponentType<{id: string, error: Error}>` | β | Custom error component |
|
|
111
124
|
| `DismissButtonComponent` | `ComponentType<{id: string, onDismiss: () => Promise<void>, ariaLabel: string}>` | β | Custom dismiss button |
|
|
125
|
+
| `ignoreErrors` | `boolean` | β | Ignore errors and display component anyway (default: false) |
|
|
112
126
|
|
|
113
127
|
#### Example
|
|
114
128
|
|
|
@@ -177,7 +191,9 @@ function CustomDismissible({ id, children }) {
|
|
|
177
191
|
|
|
178
192
|
## Usage Examples
|
|
179
193
|
|
|
180
|
-
### JWT Authentication Setup
|
|
194
|
+
### JWT Authentication Setup (Enterprise Only)
|
|
195
|
+
|
|
196
|
+
> **Enterprise Feature:** JWT authentication allows user-specific dismissible state management. This feature requires an Enterprise subscription. [Learn more about Enterprise features β](https://dismissible.io/pricing)
|
|
181
197
|
|
|
182
198
|
For enterprise accounts that require user-specific dismissible state, wrap your app with the `DismissibleProvider`:
|
|
183
199
|
|
|
@@ -216,6 +232,7 @@ function Dashboard() {
|
|
|
216
232
|
import { DismissibleProvider } from '@dismissible/react-client';
|
|
217
233
|
import { useAuth } from './auth'; // Your auth context
|
|
218
234
|
|
|
235
|
+
// Synchronous JWT function
|
|
219
236
|
function App() {
|
|
220
237
|
const { getAccessToken } = useAuth();
|
|
221
238
|
|
|
@@ -225,6 +242,17 @@ function App() {
|
|
|
225
242
|
</DismissibleProvider>
|
|
226
243
|
);
|
|
227
244
|
}
|
|
245
|
+
|
|
246
|
+
// Asynchronous JWT function
|
|
247
|
+
function AppWithAsyncAuth() {
|
|
248
|
+
const { refreshAndGetToken } = useAuth();
|
|
249
|
+
|
|
250
|
+
return (
|
|
251
|
+
<DismissibleProvider jwt={async () => await refreshAndGetToken()}>
|
|
252
|
+
<YourApp />
|
|
253
|
+
</DismissibleProvider>
|
|
254
|
+
);
|
|
255
|
+
}
|
|
228
256
|
```
|
|
229
257
|
|
|
230
258
|
### Basic Dismissible Banner
|
|
@@ -371,6 +399,8 @@ function ConditionalBanner({ user }) {
|
|
|
371
399
|
|
|
372
400
|
The behavior changes based on whether JWT authentication is configured:
|
|
373
401
|
|
|
402
|
+
> **Enterprise vs Standard:** JWT authentication for user-specific dismissals is an Enterprise feature. Standard accounts use anonymous (account-level) dismissals. [Compare plans β](https://dismissible.io/pricing)
|
|
403
|
+
|
|
374
404
|
```tsx
|
|
375
405
|
import { DismissibleProvider, Dismissible } from '@dismissible/react-client';
|
|
376
406
|
|
|
@@ -406,6 +436,96 @@ function AnonymousApp() {
|
|
|
406
436
|
}
|
|
407
437
|
```
|
|
408
438
|
|
|
439
|
+
### Error Handling with ignoreErrors
|
|
440
|
+
|
|
441
|
+
```tsx
|
|
442
|
+
import { Dismissible } from '@dismissible/react-client';
|
|
443
|
+
|
|
444
|
+
// Show content even if API fails
|
|
445
|
+
function RobustBanner() {
|
|
446
|
+
return (
|
|
447
|
+
<Dismissible
|
|
448
|
+
id="important-announcement"
|
|
449
|
+
ignoreErrors={true}
|
|
450
|
+
>
|
|
451
|
+
<div className="important-banner">
|
|
452
|
+
<h3>Critical System Update</h3>
|
|
453
|
+
<p>System maintenance scheduled for tonight. Please save your work.</p>
|
|
454
|
+
</div>
|
|
455
|
+
</Dismissible>
|
|
456
|
+
);
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
// Default behavior - hide content on errors
|
|
460
|
+
function StandardBanner() {
|
|
461
|
+
return (
|
|
462
|
+
<Dismissible id="promo-banner">
|
|
463
|
+
<div className="promo">
|
|
464
|
+
<h3>Special Offer!</h3>
|
|
465
|
+
<p>Get 50% off your first order</p>
|
|
466
|
+
</div>
|
|
467
|
+
</Dismissible>
|
|
468
|
+
);
|
|
469
|
+
}
|
|
470
|
+
```
|
|
471
|
+
|
|
472
|
+
### Async JWT Authentication Examples
|
|
473
|
+
|
|
474
|
+
```tsx
|
|
475
|
+
import { DismissibleProvider } from '@dismissible/react-client';
|
|
476
|
+
|
|
477
|
+
// With token refresh logic
|
|
478
|
+
function AppWithTokenRefresh() {
|
|
479
|
+
return (
|
|
480
|
+
<DismissibleProvider
|
|
481
|
+
jwt={async () => {
|
|
482
|
+
try {
|
|
483
|
+
const token = await fetch('/api/auth/refresh', {
|
|
484
|
+
method: 'POST',
|
|
485
|
+
credentials: 'include'
|
|
486
|
+
});
|
|
487
|
+
const { accessToken } = await token.json();
|
|
488
|
+
return accessToken;
|
|
489
|
+
} catch (error) {
|
|
490
|
+
console.error('Failed to refresh token:', error);
|
|
491
|
+
throw error;
|
|
492
|
+
}
|
|
493
|
+
}}
|
|
494
|
+
>
|
|
495
|
+
<YourApp />
|
|
496
|
+
</DismissibleProvider>
|
|
497
|
+
);
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
// With Firebase Auth
|
|
501
|
+
function AppWithFirebase() {
|
|
502
|
+
return (
|
|
503
|
+
<DismissibleProvider
|
|
504
|
+
jwt={async () => {
|
|
505
|
+
const user = firebase.auth().currentUser;
|
|
506
|
+
if (user) {
|
|
507
|
+
return await user.getIdToken();
|
|
508
|
+
}
|
|
509
|
+
throw new Error('User not authenticated');
|
|
510
|
+
}}
|
|
511
|
+
>
|
|
512
|
+
<YourApp />
|
|
513
|
+
</DismissibleProvider>
|
|
514
|
+
);
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
// With Auth0
|
|
518
|
+
function AppWithAuth0() {
|
|
519
|
+
const { getAccessTokenSilently } = useAuth0();
|
|
520
|
+
|
|
521
|
+
return (
|
|
522
|
+
<DismissibleProvider jwt={async () => await getAccessTokenSilently()}>
|
|
523
|
+
<YourApp />
|
|
524
|
+
</DismissibleProvider>
|
|
525
|
+
);
|
|
526
|
+
}
|
|
527
|
+
```
|
|
528
|
+
|
|
409
529
|
### Using the Hook for Complex Logic
|
|
410
530
|
|
|
411
531
|
```tsx
|
|
@@ -446,10 +566,10 @@ function SmartNotification({ id, message, type = 'info' }) {
|
|
|
446
566
|
);
|
|
447
567
|
}
|
|
448
568
|
|
|
449
|
-
// Usage with authentication
|
|
569
|
+
// Usage with async authentication
|
|
450
570
|
function App() {
|
|
451
571
|
return (
|
|
452
|
-
<DismissibleProvider jwt={() => getUserToken()}>
|
|
572
|
+
<DismissibleProvider jwt={async () => await getUserToken()}>
|
|
453
573
|
<SmartNotification
|
|
454
574
|
id="user-specific-notification"
|
|
455
575
|
message="Welcome back!"
|
|
@@ -1 +1 @@
|
|
|
1
|
-
(function(a,u){typeof exports=="object"&&typeof module!="undefined"?u(exports,require("react/jsx-runtime"),require("react")):typeof define=="function"&&define.amd?define(["exports","react/jsx-runtime","react"],u):(a=typeof globalThis!="undefined"?globalThis:a||self,u(a.DismissibleClient={},a.React.jsxRuntime,a.React))})(this,function(a,u,l){"use strict";var Te=Object.defineProperty,Ue=Object.defineProperties;var qe=Object.getOwnPropertyDescriptors;var W=Object.getOwnPropertySymbols;var de=Object.prototype.hasOwnProperty,he=Object.prototype.propertyIsEnumerable;var fe=(a,u,l)=>u in a?Te(a,u,{enumerable:!0,configurable:!0,writable:!0,value:l}):a[u]=l,p=(a,u)=>{for(var l in u||(u={}))de.call(u,l)&&fe(a,l,u[l]);if(W)for(var l of W(u))he.call(u,l)&&fe(a,l,u[l]);return a},S=(a,u)=>Ue(a,qe(u));var Y=(a,u)=>{var l={};for(var C in a)de.call(a,C)&&u.indexOf(C)<0&&(l[C]=a[C]);if(a!=null&&W)for(var C of W(a))u.indexOf(C)<0&&he.call(a,C)&&(l[C]=a[C]);return l};var O=(a,u,l)=>new Promise((C,L)=>{var V=I=>{try{T(l.next(I))}catch(k){L(k)}},B=I=>{try{T(l.throw(I))}catch(k){L(k)}},T=I=>I.done?C(I.value):Promise.resolve(I.value).then(V,B);T((l=l.apply(a,u)).next())});const C=/\{[^{}]+\}/g,L=()=>{var e,r;return typeof process=="object"&&Number.parseInt((r=(e=process==null?void 0:process.versions)==null?void 0:e.node)==null?void 0:r.substring(0,2))>=18&&process.versions.undici};function V(){return Math.random().toString(36).slice(2,11)}function B(e){let U=p({},e),{baseUrl:r="",Request:t=globalThis.Request,fetch:n=globalThis.fetch,querySerializer:i,bodySerializer:s,headers:o,requestInitExt:d=void 0}=U,h=Y(U,["baseUrl","Request","fetch","querySerializer","bodySerializer","headers","requestInitExt"]);d=L()?d:void 0,r=te(r);const g=[];function E(f,c){return O(this,null,function*(){var ue;const ce=c||{},{baseUrl:A,fetch:D=n,Request:H=t,headers:x,params:$={},parseAs:F="json",querySerializer:z,bodySerializer:m=s!=null?s:ye,body:y}=ce,j=Y(ce,["baseUrl","fetch","Request","headers","params","parseAs","querySerializer","bodySerializer","body"]);let R=r;A&&(R=(ue=te(A))!=null?ue:r);let K=typeof i=="function"?i:Z(i);z&&(K=typeof z=="function"?z:Z(p(p({},typeof i=="object"?i:{}),z)));const Q=y===void 0?void 0:m(y,ee(o,x,$.header)),De=ee(Q===void 0||Q instanceof FormData?{}:{"Content-Type":"application/json"},o,x,$.header),$e=S(p(p({redirect:"follow"},h),j),{body:Q,headers:De});let J,M,q=new t(be(f,{baseUrl:R,params:$,querySerializer:K}),$e),b;for(const v in j)v in q||(q[v]=j[v]);if(g.length){J=V(),M=Object.freeze({baseUrl:R,fetch:D,parseAs:F,querySerializer:K,bodySerializer:m});for(const v of g)if(v&&typeof v=="object"&&typeof v.onRequest=="function"){const w=yield v.onRequest({request:q,schemaPath:f,params:$,options:M,id:J});if(w)if(w instanceof t)q=w;else if(w instanceof Response){b=w;break}else throw new Error("onRequest: must return new Request() or Response() when modifying the request")}}if(!b){try{b=yield D(q,d)}catch(v){let w=v;if(g.length)for(let P=g.length-1;P>=0;P--){const _=g[P];if(_&&typeof _=="object"&&typeof _.onError=="function"){const N=yield _.onError({request:q,error:w,schemaPath:f,params:$,options:M,id:J});if(N){if(N instanceof Response){w=void 0,b=N;break}if(N instanceof Error){w=N;continue}throw new Error("onError: must return new Response() or instance of Error")}}}if(w)throw w}if(g.length)for(let v=g.length-1;v>=0;v--){const w=g[v];if(w&&typeof w=="object"&&typeof w.onResponse=="function"){const P=yield w.onResponse({request:q,response:b,schemaPath:f,params:$,options:M,id:J});if(P){if(!(P instanceof Response))throw new Error("onResponse: must return new Response() when modifying the response");b=P}}}}if(b.status===204||q.method==="HEAD"||b.headers.get("Content-Length")==="0")return b.ok?{data:void 0,response:b}:{error:void 0,response:b};if(b.ok)return F==="stream"?{data:b.body,response:b}:{data:yield b[F](),response:b};let X=yield b.text();try{X=JSON.parse(X)}catch(v){}return{error:X,response:b}})}return{request(f,c,A){return E(c,S(p({},A),{method:f.toUpperCase()}))},GET(f,c){return E(f,S(p({},c),{method:"GET"}))},PUT(f,c){return E(f,S(p({},c),{method:"PUT"}))},POST(f,c){return E(f,S(p({},c),{method:"POST"}))},DELETE(f,c){return E(f,S(p({},c),{method:"DELETE"}))},OPTIONS(f,c){return E(f,S(p({},c),{method:"OPTIONS"}))},HEAD(f,c){return E(f,S(p({},c),{method:"HEAD"}))},PATCH(f,c){return E(f,S(p({},c),{method:"PATCH"}))},TRACE(f,c){return E(f,S(p({},c),{method:"TRACE"}))},use(...f){for(const c of f)if(c){if(typeof c!="object"||!("onRequest"in c||"onResponse"in c||"onError"in c))throw new Error("Middleware must be an object with one of `onRequest()`, `onResponse() or `onError()`");g.push(c)}},eject(...f){for(const c of f){const A=g.indexOf(c);A!==-1&&g.splice(A,1)}}}}function T(e,r,t){if(r==null)return"";if(typeof r=="object")throw new Error("Deeply-nested arrays/objects arenβt supported. Provide your own `querySerializer()` to handle these.");return`${e}=${(t==null?void 0:t.allowReserved)===!0?r:encodeURIComponent(r)}`}function I(e,r,t){if(!r||typeof r!="object")return"";const n=[],i={simple:",",label:".",matrix:";"}[t.style]||"&";if(t.style!=="deepObject"&&t.explode===!1){for(const d in r)n.push(d,t.allowReserved===!0?r[d]:encodeURIComponent(r[d]));const o=n.join(",");switch(t.style){case"form":return`${e}=${o}`;case"label":return`.${o}`;case"matrix":return`;${e}=${o}`;default:return o}}for(const o in r){const d=t.style==="deepObject"?`${e}[${o}]`:o;n.push(T(d,r[o],t))}const s=n.join(i);return t.style==="label"||t.style==="matrix"?`${i}${s}`:s}function k(e,r,t){if(!Array.isArray(r))return"";if(t.explode===!1){const s={form:",",spaceDelimited:"%20",pipeDelimited:"|"}[t.style]||",",o=(t.allowReserved===!0?r:r.map(d=>encodeURIComponent(d))).join(s);switch(t.style){case"simple":return o;case"label":return`.${o}`;case"matrix":return`;${e}=${o}`;default:return`${e}=${o}`}}const n={simple:",",label:".",matrix:";"}[t.style]||"&",i=[];for(const s of r)t.style==="simple"||t.style==="label"?i.push(t.allowReserved===!0?s:encodeURIComponent(s)):i.push(T(e,s,t));return t.style==="label"||t.style==="matrix"?`${n}${i.join(n)}`:i.join(n)}function Z(e){return function(t){const n=[];if(t&&typeof t=="object")for(const i in t){const s=t[i];if(s!=null){if(Array.isArray(s)){if(s.length===0)continue;n.push(k(i,s,S(p({style:"form",explode:!0},e==null?void 0:e.array),{allowReserved:(e==null?void 0:e.allowReserved)||!1})));continue}if(typeof s=="object"){n.push(I(i,s,S(p({style:"deepObject",explode:!0},e==null?void 0:e.object),{allowReserved:(e==null?void 0:e.allowReserved)||!1})));continue}n.push(T(i,s,e))}}return n.join("&")}}function me(e,r){var n;let t=e;for(const i of(n=e.match(C))!=null?n:[]){let s=i.substring(1,i.length-1),o=!1,d="simple";if(s.endsWith("*")&&(o=!0,s=s.substring(0,s.length-1)),s.startsWith(".")?(d="label",s=s.substring(1)):s.startsWith(";")&&(d="matrix",s=s.substring(1)),!r||r[s]===void 0||r[s]===null)continue;const h=r[s];if(Array.isArray(h)){t=t.replace(i,k(s,h,{style:d,explode:o}));continue}if(typeof h=="object"){t=t.replace(i,I(s,h,{style:d,explode:o}));continue}if(d==="matrix"){t=t.replace(i,`;${T(s,h)}`);continue}t=t.replace(i,d==="label"?`.${encodeURIComponent(h)}`:encodeURIComponent(h))}return t}function ye(e,r){var t,n;return e instanceof FormData?e:r&&(r.get instanceof Function?(t=r.get("Content-Type"))!=null?t:r.get("content-type"):(n=r["Content-Type"])!=null?n:r["content-type"])==="application/x-www-form-urlencoded"?new URLSearchParams(e).toString():JSON.stringify(e)}function be(e,r){var i,s;let t=`${r.baseUrl}${e}`;(i=r.params)!=null&&i.path&&(t=me(t,r.params.path));let n=r.querySerializer((s=r.params.query)!=null?s:{});return n.startsWith("?")&&(n=n.substring(1)),n&&(t+=`?${n}`),t}function ee(...e){const r=new Headers;for(const t of e){if(!t||typeof t!="object")continue;const n=t instanceof Headers?t.entries():Object.entries(t);for(const[i,s]of n)if(s===null)r.delete(i);else if(Array.isArray(s))for(const o of s)r.append(i,o);else s!==void 0&&r.set(i,s)}return r}function te(e){return e.endsWith("/")?e.substring(0,e.length-1):e}const pe={baseUrl:"http://localhost:3200"},ge={development:{baseUrl:"http://localhost:3200"},staging:{baseUrl:"https://api.staging.dismissible.io"},production:{baseUrl:"https://api.dismissible.io"}},we=()=>ge["production"]||pe,re=(e,r,t)=>{try{const n=`${r}_${e}`,i=localStorage.getItem(n);if(!i)return null;const{data:s,timestamp:o}=JSON.parse(i);return t&&Date.now()-o>t?(localStorage.removeItem(n),null):s}catch(n){return null}},se=(e,r,t)=>{try{const n=`${t}_${e}`,i={data:r,timestamp:Date.now()};localStorage.setItem(n,JSON.stringify(i))}catch(n){console.warn("Failed to cache dismissible item:",n)}},ne=(e,r)=>{try{const t=`${r}_${e}`;localStorage.removeItem(t)}catch(t){console.warn("Failed to remove cached dismissible item:",t)}},G=l.createContext(null),ie=()=>l.useContext(G),ve="dismissible",oe=(e,r={})=>{var z;const{initialData:t,enableCache:n=!0,cachePrefix:i=ve,cacheExpiration:s}=r,o=ie(),d=l.useMemo(()=>{const m=we(),y=(o==null?void 0:o.baseUrl)||m.baseUrl;return B({baseUrl:y,headers:{}})},[o]),h=l.useMemo(()=>!!(o!=null&&o.jwt)?`${e}-auth`:e,[e,o==null?void 0:o.jwt]),g=l.useRef({enableCache:n,cachePrefix:i,cacheExpiration:s}),E=l.useRef(e),U=l.useRef(h),[f,c]=l.useState(!1),[A,D]=l.useState(null),[H,x]=l.useState(()=>{if(t)return t;if(n){const m=re(h,i,s);if(m)return m}}),$=l.useCallback(()=>O(this,null,function*(){var m;if(n){const y=re(h,i,s);if(y!=null&&y.dismissedAt){x(y),c(!1);return}}c(!0),D(null);try{const y=o!=null&&o.getAuthHeaders?yield o.getAuthHeaders():{},{data:j,error:R}=yield d.GET("/v1/dismissible/{itemId}",{params:{path:{itemId:e}},headers:y});if(R)throw new Error(((m=R==null?void 0:R.error)==null?void 0:m.message)||"Failed to fetch dismissible item");x(j.data),n&&j.data&&se(h,j.data,i)}catch(y){D(y instanceof Error?y:new Error("Unknown error occurred"))}finally{c(!1)}}),[e,h,n,i,s,d,o]);l.useEffect(()=>{const m=E.current!==e,y=U.current!==h;m||y?(E.current=e,U.current=h,$()):t||$()},[e,h,t]),l.useEffect(()=>{const m=g.current;(m.enableCache!==n||m.cachePrefix!==i||m.cacheExpiration!==s)&&(m.cachePrefix!==i&&ne(h,m.cachePrefix),!n&&m.enableCache&&ne(h,i),g.current={enableCache:n,cachePrefix:i,cacheExpiration:s},$())},[n,i,s,h]);const F=l.useCallback(()=>O(this,null,function*(){var m;D(null);try{const y=o!=null&&o.getAuthHeaders?yield o.getAuthHeaders():{},{data:j,error:R}=yield d.DELETE("/v1/dismissible/{itemId}",{params:{path:{itemId:e}},headers:y});if(R)throw new Error(((m=R==null?void 0:R.error)==null?void 0:m.message)||"Failed to dismiss item");x(j.data),n&&j.data&&se(h,j.data,i)}catch(y){throw D(y instanceof Error?y:new Error("Failed to dismiss item")),y}}),[h,n,i,d,o]);return{dismissedOn:(z=H==null?void 0:H.dismissedAt)!=null?z:null,dismiss:F,isLoading:f,error:A,item:H}},Ee=()=>u.jsx("div",{className:"dismissible-loading","aria-live":"polite",children:"Loading..."}),Ce=({error:e})=>u.jsxs("div",{className:"dismissible-error",role:"alert",children:["Error loading dismissible item: ",e.message]}),Re=({id:e,onDismiss:r,ariaLabel:t})=>u.jsx("button",{id:e,className:"dismissible-button",onClick:r,"aria-label":t,type:"button",children:"Γ"}),Se=({id:e,children:r,onDismiss:t,LoadingComponent:n=Ee,ErrorComponent:i=Ce,DismissButtonComponent:s=Re,enableCache:o,cachePrefix:d,cacheExpiration:h,ignoreErrors:g=!1})=>{const{dismissedOn:E,isLoading:U,error:f,dismiss:c}=oe(e,{enableCache:o,cachePrefix:d,cacheExpiration:h}),[A,D]=l.useState(!1),H=()=>O(this,null,function*(){D(!0);try{yield c(),t==null||t()}catch(x){D(!1)}});return U&&n?u.jsx(n,{id:e}):U&&!n?null:f&&i&&!g?u.jsx(i,{id:e,error:f}):E||A?null:u.jsxs("div",{className:"dismissible-container",children:[u.jsx("div",{className:"dismissible-content",children:r}),s?u.jsx(s,{id:e,onDismiss:H,ariaLabel:`Dismiss ${e}`}):null]})},ae=e=>O(this,null,function*(){if(typeof e=="function")try{const r=e();return yield Promise.resolve(r)}catch(r){console.warn("Failed to resolve JWT from function:",r);return}return e}),le=e=>O(this,null,function*(){const r=yield ae(e);return r?{Authorization:`Bearer ${r}`}:{}}),je=e=>{const r=e.split(".");return r.length===3&&r.every(t=>t.length>0)},Ae=({jwt:e,baseUrl:r,children:t})=>{const n=l.useMemo(()=>({jwt:e,baseUrl:r,getAuthHeaders:()=>O(this,null,function*(){return yield le(e)})}),[e,r]);return u.jsx(G.Provider,{value:n,children:t})},Ie="0.3.0";a.Dismissible=Se,a.DismissibleContext=G,a.DismissibleProvider=Ae,a.VERSION=Ie,a.getAuthHeaders=le,a.isValidJwtFormat=je,a.resolveJwt=ae,a.useDismissibleContext=ie,a.useDismissibleItem=oe,Object.defineProperty(a,Symbol.toStringTag,{value:"Module"})});
|
|
1
|
+
(function(a,u){typeof exports=="object"&&typeof module!="undefined"?u(exports,require("react/jsx-runtime"),require("react")):typeof define=="function"&&define.amd?define(["exports","react/jsx-runtime","react"],u):(a=typeof globalThis!="undefined"?globalThis:a||self,u(a.DismissibleClient={},a.React.jsxRuntime,a.React))})(this,function(a,u,l){"use strict";var Te=Object.defineProperty,Ue=Object.defineProperties;var qe=Object.getOwnPropertyDescriptors;var W=Object.getOwnPropertySymbols;var de=Object.prototype.hasOwnProperty,he=Object.prototype.propertyIsEnumerable;var fe=(a,u,l)=>u in a?Te(a,u,{enumerable:!0,configurable:!0,writable:!0,value:l}):a[u]=l,p=(a,u)=>{for(var l in u||(u={}))de.call(u,l)&&fe(a,l,u[l]);if(W)for(var l of W(u))he.call(u,l)&&fe(a,l,u[l]);return a},S=(a,u)=>Ue(a,qe(u));var Y=(a,u)=>{var l={};for(var C in a)de.call(a,C)&&u.indexOf(C)<0&&(l[C]=a[C]);if(a!=null&&W)for(var C of W(a))u.indexOf(C)<0&&he.call(a,C)&&(l[C]=a[C]);return l};var O=(a,u,l)=>new Promise((C,L)=>{var V=I=>{try{T(l.next(I))}catch(k){L(k)}},B=I=>{try{T(l.throw(I))}catch(k){L(k)}},T=I=>I.done?C(I.value):Promise.resolve(I.value).then(V,B);T((l=l.apply(a,u)).next())});const C=/\{[^{}]+\}/g,L=()=>{var e,r;return typeof process=="object"&&Number.parseInt((r=(e=process==null?void 0:process.versions)==null?void 0:e.node)==null?void 0:r.substring(0,2))>=18&&process.versions.undici};function V(){return Math.random().toString(36).slice(2,11)}function B(e){let U=p({},e),{baseUrl:r="",Request:t=globalThis.Request,fetch:n=globalThis.fetch,querySerializer:i,bodySerializer:s,headers:o,requestInitExt:d=void 0}=U,h=Y(U,["baseUrl","Request","fetch","querySerializer","bodySerializer","headers","requestInitExt"]);d=L()?d:void 0,r=te(r);const g=[];function E(f,c){return O(this,null,function*(){var ue;const ce=c||{},{baseUrl:A,fetch:D=n,Request:H=t,headers:x,params:$={},parseAs:F="json",querySerializer:z,bodySerializer:m=s!=null?s:ye,body:y}=ce,j=Y(ce,["baseUrl","fetch","Request","headers","params","parseAs","querySerializer","bodySerializer","body"]);let R=r;A&&(R=(ue=te(A))!=null?ue:r);let K=typeof i=="function"?i:Z(i);z&&(K=typeof z=="function"?z:Z(p(p({},typeof i=="object"?i:{}),z)));const Q=y===void 0?void 0:m(y,ee(o,x,$.header)),De=ee(Q===void 0||Q instanceof FormData?{}:{"Content-Type":"application/json"},o,x,$.header),$e=S(p(p({redirect:"follow"},h),j),{body:Q,headers:De});let J,M,q=new t(be(f,{baseUrl:R,params:$,querySerializer:K}),$e),b;for(const v in j)v in q||(q[v]=j[v]);if(g.length){J=V(),M=Object.freeze({baseUrl:R,fetch:D,parseAs:F,querySerializer:K,bodySerializer:m});for(const v of g)if(v&&typeof v=="object"&&typeof v.onRequest=="function"){const w=yield v.onRequest({request:q,schemaPath:f,params:$,options:M,id:J});if(w)if(w instanceof t)q=w;else if(w instanceof Response){b=w;break}else throw new Error("onRequest: must return new Request() or Response() when modifying the request")}}if(!b){try{b=yield D(q,d)}catch(v){let w=v;if(g.length)for(let P=g.length-1;P>=0;P--){const _=g[P];if(_&&typeof _=="object"&&typeof _.onError=="function"){const N=yield _.onError({request:q,error:w,schemaPath:f,params:$,options:M,id:J});if(N){if(N instanceof Response){w=void 0,b=N;break}if(N instanceof Error){w=N;continue}throw new Error("onError: must return new Response() or instance of Error")}}}if(w)throw w}if(g.length)for(let v=g.length-1;v>=0;v--){const w=g[v];if(w&&typeof w=="object"&&typeof w.onResponse=="function"){const P=yield w.onResponse({request:q,response:b,schemaPath:f,params:$,options:M,id:J});if(P){if(!(P instanceof Response))throw new Error("onResponse: must return new Response() when modifying the response");b=P}}}}if(b.status===204||q.method==="HEAD"||b.headers.get("Content-Length")==="0")return b.ok?{data:void 0,response:b}:{error:void 0,response:b};if(b.ok)return F==="stream"?{data:b.body,response:b}:{data:yield b[F](),response:b};let X=yield b.text();try{X=JSON.parse(X)}catch(v){}return{error:X,response:b}})}return{request(f,c,A){return E(c,S(p({},A),{method:f.toUpperCase()}))},GET(f,c){return E(f,S(p({},c),{method:"GET"}))},PUT(f,c){return E(f,S(p({},c),{method:"PUT"}))},POST(f,c){return E(f,S(p({},c),{method:"POST"}))},DELETE(f,c){return E(f,S(p({},c),{method:"DELETE"}))},OPTIONS(f,c){return E(f,S(p({},c),{method:"OPTIONS"}))},HEAD(f,c){return E(f,S(p({},c),{method:"HEAD"}))},PATCH(f,c){return E(f,S(p({},c),{method:"PATCH"}))},TRACE(f,c){return E(f,S(p({},c),{method:"TRACE"}))},use(...f){for(const c of f)if(c){if(typeof c!="object"||!("onRequest"in c||"onResponse"in c||"onError"in c))throw new Error("Middleware must be an object with one of `onRequest()`, `onResponse() or `onError()`");g.push(c)}},eject(...f){for(const c of f){const A=g.indexOf(c);A!==-1&&g.splice(A,1)}}}}function T(e,r,t){if(r==null)return"";if(typeof r=="object")throw new Error("Deeply-nested arrays/objects arenβt supported. Provide your own `querySerializer()` to handle these.");return`${e}=${(t==null?void 0:t.allowReserved)===!0?r:encodeURIComponent(r)}`}function I(e,r,t){if(!r||typeof r!="object")return"";const n=[],i={simple:",",label:".",matrix:";"}[t.style]||"&";if(t.style!=="deepObject"&&t.explode===!1){for(const d in r)n.push(d,t.allowReserved===!0?r[d]:encodeURIComponent(r[d]));const o=n.join(",");switch(t.style){case"form":return`${e}=${o}`;case"label":return`.${o}`;case"matrix":return`;${e}=${o}`;default:return o}}for(const o in r){const d=t.style==="deepObject"?`${e}[${o}]`:o;n.push(T(d,r[o],t))}const s=n.join(i);return t.style==="label"||t.style==="matrix"?`${i}${s}`:s}function k(e,r,t){if(!Array.isArray(r))return"";if(t.explode===!1){const s={form:",",spaceDelimited:"%20",pipeDelimited:"|"}[t.style]||",",o=(t.allowReserved===!0?r:r.map(d=>encodeURIComponent(d))).join(s);switch(t.style){case"simple":return o;case"label":return`.${o}`;case"matrix":return`;${e}=${o}`;default:return`${e}=${o}`}}const n={simple:",",label:".",matrix:";"}[t.style]||"&",i=[];for(const s of r)t.style==="simple"||t.style==="label"?i.push(t.allowReserved===!0?s:encodeURIComponent(s)):i.push(T(e,s,t));return t.style==="label"||t.style==="matrix"?`${n}${i.join(n)}`:i.join(n)}function Z(e){return function(t){const n=[];if(t&&typeof t=="object")for(const i in t){const s=t[i];if(s!=null){if(Array.isArray(s)){if(s.length===0)continue;n.push(k(i,s,S(p({style:"form",explode:!0},e==null?void 0:e.array),{allowReserved:(e==null?void 0:e.allowReserved)||!1})));continue}if(typeof s=="object"){n.push(I(i,s,S(p({style:"deepObject",explode:!0},e==null?void 0:e.object),{allowReserved:(e==null?void 0:e.allowReserved)||!1})));continue}n.push(T(i,s,e))}}return n.join("&")}}function me(e,r){var n;let t=e;for(const i of(n=e.match(C))!=null?n:[]){let s=i.substring(1,i.length-1),o=!1,d="simple";if(s.endsWith("*")&&(o=!0,s=s.substring(0,s.length-1)),s.startsWith(".")?(d="label",s=s.substring(1)):s.startsWith(";")&&(d="matrix",s=s.substring(1)),!r||r[s]===void 0||r[s]===null)continue;const h=r[s];if(Array.isArray(h)){t=t.replace(i,k(s,h,{style:d,explode:o}));continue}if(typeof h=="object"){t=t.replace(i,I(s,h,{style:d,explode:o}));continue}if(d==="matrix"){t=t.replace(i,`;${T(s,h)}`);continue}t=t.replace(i,d==="label"?`.${encodeURIComponent(h)}`:encodeURIComponent(h))}return t}function ye(e,r){var t,n;return e instanceof FormData?e:r&&(r.get instanceof Function?(t=r.get("Content-Type"))!=null?t:r.get("content-type"):(n=r["Content-Type"])!=null?n:r["content-type"])==="application/x-www-form-urlencoded"?new URLSearchParams(e).toString():JSON.stringify(e)}function be(e,r){var i,s;let t=`${r.baseUrl}${e}`;(i=r.params)!=null&&i.path&&(t=me(t,r.params.path));let n=r.querySerializer((s=r.params.query)!=null?s:{});return n.startsWith("?")&&(n=n.substring(1)),n&&(t+=`?${n}`),t}function ee(...e){const r=new Headers;for(const t of e){if(!t||typeof t!="object")continue;const n=t instanceof Headers?t.entries():Object.entries(t);for(const[i,s]of n)if(s===null)r.delete(i);else if(Array.isArray(s))for(const o of s)r.append(i,o);else s!==void 0&&r.set(i,s)}return r}function te(e){return e.endsWith("/")?e.substring(0,e.length-1):e}const pe={baseUrl:"http://localhost:3200"},ge={development:{baseUrl:"http://localhost:3200"},staging:{baseUrl:"https://api.staging.dismissible.io"},production:{baseUrl:"https://api.dismissible.io"}},we=()=>ge["production"]||pe,re=(e,r,t)=>{try{const n=`${r}_${e}`,i=localStorage.getItem(n);if(!i)return null;const{data:s,timestamp:o}=JSON.parse(i);return t&&Date.now()-o>t?(localStorage.removeItem(n),null):s}catch(n){return null}},se=(e,r,t)=>{try{const n=`${t}_${e}`,i={data:r,timestamp:Date.now()};localStorage.setItem(n,JSON.stringify(i))}catch(n){console.warn("Failed to cache dismissible item:",n)}},ne=(e,r)=>{try{const t=`${r}_${e}`;localStorage.removeItem(t)}catch(t){console.warn("Failed to remove cached dismissible item:",t)}},G=l.createContext(null),ie=()=>l.useContext(G),ve="dismissible",oe=(e,r={})=>{var z;const{initialData:t,enableCache:n=!0,cachePrefix:i=ve,cacheExpiration:s}=r,o=ie(),d=l.useMemo(()=>{const m=we(),y=(o==null?void 0:o.baseUrl)||m.baseUrl;return B({baseUrl:y,headers:{}})},[o]),h=l.useMemo(()=>!!(o!=null&&o.jwt)?`${e}-auth`:e,[e,o==null?void 0:o.jwt]),g=l.useRef({enableCache:n,cachePrefix:i,cacheExpiration:s}),E=l.useRef(e),U=l.useRef(h),[f,c]=l.useState(!1),[A,D]=l.useState(null),[H,x]=l.useState(()=>{if(t)return t;if(n){const m=re(h,i,s);if(m)return m}}),$=l.useCallback(()=>O(this,null,function*(){var m;if(n){const y=re(h,i,s);if(y!=null&&y.dismissedAt){x(y),c(!1);return}}c(!0),D(null);try{const y=o!=null&&o.getAuthHeaders?yield o.getAuthHeaders():{},{data:j,error:R}=yield d.GET("/v1/dismissible/{itemId}",{params:{path:{itemId:e}},headers:y});if(R)throw new Error(((m=R==null?void 0:R.error)==null?void 0:m.message)||"Failed to fetch dismissible item");x(j.data),n&&j.data&&se(h,j.data,i)}catch(y){D(y instanceof Error?y:new Error("Unknown error occurred"))}finally{c(!1)}}),[e,h,n,i,s,d,o]);l.useEffect(()=>{const m=E.current!==e,y=U.current!==h;m||y?(E.current=e,U.current=h,$()):t||$()},[e,h,t]),l.useEffect(()=>{const m=g.current;(m.enableCache!==n||m.cachePrefix!==i||m.cacheExpiration!==s)&&(m.cachePrefix!==i&&ne(h,m.cachePrefix),!n&&m.enableCache&&ne(h,i),g.current={enableCache:n,cachePrefix:i,cacheExpiration:s},$())},[n,i,s,h]);const F=l.useCallback(()=>O(this,null,function*(){var m;D(null);try{const y=o!=null&&o.getAuthHeaders?yield o.getAuthHeaders():{},{data:j,error:R}=yield d.DELETE("/v1/dismissible/{itemId}",{params:{path:{itemId:e}},headers:y});if(R)throw new Error(((m=R==null?void 0:R.error)==null?void 0:m.message)||"Failed to dismiss item");x(j.data),n&&j.data&&se(h,j.data,i)}catch(y){throw D(y instanceof Error?y:new Error("Failed to dismiss item")),y}}),[h,n,i,d,o]);return{dismissedOn:(z=H==null?void 0:H.dismissedAt)!=null?z:null,dismiss:F,isLoading:f,error:A,item:H}},Ee=()=>u.jsx("div",{className:"dismissible-loading","aria-live":"polite",children:"Loading..."}),Ce=({error:e})=>u.jsxs("div",{className:"dismissible-error",role:"alert",children:["Error loading dismissible item: ",e.message]}),Re=({id:e,onDismiss:r,ariaLabel:t})=>u.jsx("button",{id:e,className:"dismissible-button",onClick:r,"aria-label":t,type:"button",children:"Γ"}),Se=({id:e,children:r,onDismiss:t,LoadingComponent:n=Ee,ErrorComponent:i=Ce,DismissButtonComponent:s=Re,enableCache:o,cachePrefix:d,cacheExpiration:h,ignoreErrors:g=!1})=>{const{dismissedOn:E,isLoading:U,error:f,dismiss:c}=oe(e,{enableCache:o,cachePrefix:d,cacheExpiration:h}),[A,D]=l.useState(!1),H=()=>O(this,null,function*(){D(!0);try{yield c(),t==null||t()}catch(x){D(!1)}});return U&&n?u.jsx(n,{id:e}):U&&!n?null:f&&i&&!g?u.jsx(i,{id:e,error:f}):E||A?null:u.jsxs("div",{className:"dismissible-container",children:[u.jsx("div",{className:"dismissible-content",children:r}),s?u.jsx(s,{id:e,onDismiss:H,ariaLabel:`Dismiss ${e}`}):null]})},ae=e=>O(this,null,function*(){if(typeof e=="function")try{const r=e();return yield Promise.resolve(r)}catch(r){console.warn("Failed to resolve JWT from function:",r);return}return e}),le=e=>O(this,null,function*(){const r=yield ae(e);return r?{Authorization:`Bearer ${r}`}:{}}),je=e=>{const r=e.split(".");return r.length===3&&r.every(t=>t.length>0)},Ae=({jwt:e,baseUrl:r,children:t})=>{const n=l.useMemo(()=>({jwt:e,baseUrl:r,getAuthHeaders:()=>O(this,null,function*(){return yield le(e)})}),[e,r]);return u.jsx(G.Provider,{value:n,children:t})},Ie="0.3.1";a.Dismissible=Se,a.DismissibleContext=G,a.DismissibleProvider=Ae,a.VERSION=Ie,a.getAuthHeaders=le,a.isValidJwtFormat=je,a.resolveJwt=ae,a.useDismissibleContext=ie,a.useDismissibleItem=oe,Object.defineProperty(a,Symbol.toStringTag,{value:"Module"})});
|
package/dist/root.d.ts
CHANGED