@dismissible/react-client 0.1.0 β 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +161 -1
- package/dist/contexts/DismissibleContext.d.ts +10 -0
- package/dist/contexts/DismissibleProvider.d.ts +22 -0
- package/dist/dismissible-client.es.js +356 -305
- package/dist/dismissible-client.umd.js +1 -1
- package/dist/root.d.ts +4 -0
- package/dist/types/dismissible.types.d.ts +36 -0
- package/dist/utils/auth.utils.d.ts +19 -0
- package/package.json +3 -3
- package/dist/utils/msw-toggle.d.ts +0 -13
package/README.md
CHANGED
|
@@ -9,6 +9,7 @@ A React component library for creating dismissible UI elements with persistent s
|
|
|
9
9
|
|
|
10
10
|
- π― **Easy to use** - Simple component API for dismissible content
|
|
11
11
|
- πΎ **Persistent state** - Dismissal state is saved and restored across sessions
|
|
12
|
+
- π **JWT Authentication** - Built-in support for JWT-based user authentication
|
|
12
13
|
- π¨ **Customizable** - Custom loading, error, and dismiss button components
|
|
13
14
|
- βΏ **Accessible** - Built with accessibility best practices
|
|
14
15
|
- πͺ **Hook-based** - Includes `useDismissibleItem` hook for custom implementations
|
|
@@ -49,6 +50,51 @@ function App() {
|
|
|
49
50
|
|
|
50
51
|
## API Reference
|
|
51
52
|
|
|
53
|
+
### `<DismissibleProvider>` Component
|
|
54
|
+
|
|
55
|
+
Context provider for JWT authentication and configuration. Wrap your app or components that need JWT authentication.
|
|
56
|
+
|
|
57
|
+
#### Props
|
|
58
|
+
|
|
59
|
+
| Prop | Type | Required | Description |
|
|
60
|
+
|------|------|----------|-------------|
|
|
61
|
+
| `jwt` | `string \| (() => string)` | β | JWT token (static string or function) |
|
|
62
|
+
| `baseUrl` | `string` | β | Custom API base URL override |
|
|
63
|
+
| `children` | `ReactNode` | β
| Components that will use the dismissible functionality |
|
|
64
|
+
|
|
65
|
+
#### Example
|
|
66
|
+
|
|
67
|
+
```tsx
|
|
68
|
+
import { DismissibleProvider } from '@dismissible/react-client';
|
|
69
|
+
|
|
70
|
+
// With static JWT
|
|
71
|
+
function App() {
|
|
72
|
+
return (
|
|
73
|
+
<DismissibleProvider jwt="eyJhbGciOiJIUzI1NiIs...">
|
|
74
|
+
<YourApp />
|
|
75
|
+
</DismissibleProvider>
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// With dynamic JWT function
|
|
80
|
+
function AppWithDynamicAuth() {
|
|
81
|
+
return (
|
|
82
|
+
<DismissibleProvider jwt={() => getAccessToken()}>
|
|
83
|
+
<YourApp />
|
|
84
|
+
</DismissibleProvider>
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Without JWT (anonymous/backwards compatible)
|
|
89
|
+
function AppWithoutAuth() {
|
|
90
|
+
return (
|
|
91
|
+
<DismissibleProvider>
|
|
92
|
+
<YourApp />
|
|
93
|
+
</DismissibleProvider>
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
52
98
|
### `<Dismissible>` Component
|
|
53
99
|
|
|
54
100
|
The main component for creating dismissible content.
|
|
@@ -131,6 +177,56 @@ function CustomDismissible({ id, children }) {
|
|
|
131
177
|
|
|
132
178
|
## Usage Examples
|
|
133
179
|
|
|
180
|
+
### JWT Authentication Setup
|
|
181
|
+
|
|
182
|
+
For enterprise accounts that require user-specific dismissible state, wrap your app with the `DismissibleProvider`:
|
|
183
|
+
|
|
184
|
+
```tsx
|
|
185
|
+
import { DismissibleProvider, Dismissible } from '@dismissible/react-client';
|
|
186
|
+
|
|
187
|
+
function App() {
|
|
188
|
+
// Example with static JWT token
|
|
189
|
+
const jwt = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...";
|
|
190
|
+
|
|
191
|
+
return (
|
|
192
|
+
<DismissibleProvider jwt={jwt}>
|
|
193
|
+
<Dashboard />
|
|
194
|
+
</DismissibleProvider>
|
|
195
|
+
);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
function Dashboard() {
|
|
199
|
+
return (
|
|
200
|
+
<div>
|
|
201
|
+
{/* These dismissible items will be user-specific */}
|
|
202
|
+
<Dismissible id="user-welcome-banner">
|
|
203
|
+
<div className="alert alert-info">
|
|
204
|
+
<h4>Welcome back!</h4>
|
|
205
|
+
<p>You have 3 new notifications.</p>
|
|
206
|
+
</div>
|
|
207
|
+
</Dismissible>
|
|
208
|
+
</div>
|
|
209
|
+
);
|
|
210
|
+
}
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
### Dynamic JWT with Authentication Provider
|
|
214
|
+
|
|
215
|
+
```tsx
|
|
216
|
+
import { DismissibleProvider } from '@dismissible/react-client';
|
|
217
|
+
import { useAuth } from './auth'; // Your auth context
|
|
218
|
+
|
|
219
|
+
function App() {
|
|
220
|
+
const { getAccessToken } = useAuth();
|
|
221
|
+
|
|
222
|
+
return (
|
|
223
|
+
<DismissibleProvider jwt={() => getAccessToken()}>
|
|
224
|
+
<YourApp />
|
|
225
|
+
</DismissibleProvider>
|
|
226
|
+
);
|
|
227
|
+
}
|
|
228
|
+
```
|
|
229
|
+
|
|
134
230
|
### Basic Dismissible Banner
|
|
135
231
|
|
|
136
232
|
```tsx
|
|
@@ -271,10 +367,49 @@ function ConditionalBanner({ user }) {
|
|
|
271
367
|
}
|
|
272
368
|
```
|
|
273
369
|
|
|
370
|
+
### User-Specific vs Anonymous Dismissible Items
|
|
371
|
+
|
|
372
|
+
The behavior changes based on whether JWT authentication is configured:
|
|
373
|
+
|
|
374
|
+
```tsx
|
|
375
|
+
import { DismissibleProvider, Dismissible } from '@dismissible/react-client';
|
|
376
|
+
|
|
377
|
+
// With JWT - dismissible state is user-specific
|
|
378
|
+
function AuthenticatedApp() {
|
|
379
|
+
return (
|
|
380
|
+
<DismissibleProvider jwt={() => getAccessToken()}>
|
|
381
|
+
<div>
|
|
382
|
+
{/* Each user will see this banner independently */}
|
|
383
|
+
<Dismissible id="feature-announcement">
|
|
384
|
+
<div>New feature available!</div>
|
|
385
|
+
</Dismissible>
|
|
386
|
+
|
|
387
|
+
{/* User A dismissing this won't affect User B */}
|
|
388
|
+
<Dismissible id="survey-request">
|
|
389
|
+
<div>Please take our survey!</div>
|
|
390
|
+
</Dismissible>
|
|
391
|
+
</div>
|
|
392
|
+
</DismissibleProvider>
|
|
393
|
+
);
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
// Without JWT - dismissible state is account-level (anonymous)
|
|
397
|
+
function AnonymousApp() {
|
|
398
|
+
return (
|
|
399
|
+
<div>
|
|
400
|
+
{/* These will be dismissed for all users of this account */}
|
|
401
|
+
<Dismissible id="general-announcement">
|
|
402
|
+
<div>Site maintenance scheduled</div>
|
|
403
|
+
</Dismissible>
|
|
404
|
+
</div>
|
|
405
|
+
);
|
|
406
|
+
}
|
|
407
|
+
```
|
|
408
|
+
|
|
274
409
|
### Using the Hook for Complex Logic
|
|
275
410
|
|
|
276
411
|
```tsx
|
|
277
|
-
import { useDismissibleItem } from '@dismissible/react-client';
|
|
412
|
+
import { useDismissibleItem, DismissibleProvider } from '@dismissible/react-client';
|
|
278
413
|
import { useState, useEffect } from 'react';
|
|
279
414
|
|
|
280
415
|
function SmartNotification({ id, message, type = 'info' }) {
|
|
@@ -310,6 +445,19 @@ function SmartNotification({ id, message, type = 'info' }) {
|
|
|
310
445
|
</div>
|
|
311
446
|
);
|
|
312
447
|
}
|
|
448
|
+
|
|
449
|
+
// Usage with authentication
|
|
450
|
+
function App() {
|
|
451
|
+
return (
|
|
452
|
+
<DismissibleProvider jwt={() => getUserToken()}>
|
|
453
|
+
<SmartNotification
|
|
454
|
+
id="user-specific-notification"
|
|
455
|
+
message="Welcome back!"
|
|
456
|
+
type="info"
|
|
457
|
+
/>
|
|
458
|
+
</DismissibleProvider>
|
|
459
|
+
);
|
|
460
|
+
}
|
|
313
461
|
```
|
|
314
462
|
|
|
315
463
|
## Styling
|
|
@@ -342,12 +490,24 @@ The library is written in TypeScript and exports all type definitions:
|
|
|
342
490
|
```tsx
|
|
343
491
|
import type {
|
|
344
492
|
DismissibleProps,
|
|
493
|
+
DismissibleProviderProps,
|
|
494
|
+
JwtToken,
|
|
345
495
|
IDismissibleItem
|
|
346
496
|
} from '@dismissible/react-client';
|
|
347
497
|
|
|
498
|
+
// Dismissible component with custom props
|
|
348
499
|
const MyComponent: React.FC<DismissibleProps> = (props) => {
|
|
349
500
|
// Your component implementation
|
|
350
501
|
};
|
|
502
|
+
|
|
503
|
+
// Provider with JWT authentication
|
|
504
|
+
const AuthProvider: React.FC<DismissibleProviderProps> = ({ children, jwt }) => {
|
|
505
|
+
return (
|
|
506
|
+
<DismissibleProvider jwt={jwt}>
|
|
507
|
+
{children}
|
|
508
|
+
</DismissibleProvider>
|
|
509
|
+
);
|
|
510
|
+
};
|
|
351
511
|
```
|
|
352
512
|
|
|
353
513
|
## Development
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { DismissibleContextValue } from '../types/dismissible.types';
|
|
2
|
+
/**
|
|
3
|
+
* React context for sharing dismissible authentication state
|
|
4
|
+
*/
|
|
5
|
+
export declare const DismissibleContext: import('react').Context<DismissibleContextValue | null>;
|
|
6
|
+
/**
|
|
7
|
+
* Hook to consume the DismissibleContext
|
|
8
|
+
* @returns The context value or null if not within a provider
|
|
9
|
+
*/
|
|
10
|
+
export declare const useDismissibleContext: () => DismissibleContextValue | null;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
import { DismissibleProviderProps } from '../types/dismissible.types';
|
|
3
|
+
/**
|
|
4
|
+
* Provider component for managing dismissible authentication state
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```tsx
|
|
8
|
+
* // With static JWT
|
|
9
|
+
* <DismissibleProvider jwt="eyJhbGciOiJ..." baseUrl="https://api.dismissible.io">
|
|
10
|
+
* <App />
|
|
11
|
+
* </DismissibleProvider>
|
|
12
|
+
*
|
|
13
|
+
* // With dynamic JWT function
|
|
14
|
+
* <DismissibleProvider
|
|
15
|
+
* jwt={() => getAccessToken()}
|
|
16
|
+
* baseUrl="https://api.dismissible.io"
|
|
17
|
+
* >
|
|
18
|
+
* <App />
|
|
19
|
+
* </DismissibleProvider>
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export declare const DismissibleProvider: React.FC<DismissibleProviderProps>;
|
|
@@ -1,292 +1,292 @@
|
|
|
1
|
-
import { jsx as
|
|
2
|
-
import { useRef as
|
|
3
|
-
const
|
|
4
|
-
var e,
|
|
5
|
-
return typeof process == "object" && Number.parseInt((
|
|
1
|
+
import { jsx as I, jsxs as Q } from "react/jsx-runtime";
|
|
2
|
+
import { createContext as te, useContext as re, useMemo as N, useRef as P, useState as q, useCallback as L, useEffect as J } from "react";
|
|
3
|
+
const ne = /\{[^{}]+\}/g, se = () => {
|
|
4
|
+
var e, r;
|
|
5
|
+
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;
|
|
6
6
|
};
|
|
7
|
-
function
|
|
7
|
+
function ie() {
|
|
8
8
|
return Math.random().toString(36).slice(2, 11);
|
|
9
9
|
}
|
|
10
|
-
function
|
|
10
|
+
function oe(e) {
|
|
11
11
|
let {
|
|
12
|
-
baseUrl:
|
|
12
|
+
baseUrl: r = "",
|
|
13
13
|
Request: t = globalThis.Request,
|
|
14
14
|
fetch: s = globalThis.fetch,
|
|
15
|
-
querySerializer:
|
|
16
|
-
bodySerializer:
|
|
17
|
-
headers:
|
|
18
|
-
requestInitExt:
|
|
19
|
-
...
|
|
15
|
+
querySerializer: n,
|
|
16
|
+
bodySerializer: o,
|
|
17
|
+
headers: i,
|
|
18
|
+
requestInitExt: u = void 0,
|
|
19
|
+
...d
|
|
20
20
|
} = { ...e };
|
|
21
|
-
|
|
22
|
-
const
|
|
23
|
-
async function
|
|
21
|
+
u = se() ? u : void 0, r = W(r);
|
|
22
|
+
const m = [];
|
|
23
|
+
async function y(c, l) {
|
|
24
24
|
const {
|
|
25
25
|
baseUrl: p,
|
|
26
|
-
fetch:
|
|
27
|
-
Request:
|
|
28
|
-
headers:
|
|
29
|
-
params:
|
|
30
|
-
parseAs:
|
|
31
|
-
querySerializer:
|
|
32
|
-
bodySerializer:
|
|
33
|
-
body:
|
|
34
|
-
|
|
35
|
-
} =
|
|
36
|
-
let
|
|
37
|
-
p && (
|
|
38
|
-
let
|
|
39
|
-
|
|
40
|
-
...typeof
|
|
41
|
-
...
|
|
26
|
+
fetch: E = s,
|
|
27
|
+
Request: v = t,
|
|
28
|
+
headers: C,
|
|
29
|
+
params: w = {},
|
|
30
|
+
parseAs: S = "json",
|
|
31
|
+
querySerializer: A,
|
|
32
|
+
bodySerializer: a = o ?? ce,
|
|
33
|
+
body: g,
|
|
34
|
+
...$
|
|
35
|
+
} = l || {};
|
|
36
|
+
let z = r;
|
|
37
|
+
p && (z = W(p) ?? r);
|
|
38
|
+
let H = typeof n == "function" ? n : _(n);
|
|
39
|
+
A && (H = typeof A == "function" ? A : _({
|
|
40
|
+
...typeof n == "object" ? n : {},
|
|
41
|
+
...A
|
|
42
42
|
}));
|
|
43
|
-
const
|
|
44
|
-
|
|
43
|
+
const k = g === void 0 ? void 0 : a(
|
|
44
|
+
g,
|
|
45
45
|
// Note: we declare mergeHeaders() both here and below because itβs a bit of a chicken-or-egg situation:
|
|
46
46
|
// bodySerializer() needs all headers so we arenβt dropping ones set by the user, however,
|
|
47
47
|
// the result of this ALSO sets the lowest-priority content-type header. So we re-merge below,
|
|
48
48
|
// setting the content-type at the very beginning to be overwritten.
|
|
49
49
|
// Lastly, based on the way headers work, itβs not a simpleΒ βpresent-or-notβ check becauase null intentionally un-sets headers.
|
|
50
|
-
B(
|
|
51
|
-
),
|
|
50
|
+
B(i, C, w.header)
|
|
51
|
+
), Z = B(
|
|
52
52
|
// with no body, we should not to set Content-Type
|
|
53
|
-
|
|
54
|
-
|
|
53
|
+
k === void 0 || // if serialized body is FormData; browser will correctly set Content-Type & boundary expression
|
|
54
|
+
k instanceof FormData ? {} : {
|
|
55
55
|
"Content-Type": "application/json"
|
|
56
56
|
},
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
),
|
|
57
|
+
i,
|
|
58
|
+
C,
|
|
59
|
+
w.header
|
|
60
|
+
), ee = {
|
|
61
61
|
redirect: "follow",
|
|
62
|
-
...
|
|
63
|
-
|
|
64
|
-
body:
|
|
65
|
-
headers:
|
|
62
|
+
...d,
|
|
63
|
+
...$,
|
|
64
|
+
body: k,
|
|
65
|
+
headers: Z
|
|
66
66
|
};
|
|
67
|
-
let
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
),
|
|
71
|
-
for (const b in
|
|
72
|
-
b in
|
|
73
|
-
if (
|
|
74
|
-
|
|
75
|
-
baseUrl:
|
|
76
|
-
fetch:
|
|
77
|
-
parseAs:
|
|
78
|
-
querySerializer:
|
|
79
|
-
bodySerializer:
|
|
67
|
+
let U, T, R = new t(
|
|
68
|
+
le(c, { baseUrl: z, params: w, querySerializer: H }),
|
|
69
|
+
ee
|
|
70
|
+
), f;
|
|
71
|
+
for (const b in $)
|
|
72
|
+
b in R || (R[b] = $[b]);
|
|
73
|
+
if (m.length) {
|
|
74
|
+
U = ie(), T = Object.freeze({
|
|
75
|
+
baseUrl: z,
|
|
76
|
+
fetch: E,
|
|
77
|
+
parseAs: S,
|
|
78
|
+
querySerializer: H,
|
|
79
|
+
bodySerializer: a
|
|
80
80
|
});
|
|
81
|
-
for (const b of
|
|
81
|
+
for (const b of m)
|
|
82
82
|
if (b && typeof b == "object" && typeof b.onRequest == "function") {
|
|
83
|
-
const
|
|
84
|
-
request:
|
|
85
|
-
schemaPath:
|
|
86
|
-
params:
|
|
87
|
-
options:
|
|
88
|
-
id:
|
|
83
|
+
const h = await b.onRequest({
|
|
84
|
+
request: R,
|
|
85
|
+
schemaPath: c,
|
|
86
|
+
params: w,
|
|
87
|
+
options: T,
|
|
88
|
+
id: U
|
|
89
89
|
});
|
|
90
|
-
if (
|
|
91
|
-
if (
|
|
92
|
-
|
|
93
|
-
else if (
|
|
94
|
-
|
|
90
|
+
if (h)
|
|
91
|
+
if (h instanceof t)
|
|
92
|
+
R = h;
|
|
93
|
+
else if (h instanceof Response) {
|
|
94
|
+
f = h;
|
|
95
95
|
break;
|
|
96
96
|
} else
|
|
97
97
|
throw new Error("onRequest: must return new Request() or Response() when modifying the request");
|
|
98
98
|
}
|
|
99
99
|
}
|
|
100
|
-
if (!
|
|
100
|
+
if (!f) {
|
|
101
101
|
try {
|
|
102
|
-
|
|
102
|
+
f = await E(R, u);
|
|
103
103
|
} catch (b) {
|
|
104
|
-
let
|
|
105
|
-
if (
|
|
106
|
-
for (let
|
|
107
|
-
const
|
|
108
|
-
if (
|
|
109
|
-
const
|
|
110
|
-
request:
|
|
111
|
-
error:
|
|
112
|
-
schemaPath:
|
|
113
|
-
params:
|
|
114
|
-
options:
|
|
115
|
-
id:
|
|
104
|
+
let h = b;
|
|
105
|
+
if (m.length)
|
|
106
|
+
for (let j = m.length - 1; j >= 0; j--) {
|
|
107
|
+
const x = m[j];
|
|
108
|
+
if (x && typeof x == "object" && typeof x.onError == "function") {
|
|
109
|
+
const D = await x.onError({
|
|
110
|
+
request: R,
|
|
111
|
+
error: h,
|
|
112
|
+
schemaPath: c,
|
|
113
|
+
params: w,
|
|
114
|
+
options: T,
|
|
115
|
+
id: U
|
|
116
116
|
});
|
|
117
|
-
if (
|
|
118
|
-
if (
|
|
119
|
-
|
|
117
|
+
if (D) {
|
|
118
|
+
if (D instanceof Response) {
|
|
119
|
+
h = void 0, f = D;
|
|
120
120
|
break;
|
|
121
121
|
}
|
|
122
|
-
if (
|
|
123
|
-
|
|
122
|
+
if (D instanceof Error) {
|
|
123
|
+
h = D;
|
|
124
124
|
continue;
|
|
125
125
|
}
|
|
126
126
|
throw new Error("onError: must return new Response() or instance of Error");
|
|
127
127
|
}
|
|
128
128
|
}
|
|
129
129
|
}
|
|
130
|
-
if (
|
|
131
|
-
throw
|
|
130
|
+
if (h)
|
|
131
|
+
throw h;
|
|
132
132
|
}
|
|
133
|
-
if (
|
|
134
|
-
for (let b =
|
|
135
|
-
const
|
|
136
|
-
if (
|
|
137
|
-
const
|
|
138
|
-
request:
|
|
139
|
-
response:
|
|
140
|
-
schemaPath:
|
|
141
|
-
params:
|
|
142
|
-
options:
|
|
143
|
-
id:
|
|
133
|
+
if (m.length)
|
|
134
|
+
for (let b = m.length - 1; b >= 0; b--) {
|
|
135
|
+
const h = m[b];
|
|
136
|
+
if (h && typeof h == "object" && typeof h.onResponse == "function") {
|
|
137
|
+
const j = await h.onResponse({
|
|
138
|
+
request: R,
|
|
139
|
+
response: f,
|
|
140
|
+
schemaPath: c,
|
|
141
|
+
params: w,
|
|
142
|
+
options: T,
|
|
143
|
+
id: U
|
|
144
144
|
});
|
|
145
|
-
if (
|
|
146
|
-
if (!(
|
|
145
|
+
if (j) {
|
|
146
|
+
if (!(j instanceof Response))
|
|
147
147
|
throw new Error("onResponse: must return new Response() when modifying the response");
|
|
148
|
-
|
|
148
|
+
f = j;
|
|
149
149
|
}
|
|
150
150
|
}
|
|
151
151
|
}
|
|
152
152
|
}
|
|
153
|
-
if (
|
|
154
|
-
return
|
|
155
|
-
if (
|
|
156
|
-
return
|
|
157
|
-
let
|
|
153
|
+
if (f.status === 204 || R.method === "HEAD" || f.headers.get("Content-Length") === "0")
|
|
154
|
+
return f.ok ? { data: void 0, response: f } : { error: void 0, response: f };
|
|
155
|
+
if (f.ok)
|
|
156
|
+
return S === "stream" ? { data: f.body, response: f } : { data: await f[S](), response: f };
|
|
157
|
+
let F = await f.text();
|
|
158
158
|
try {
|
|
159
|
-
|
|
159
|
+
F = JSON.parse(F);
|
|
160
160
|
} catch {
|
|
161
161
|
}
|
|
162
|
-
return { error:
|
|
162
|
+
return { error: F, response: f };
|
|
163
163
|
}
|
|
164
164
|
return {
|
|
165
|
-
request(
|
|
166
|
-
return
|
|
165
|
+
request(c, l, p) {
|
|
166
|
+
return y(l, { ...p, method: c.toUpperCase() });
|
|
167
167
|
},
|
|
168
168
|
/** Call a GET endpoint */
|
|
169
|
-
GET(
|
|
170
|
-
return
|
|
169
|
+
GET(c, l) {
|
|
170
|
+
return y(c, { ...l, method: "GET" });
|
|
171
171
|
},
|
|
172
172
|
/** Call a PUT endpoint */
|
|
173
|
-
PUT(
|
|
174
|
-
return
|
|
173
|
+
PUT(c, l) {
|
|
174
|
+
return y(c, { ...l, method: "PUT" });
|
|
175
175
|
},
|
|
176
176
|
/** Call a POST endpoint */
|
|
177
|
-
POST(
|
|
178
|
-
return
|
|
177
|
+
POST(c, l) {
|
|
178
|
+
return y(c, { ...l, method: "POST" });
|
|
179
179
|
},
|
|
180
180
|
/** Call a DELETE endpoint */
|
|
181
|
-
DELETE(
|
|
182
|
-
return
|
|
181
|
+
DELETE(c, l) {
|
|
182
|
+
return y(c, { ...l, method: "DELETE" });
|
|
183
183
|
},
|
|
184
184
|
/** Call a OPTIONS endpoint */
|
|
185
|
-
OPTIONS(
|
|
186
|
-
return
|
|
185
|
+
OPTIONS(c, l) {
|
|
186
|
+
return y(c, { ...l, method: "OPTIONS" });
|
|
187
187
|
},
|
|
188
188
|
/** Call a HEAD endpoint */
|
|
189
|
-
HEAD(
|
|
190
|
-
return
|
|
189
|
+
HEAD(c, l) {
|
|
190
|
+
return y(c, { ...l, method: "HEAD" });
|
|
191
191
|
},
|
|
192
192
|
/** Call a PATCH endpoint */
|
|
193
|
-
PATCH(
|
|
194
|
-
return
|
|
193
|
+
PATCH(c, l) {
|
|
194
|
+
return y(c, { ...l, method: "PATCH" });
|
|
195
195
|
},
|
|
196
196
|
/** Call a TRACE endpoint */
|
|
197
|
-
TRACE(
|
|
198
|
-
return
|
|
197
|
+
TRACE(c, l) {
|
|
198
|
+
return y(c, { ...l, method: "TRACE" });
|
|
199
199
|
},
|
|
200
200
|
/** Register middleware */
|
|
201
|
-
use(...
|
|
202
|
-
for (const
|
|
203
|
-
if (
|
|
204
|
-
if (typeof
|
|
201
|
+
use(...c) {
|
|
202
|
+
for (const l of c)
|
|
203
|
+
if (l) {
|
|
204
|
+
if (typeof l != "object" || !("onRequest" in l || "onResponse" in l || "onError" in l))
|
|
205
205
|
throw new Error("Middleware must be an object with one of `onRequest()`, `onResponse() or `onError()`");
|
|
206
|
-
|
|
206
|
+
m.push(l);
|
|
207
207
|
}
|
|
208
208
|
},
|
|
209
209
|
/** Unregister middleware */
|
|
210
|
-
eject(...
|
|
211
|
-
for (const
|
|
212
|
-
const p =
|
|
213
|
-
p !== -1 &&
|
|
210
|
+
eject(...c) {
|
|
211
|
+
for (const l of c) {
|
|
212
|
+
const p = m.indexOf(l);
|
|
213
|
+
p !== -1 && m.splice(p, 1);
|
|
214
214
|
}
|
|
215
215
|
}
|
|
216
216
|
};
|
|
217
217
|
}
|
|
218
|
-
function
|
|
219
|
-
if (
|
|
218
|
+
function O(e, r, t) {
|
|
219
|
+
if (r == null)
|
|
220
220
|
return "";
|
|
221
|
-
if (typeof
|
|
221
|
+
if (typeof r == "object")
|
|
222
222
|
throw new Error(
|
|
223
223
|
"Deeply-nested arrays/objects arenβt supported. Provide your own `querySerializer()` to handle these."
|
|
224
224
|
);
|
|
225
|
-
return `${e}=${(t == null ? void 0 : t.allowReserved) === !0 ?
|
|
225
|
+
return `${e}=${(t == null ? void 0 : t.allowReserved) === !0 ? r : encodeURIComponent(r)}`;
|
|
226
226
|
}
|
|
227
|
-
function
|
|
228
|
-
if (!
|
|
227
|
+
function V(e, r, t) {
|
|
228
|
+
if (!r || typeof r != "object")
|
|
229
229
|
return "";
|
|
230
|
-
const s = [],
|
|
230
|
+
const s = [], n = {
|
|
231
231
|
simple: ",",
|
|
232
232
|
label: ".",
|
|
233
233
|
matrix: ";"
|
|
234
234
|
}[t.style] || "&";
|
|
235
235
|
if (t.style !== "deepObject" && t.explode === !1) {
|
|
236
|
-
for (const
|
|
237
|
-
s.push(
|
|
238
|
-
const
|
|
236
|
+
for (const u in r)
|
|
237
|
+
s.push(u, t.allowReserved === !0 ? r[u] : encodeURIComponent(r[u]));
|
|
238
|
+
const i = s.join(",");
|
|
239
239
|
switch (t.style) {
|
|
240
240
|
case "form":
|
|
241
|
-
return `${e}=${
|
|
241
|
+
return `${e}=${i}`;
|
|
242
242
|
case "label":
|
|
243
|
-
return `.${
|
|
243
|
+
return `.${i}`;
|
|
244
244
|
case "matrix":
|
|
245
|
-
return `;${e}=${
|
|
245
|
+
return `;${e}=${i}`;
|
|
246
246
|
default:
|
|
247
|
-
return
|
|
247
|
+
return i;
|
|
248
248
|
}
|
|
249
249
|
}
|
|
250
|
-
for (const
|
|
251
|
-
const
|
|
252
|
-
s.push(
|
|
250
|
+
for (const i in r) {
|
|
251
|
+
const u = t.style === "deepObject" ? `${e}[${i}]` : i;
|
|
252
|
+
s.push(O(u, r[i], t));
|
|
253
253
|
}
|
|
254
|
-
const
|
|
255
|
-
return t.style === "label" || t.style === "matrix" ? `${
|
|
254
|
+
const o = s.join(n);
|
|
255
|
+
return t.style === "label" || t.style === "matrix" ? `${n}${o}` : o;
|
|
256
256
|
}
|
|
257
|
-
function
|
|
258
|
-
if (!Array.isArray(
|
|
257
|
+
function X(e, r, t) {
|
|
258
|
+
if (!Array.isArray(r))
|
|
259
259
|
return "";
|
|
260
260
|
if (t.explode === !1) {
|
|
261
|
-
const
|
|
261
|
+
const o = { form: ",", spaceDelimited: "%20", pipeDelimited: "|" }[t.style] || ",", i = (t.allowReserved === !0 ? r : r.map((u) => encodeURIComponent(u))).join(o);
|
|
262
262
|
switch (t.style) {
|
|
263
263
|
case "simple":
|
|
264
|
-
return
|
|
264
|
+
return i;
|
|
265
265
|
case "label":
|
|
266
|
-
return `.${
|
|
266
|
+
return `.${i}`;
|
|
267
267
|
case "matrix":
|
|
268
|
-
return `;${e}=${
|
|
268
|
+
return `;${e}=${i}`;
|
|
269
269
|
default:
|
|
270
|
-
return `${e}=${
|
|
270
|
+
return `${e}=${i}`;
|
|
271
271
|
}
|
|
272
272
|
}
|
|
273
|
-
const s = { simple: ",", label: ".", matrix: ";" }[t.style] || "&",
|
|
274
|
-
for (const
|
|
275
|
-
t.style === "simple" || t.style === "label" ?
|
|
276
|
-
return t.style === "label" || t.style === "matrix" ? `${s}${
|
|
273
|
+
const s = { simple: ",", label: ".", matrix: ";" }[t.style] || "&", n = [];
|
|
274
|
+
for (const o of r)
|
|
275
|
+
t.style === "simple" || t.style === "label" ? n.push(t.allowReserved === !0 ? o : encodeURIComponent(o)) : n.push(O(e, o, t));
|
|
276
|
+
return t.style === "label" || t.style === "matrix" ? `${s}${n.join(s)}` : n.join(s);
|
|
277
277
|
}
|
|
278
278
|
function _(e) {
|
|
279
279
|
return function(t) {
|
|
280
280
|
const s = [];
|
|
281
281
|
if (t && typeof t == "object")
|
|
282
|
-
for (const
|
|
283
|
-
const
|
|
284
|
-
if (
|
|
285
|
-
if (Array.isArray(
|
|
286
|
-
if (
|
|
282
|
+
for (const n in t) {
|
|
283
|
+
const o = t[n];
|
|
284
|
+
if (o != null) {
|
|
285
|
+
if (Array.isArray(o)) {
|
|
286
|
+
if (o.length === 0)
|
|
287
287
|
continue;
|
|
288
288
|
s.push(
|
|
289
|
-
|
|
289
|
+
X(n, o, {
|
|
290
290
|
style: "form",
|
|
291
291
|
explode: !0,
|
|
292
292
|
...e == null ? void 0 : e.array,
|
|
@@ -295,9 +295,9 @@ function _(e) {
|
|
|
295
295
|
);
|
|
296
296
|
continue;
|
|
297
297
|
}
|
|
298
|
-
if (typeof
|
|
298
|
+
if (typeof o == "object") {
|
|
299
299
|
s.push(
|
|
300
|
-
|
|
300
|
+
V(n, o, {
|
|
301
301
|
style: "deepObject",
|
|
302
302
|
explode: !0,
|
|
303
303
|
...e == null ? void 0 : e.object,
|
|
@@ -306,67 +306,67 @@ function _(e) {
|
|
|
306
306
|
);
|
|
307
307
|
continue;
|
|
308
308
|
}
|
|
309
|
-
s.push(
|
|
309
|
+
s.push(O(n, o, e));
|
|
310
310
|
}
|
|
311
311
|
}
|
|
312
312
|
return s.join("&");
|
|
313
313
|
};
|
|
314
314
|
}
|
|
315
|
-
function
|
|
315
|
+
function ae(e, r) {
|
|
316
316
|
let t = e;
|
|
317
|
-
for (const s of e.match(
|
|
318
|
-
let
|
|
319
|
-
if (
|
|
317
|
+
for (const s of e.match(ne) ?? []) {
|
|
318
|
+
let n = s.substring(1, s.length - 1), o = !1, i = "simple";
|
|
319
|
+
if (n.endsWith("*") && (o = !0, n = n.substring(0, n.length - 1)), n.startsWith(".") ? (i = "label", n = n.substring(1)) : n.startsWith(";") && (i = "matrix", n = n.substring(1)), !r || r[n] === void 0 || r[n] === null)
|
|
320
320
|
continue;
|
|
321
|
-
const
|
|
322
|
-
if (Array.isArray(
|
|
323
|
-
t = t.replace(s,
|
|
321
|
+
const u = r[n];
|
|
322
|
+
if (Array.isArray(u)) {
|
|
323
|
+
t = t.replace(s, X(n, u, { style: i, explode: o }));
|
|
324
324
|
continue;
|
|
325
325
|
}
|
|
326
|
-
if (typeof
|
|
327
|
-
t = t.replace(s,
|
|
326
|
+
if (typeof u == "object") {
|
|
327
|
+
t = t.replace(s, V(n, u, { style: i, explode: o }));
|
|
328
328
|
continue;
|
|
329
329
|
}
|
|
330
|
-
if (
|
|
331
|
-
t = t.replace(s, `;${
|
|
330
|
+
if (i === "matrix") {
|
|
331
|
+
t = t.replace(s, `;${O(n, u)}`);
|
|
332
332
|
continue;
|
|
333
333
|
}
|
|
334
|
-
t = t.replace(s,
|
|
334
|
+
t = t.replace(s, i === "label" ? `.${encodeURIComponent(u)}` : encodeURIComponent(u));
|
|
335
335
|
}
|
|
336
336
|
return t;
|
|
337
337
|
}
|
|
338
|
-
function
|
|
339
|
-
return e instanceof FormData ? e :
|
|
338
|
+
function ce(e, r) {
|
|
339
|
+
return e instanceof FormData ? e : r && (r.get instanceof Function ? r.get("Content-Type") ?? r.get("content-type") : r["Content-Type"] ?? r["content-type"]) === "application/x-www-form-urlencoded" ? new URLSearchParams(e).toString() : JSON.stringify(e);
|
|
340
340
|
}
|
|
341
|
-
function
|
|
342
|
-
var
|
|
343
|
-
let t = `${
|
|
344
|
-
(
|
|
345
|
-
let s =
|
|
341
|
+
function le(e, r) {
|
|
342
|
+
var n;
|
|
343
|
+
let t = `${r.baseUrl}${e}`;
|
|
344
|
+
(n = r.params) != null && n.path && (t = ae(t, r.params.path));
|
|
345
|
+
let s = r.querySerializer(r.params.query ?? {});
|
|
346
346
|
return s.startsWith("?") && (s = s.substring(1)), s && (t += `?${s}`), t;
|
|
347
347
|
}
|
|
348
348
|
function B(...e) {
|
|
349
|
-
const
|
|
349
|
+
const r = new Headers();
|
|
350
350
|
for (const t of e) {
|
|
351
351
|
if (!t || typeof t != "object")
|
|
352
352
|
continue;
|
|
353
353
|
const s = t instanceof Headers ? t.entries() : Object.entries(t);
|
|
354
|
-
for (const [
|
|
355
|
-
if (
|
|
356
|
-
|
|
357
|
-
else if (Array.isArray(
|
|
358
|
-
for (const
|
|
359
|
-
|
|
360
|
-
else
|
|
354
|
+
for (const [n, o] of s)
|
|
355
|
+
if (o === null)
|
|
356
|
+
r.delete(n);
|
|
357
|
+
else if (Array.isArray(o))
|
|
358
|
+
for (const i of o)
|
|
359
|
+
r.append(n, i);
|
|
360
|
+
else o !== void 0 && r.set(n, o);
|
|
361
361
|
}
|
|
362
|
-
return
|
|
362
|
+
return r;
|
|
363
363
|
}
|
|
364
364
|
function W(e) {
|
|
365
365
|
return e.endsWith("/") ? e.substring(0, e.length - 1) : e;
|
|
366
366
|
}
|
|
367
|
-
const
|
|
367
|
+
const ue = {
|
|
368
368
|
baseUrl: "http://localhost:3200"
|
|
369
|
-
},
|
|
369
|
+
}, fe = {
|
|
370
370
|
development: {
|
|
371
371
|
baseUrl: "http://localhost:3200"
|
|
372
372
|
},
|
|
@@ -378,69 +378,77 @@ const ae = {
|
|
|
378
378
|
// baseUrl: import.meta.env.VITE_API_BASE_URL || "https://api.dismissible.io",
|
|
379
379
|
baseUrl: "https://api.dismissible.io"
|
|
380
380
|
}
|
|
381
|
-
},
|
|
381
|
+
}, de = () => fe["production"] || ue, M = (e, r, t) => {
|
|
382
382
|
try {
|
|
383
|
-
const s = `${
|
|
384
|
-
if (!
|
|
385
|
-
const { data:
|
|
386
|
-
return t && Date.now() -
|
|
383
|
+
const s = `${r}_${e}`, n = localStorage.getItem(s);
|
|
384
|
+
if (!n) return null;
|
|
385
|
+
const { data: o, timestamp: i } = JSON.parse(n);
|
|
386
|
+
return t && Date.now() - i > t ? (localStorage.removeItem(s), null) : o;
|
|
387
387
|
} catch {
|
|
388
388
|
return null;
|
|
389
389
|
}
|
|
390
|
-
},
|
|
390
|
+
}, G = (e, r, t) => {
|
|
391
391
|
try {
|
|
392
|
-
const s = `${t}_${e}`,
|
|
393
|
-
data:
|
|
392
|
+
const s = `${t}_${e}`, n = {
|
|
393
|
+
data: r,
|
|
394
394
|
timestamp: Date.now()
|
|
395
395
|
};
|
|
396
|
-
localStorage.setItem(s, JSON.stringify(
|
|
396
|
+
localStorage.setItem(s, JSON.stringify(n));
|
|
397
397
|
} catch (s) {
|
|
398
398
|
console.warn("Failed to cache dismissible item:", s);
|
|
399
399
|
}
|
|
400
|
-
},
|
|
400
|
+
}, K = (e, r) => {
|
|
401
401
|
try {
|
|
402
|
-
const t = `${
|
|
402
|
+
const t = `${r}_${e}`;
|
|
403
403
|
localStorage.removeItem(t);
|
|
404
404
|
} catch (t) {
|
|
405
405
|
console.warn("Failed to remove cached dismissible item:", t);
|
|
406
406
|
}
|
|
407
|
-
},
|
|
408
|
-
|
|
409
|
-
|
|
407
|
+
}, Y = te(
|
|
408
|
+
null
|
|
409
|
+
), me = () => re(Y), he = "dismissible", ye = (e, r = {}) => {
|
|
410
410
|
const {
|
|
411
411
|
initialData: t,
|
|
412
412
|
enableCache: s = !0,
|
|
413
|
-
cachePrefix:
|
|
414
|
-
cacheExpiration:
|
|
415
|
-
} =
|
|
413
|
+
cachePrefix: n = he,
|
|
414
|
+
cacheExpiration: o
|
|
415
|
+
} = r, i = me(), u = N(() => {
|
|
416
|
+
const a = de(), g = (i == null ? void 0 : i.baseUrl) || a.baseUrl, $ = (i == null ? void 0 : i.getAuthHeaders()) || {};
|
|
417
|
+
return oe({
|
|
418
|
+
baseUrl: g,
|
|
419
|
+
headers: {
|
|
420
|
+
...$
|
|
421
|
+
}
|
|
422
|
+
});
|
|
423
|
+
}, [i]), d = N(() => !!(i != null && i.jwt) ? `${e}-auth` : e, [e, i == null ? void 0 : i.jwt]), m = P({
|
|
416
424
|
enableCache: s,
|
|
417
|
-
cachePrefix:
|
|
418
|
-
cacheExpiration:
|
|
419
|
-
}),
|
|
425
|
+
cachePrefix: n,
|
|
426
|
+
cacheExpiration: o
|
|
427
|
+
}), y = P(e), c = P(d), [l, p] = q(!1), [E, v] = q(null), [C, w] = q(() => {
|
|
420
428
|
if (t) return t;
|
|
421
429
|
if (s) {
|
|
422
|
-
const
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
430
|
+
const a = M(
|
|
431
|
+
d,
|
|
432
|
+
n,
|
|
433
|
+
o
|
|
426
434
|
);
|
|
427
|
-
if (
|
|
435
|
+
if (a) return a;
|
|
428
436
|
}
|
|
429
|
-
}),
|
|
437
|
+
}), S = L(async () => {
|
|
430
438
|
if (s) {
|
|
431
|
-
const
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
439
|
+
const a = M(
|
|
440
|
+
d,
|
|
441
|
+
n,
|
|
442
|
+
o
|
|
435
443
|
);
|
|
436
|
-
if (
|
|
437
|
-
|
|
444
|
+
if (a != null && a.dismissedAt) {
|
|
445
|
+
w(a), p(!1);
|
|
438
446
|
return;
|
|
439
447
|
}
|
|
440
448
|
}
|
|
441
|
-
|
|
449
|
+
p(!0), v(null);
|
|
442
450
|
try {
|
|
443
|
-
const { data:
|
|
451
|
+
const { data: a, error: g } = await u.GET(
|
|
444
452
|
"/v1/dismissible/{itemId}",
|
|
445
453
|
{
|
|
446
454
|
params: {
|
|
@@ -450,33 +458,41 @@ const ae = {
|
|
|
450
458
|
}
|
|
451
459
|
}
|
|
452
460
|
);
|
|
453
|
-
if (
|
|
461
|
+
if (g)
|
|
454
462
|
throw new Error(
|
|
455
|
-
|
|
463
|
+
g.error.message || "Failed to fetch dismissible item"
|
|
456
464
|
);
|
|
457
|
-
|
|
458
|
-
} catch (
|
|
459
|
-
|
|
460
|
-
|
|
465
|
+
w(a.data), s && a.data && G(d, a.data, n);
|
|
466
|
+
} catch (a) {
|
|
467
|
+
v(
|
|
468
|
+
a instanceof Error ? a : new Error("Unknown error occurred")
|
|
461
469
|
);
|
|
462
470
|
} finally {
|
|
463
|
-
|
|
471
|
+
p(!1);
|
|
464
472
|
}
|
|
465
|
-
}, [
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
473
|
+
}, [
|
|
474
|
+
e,
|
|
475
|
+
d,
|
|
476
|
+
s,
|
|
477
|
+
n,
|
|
478
|
+
o,
|
|
479
|
+
u
|
|
480
|
+
]);
|
|
481
|
+
J(() => {
|
|
482
|
+
const a = y.current !== e, g = c.current !== d;
|
|
483
|
+
a || g ? (y.current = e, c.current = d, S()) : t || S();
|
|
484
|
+
}, [e, d, t]), J(() => {
|
|
485
|
+
const a = m.current;
|
|
486
|
+
(a.enableCache !== s || a.cachePrefix !== n || a.cacheExpiration !== o) && (a.cachePrefix !== n && K(d, a.cachePrefix), !s && a.enableCache && K(d, n), m.current = {
|
|
471
487
|
enableCache: s,
|
|
472
|
-
cachePrefix:
|
|
473
|
-
cacheExpiration:
|
|
474
|
-
},
|
|
475
|
-
}, [s,
|
|
476
|
-
const
|
|
477
|
-
|
|
488
|
+
cachePrefix: n,
|
|
489
|
+
cacheExpiration: o
|
|
490
|
+
}, S());
|
|
491
|
+
}, [s, n, o, d]);
|
|
492
|
+
const A = L(async () => {
|
|
493
|
+
v(null);
|
|
478
494
|
try {
|
|
479
|
-
const { data:
|
|
495
|
+
const { data: a, error: g } = await u.DELETE(
|
|
480
496
|
"/v1/dismissible/{itemId}",
|
|
481
497
|
{
|
|
482
498
|
params: {
|
|
@@ -486,74 +502,109 @@ const ae = {
|
|
|
486
502
|
}
|
|
487
503
|
}
|
|
488
504
|
);
|
|
489
|
-
if (
|
|
490
|
-
throw new Error(
|
|
491
|
-
|
|
492
|
-
} catch (
|
|
493
|
-
throw
|
|
494
|
-
|
|
495
|
-
),
|
|
505
|
+
if (g)
|
|
506
|
+
throw new Error(g.error.message || "Failed to dismiss item");
|
|
507
|
+
w(a.data), s && a.data && G(d, a.data, n);
|
|
508
|
+
} catch (a) {
|
|
509
|
+
throw v(
|
|
510
|
+
a instanceof Error ? a : new Error("Failed to dismiss item")
|
|
511
|
+
), a;
|
|
496
512
|
}
|
|
497
|
-
}, [
|
|
513
|
+
}, [d, s, n, u]);
|
|
498
514
|
return {
|
|
499
|
-
dismissedOn: (
|
|
500
|
-
dismiss:
|
|
501
|
-
isLoading:
|
|
502
|
-
error:
|
|
503
|
-
item:
|
|
515
|
+
dismissedOn: (C == null ? void 0 : C.dismissedAt) ?? null,
|
|
516
|
+
dismiss: A,
|
|
517
|
+
isLoading: l,
|
|
518
|
+
error: E,
|
|
519
|
+
item: C
|
|
504
520
|
};
|
|
505
|
-
},
|
|
521
|
+
}, be = () => /* @__PURE__ */ I("div", { className: "dismissible-loading", "aria-live": "polite", children: "Loading..." }), pe = ({
|
|
506
522
|
error: e
|
|
507
|
-
}) => /* @__PURE__ */
|
|
523
|
+
}) => /* @__PURE__ */ Q("div", { className: "dismissible-error", role: "alert", children: [
|
|
508
524
|
"Error loading dismissible item: ",
|
|
509
525
|
e.message
|
|
510
|
-
] }),
|
|
526
|
+
] }), ge = ({ id: e, onDismiss: r, ariaLabel: t }) => /* @__PURE__ */ I(
|
|
511
527
|
"button",
|
|
512
528
|
{
|
|
513
529
|
id: e,
|
|
514
530
|
className: "dismissible-button",
|
|
515
|
-
onClick:
|
|
531
|
+
onClick: r,
|
|
516
532
|
"aria-label": t,
|
|
517
533
|
type: "button",
|
|
518
534
|
children: "Γ"
|
|
519
535
|
}
|
|
520
|
-
),
|
|
536
|
+
), Ce = ({
|
|
521
537
|
id: e,
|
|
522
|
-
children:
|
|
538
|
+
children: r,
|
|
523
539
|
onDismiss: t,
|
|
524
|
-
LoadingComponent: s =
|
|
525
|
-
ErrorComponent:
|
|
526
|
-
DismissButtonComponent:
|
|
527
|
-
enableCache:
|
|
528
|
-
cachePrefix:
|
|
529
|
-
cacheExpiration:
|
|
540
|
+
LoadingComponent: s = be,
|
|
541
|
+
ErrorComponent: n = pe,
|
|
542
|
+
DismissButtonComponent: o = ge,
|
|
543
|
+
enableCache: i,
|
|
544
|
+
cachePrefix: u,
|
|
545
|
+
cacheExpiration: d
|
|
530
546
|
}) => {
|
|
531
|
-
const { dismissedOn:
|
|
532
|
-
enableCache:
|
|
533
|
-
cachePrefix:
|
|
534
|
-
cacheExpiration:
|
|
535
|
-
}), [p,
|
|
536
|
-
|
|
547
|
+
const { dismissedOn: m, isLoading: y, error: c, dismiss: l } = ye(e, {
|
|
548
|
+
enableCache: i,
|
|
549
|
+
cachePrefix: u,
|
|
550
|
+
cacheExpiration: d
|
|
551
|
+
}), [p, E] = q(!1), v = async () => {
|
|
552
|
+
E(!0);
|
|
537
553
|
try {
|
|
538
|
-
await
|
|
554
|
+
await l(), t == null || t();
|
|
539
555
|
} catch {
|
|
540
|
-
|
|
556
|
+
E(!1);
|
|
541
557
|
}
|
|
542
558
|
};
|
|
543
|
-
return
|
|
544
|
-
/* @__PURE__ */
|
|
545
|
-
|
|
546
|
-
|
|
559
|
+
return y && s ? /* @__PURE__ */ I(s, { id: e }) : y && !s ? null : c && n ? /* @__PURE__ */ I(n, { id: e, error: c }) : m || p ? null : /* @__PURE__ */ Q("div", { className: "dismissible-container", children: [
|
|
560
|
+
/* @__PURE__ */ I("div", { className: "dismissible-content", children: r }),
|
|
561
|
+
o ? /* @__PURE__ */ I(
|
|
562
|
+
o,
|
|
547
563
|
{
|
|
548
564
|
id: e,
|
|
549
|
-
onDismiss:
|
|
565
|
+
onDismiss: v,
|
|
550
566
|
ariaLabel: `Dismiss ${e}`
|
|
551
567
|
}
|
|
552
568
|
) : null
|
|
553
569
|
] });
|
|
554
|
-
}, we =
|
|
570
|
+
}, we = (e) => {
|
|
571
|
+
if (typeof e == "function")
|
|
572
|
+
try {
|
|
573
|
+
return e();
|
|
574
|
+
} catch (r) {
|
|
575
|
+
console.warn("Failed to resolve JWT from function:", r);
|
|
576
|
+
return;
|
|
577
|
+
}
|
|
578
|
+
return e;
|
|
579
|
+
}, Re = (e) => {
|
|
580
|
+
const r = we(e);
|
|
581
|
+
return r ? { Authorization: `Bearer ${r}` } : {};
|
|
582
|
+
}, Se = (e) => {
|
|
583
|
+
const r = e.split(".");
|
|
584
|
+
return r.length === 3 && r.every((t) => t.length > 0);
|
|
585
|
+
}, je = ({
|
|
586
|
+
jwt: e,
|
|
587
|
+
baseUrl: r,
|
|
588
|
+
children: t
|
|
589
|
+
}) => {
|
|
590
|
+
const s = N(
|
|
591
|
+
() => ({
|
|
592
|
+
jwt: e,
|
|
593
|
+
baseUrl: r,
|
|
594
|
+
getAuthHeaders: () => Re(e)
|
|
595
|
+
}),
|
|
596
|
+
[e, r]
|
|
597
|
+
);
|
|
598
|
+
return /* @__PURE__ */ I(Y.Provider, { value: s, children: t });
|
|
599
|
+
}, Ie = "0.1.0";
|
|
555
600
|
export {
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
601
|
+
Ce as Dismissible,
|
|
602
|
+
Y as DismissibleContext,
|
|
603
|
+
je as DismissibleProvider,
|
|
604
|
+
Ie as VERSION,
|
|
605
|
+
Re as getAuthHeaders,
|
|
606
|
+
Se as isValidJwtFormat,
|
|
607
|
+
we as resolveJwt,
|
|
608
|
+
me as useDismissibleContext,
|
|
609
|
+
ye as useDismissibleItem
|
|
559
610
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
(function(w,g){typeof exports=="object"&&typeof module<"u"?g(exports,require("react/jsx-runtime"),require("react")):typeof define=="function"&&define.amd?define(["exports","react/jsx-runtime","react"],g):(w=typeof globalThis<"u"?globalThis:w||self,g(w.DismissibleClient={},w.React.jsxRuntime,w.React))})(this,function(w,g,E){"use strict";const X=/\{[^{}]+\}/g,K=()=>{var e,n;return typeof process=="object"&&Number.parseInt((n=(e=process==null?void 0:process.versions)==null?void 0:e.node)==null?void 0:n.substring(0,2))>=18&&process.versions.undici};function Y(){return Math.random().toString(36).slice(2,11)}function Z(e){let{baseUrl:n="",Request:t=globalThis.Request,fetch:s=globalThis.fetch,querySerializer:r,bodySerializer:i,headers:c,requestInitExt:f=void 0,...v}={...e};f=K()?f:void 0,n=_(n);const d=[];async function h(a,o){const{baseUrl:p,fetch:R=s,Request:$=t,headers:l,params:b={},parseAs:A="json",querySerializer:T,bodySerializer:Q=i??te,body:V,...q}=o||{};let O=n;p&&(O=_(p)??n);let z=typeof r=="function"?r:H(r);T&&(z=typeof T=="function"?T:H({...typeof r=="object"?r:{},...T}));const k=V===void 0?void 0:Q(V,L(c,l,b.header)),me=L(k===void 0||k instanceof FormData?{}:{"Content-Type":"application/json"},c,l,b.header),he={redirect:"follow",...v,...q,body:k,headers:me};let x,D,S=new t(re(a,{baseUrl:O,params:b,querySerializer:z}),he),u;for(const y in q)y in S||(S[y]=q[y]);if(d.length){x=Y(),D=Object.freeze({baseUrl:O,fetch:R,parseAs:A,querySerializer:z,bodySerializer:Q});for(const y of d)if(y&&typeof y=="object"&&typeof y.onRequest=="function"){const m=await y.onRequest({request:S,schemaPath:a,params:b,options:D,id:x});if(m)if(m instanceof t)S=m;else if(m instanceof Response){u=m;break}else throw new Error("onRequest: must return new Request() or Response() when modifying the request")}}if(!u){try{u=await R(S,f)}catch(y){let m=y;if(d.length)for(let j=d.length-1;j>=0;j--){const U=d[j];if(U&&typeof U=="object"&&typeof U.onError=="function"){const C=await U.onError({request:S,error:m,schemaPath:a,params:b,options:D,id:x});if(C){if(C instanceof Response){m=void 0,u=C;break}if(C instanceof Error){m=C;continue}throw new Error("onError: must return new Response() or instance of Error")}}}if(m)throw m}if(d.length)for(let y=d.length-1;y>=0;y--){const m=d[y];if(m&&typeof m=="object"&&typeof m.onResponse=="function"){const j=await m.onResponse({request:S,response:u,schemaPath:a,params:b,options:D,id:x});if(j){if(!(j instanceof Response))throw new Error("onResponse: must return new Response() when modifying the response");u=j}}}}if(u.status===204||S.method==="HEAD"||u.headers.get("Content-Length")==="0")return u.ok?{data:void 0,response:u}:{error:void 0,response:u};if(u.ok)return A==="stream"?{data:u.body,response:u}:{data:await u[A](),response:u};let N=await u.text();try{N=JSON.parse(N)}catch{}return{error:N,response:u}}return{request(a,o,p){return h(o,{...p,method:a.toUpperCase()})},GET(a,o){return h(a,{...o,method:"GET"})},PUT(a,o){return h(a,{...o,method:"PUT"})},POST(a,o){return h(a,{...o,method:"POST"})},DELETE(a,o){return h(a,{...o,method:"DELETE"})},OPTIONS(a,o){return h(a,{...o,method:"OPTIONS"})},HEAD(a,o){return h(a,{...o,method:"HEAD"})},PATCH(a,o){return h(a,{...o,method:"PATCH"})},TRACE(a,o){return h(a,{...o,method:"TRACE"})},use(...a){for(const o of a)if(o){if(typeof o!="object"||!("onRequest"in o||"onResponse"in o||"onError"in o))throw new Error("Middleware must be an object with one of `onRequest()`, `onResponse() or `onError()`");d.push(o)}},eject(...a){for(const o of a){const p=d.indexOf(o);p!==-1&&d.splice(p,1)}}}}function I(e,n,t){if(n==null)return"";if(typeof n=="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?n:encodeURIComponent(n)}`}function P(e,n,t){if(!n||typeof n!="object")return"";const s=[],r={simple:",",label:".",matrix:";"}[t.style]||"&";if(t.style!=="deepObject"&&t.explode===!1){for(const f in n)s.push(f,t.allowReserved===!0?n[f]:encodeURIComponent(n[f]));const c=s.join(",");switch(t.style){case"form":return`${e}=${c}`;case"label":return`.${c}`;case"matrix":return`;${e}=${c}`;default:return c}}for(const c in n){const f=t.style==="deepObject"?`${e}[${c}]`:c;s.push(I(f,n[c],t))}const i=s.join(r);return t.style==="label"||t.style==="matrix"?`${r}${i}`:i}function F(e,n,t){if(!Array.isArray(n))return"";if(t.explode===!1){const i={form:",",spaceDelimited:"%20",pipeDelimited:"|"}[t.style]||",",c=(t.allowReserved===!0?n:n.map(f=>encodeURIComponent(f))).join(i);switch(t.style){case"simple":return c;case"label":return`.${c}`;case"matrix":return`;${e}=${c}`;default:return`${e}=${c}`}}const s={simple:",",label:".",matrix:";"}[t.style]||"&",r=[];for(const i of n)t.style==="simple"||t.style==="label"?r.push(t.allowReserved===!0?i:encodeURIComponent(i)):r.push(I(e,i,t));return t.style==="label"||t.style==="matrix"?`${s}${r.join(s)}`:r.join(s)}function H(e){return function(t){const s=[];if(t&&typeof t=="object")for(const r in t){const i=t[r];if(i!=null){if(Array.isArray(i)){if(i.length===0)continue;s.push(F(r,i,{style:"form",explode:!0,...e==null?void 0:e.array,allowReserved:(e==null?void 0:e.allowReserved)||!1}));continue}if(typeof i=="object"){s.push(P(r,i,{style:"deepObject",explode:!0,...e==null?void 0:e.object,allowReserved:(e==null?void 0:e.allowReserved)||!1}));continue}s.push(I(r,i,e))}}return s.join("&")}}function ee(e,n){let t=e;for(const s of e.match(X)??[]){let r=s.substring(1,s.length-1),i=!1,c="simple";if(r.endsWith("*")&&(i=!0,r=r.substring(0,r.length-1)),r.startsWith(".")?(c="label",r=r.substring(1)):r.startsWith(";")&&(c="matrix",r=r.substring(1)),!n||n[r]===void 0||n[r]===null)continue;const f=n[r];if(Array.isArray(f)){t=t.replace(s,F(r,f,{style:c,explode:i}));continue}if(typeof f=="object"){t=t.replace(s,P(r,f,{style:c,explode:i}));continue}if(c==="matrix"){t=t.replace(s,`;${I(r,f)}`);continue}t=t.replace(s,c==="label"?`.${encodeURIComponent(f)}`:encodeURIComponent(f))}return t}function te(e,n){return e instanceof FormData?e:n&&(n.get instanceof Function?n.get("Content-Type")??n.get("content-type"):n["Content-Type"]??n["content-type"])==="application/x-www-form-urlencoded"?new URLSearchParams(e).toString():JSON.stringify(e)}function re(e,n){var r;let t=`${n.baseUrl}${e}`;(r=n.params)!=null&&r.path&&(t=ee(t,n.params.path));let s=n.querySerializer(n.params.query??{});return s.startsWith("?")&&(s=s.substring(1)),s&&(t+=`?${s}`),t}function L(...e){const n=new Headers;for(const t of e){if(!t||typeof t!="object")continue;const s=t instanceof Headers?t.entries():Object.entries(t);for(const[r,i]of s)if(i===null)n.delete(r);else if(Array.isArray(i))for(const c of i)n.append(r,c);else i!==void 0&&n.set(r,i)}return n}function _(e){return e.endsWith("/")?e.substring(0,e.length-1):e}const ne={baseUrl:"http://localhost:3200"},se={development:{baseUrl:"http://localhost:3200"},staging:{baseUrl:"https://api.staging.dismissible.io"},production:{baseUrl:"https://api.dismissible.io"}},ie=()=>se["production"]||ne,B=(e,n,t)=>{try{const s=`${n}_${e}`,r=localStorage.getItem(s);if(!r)return null;const{data:i,timestamp:c}=JSON.parse(r);return t&&Date.now()-c>t?(localStorage.removeItem(s),null):i}catch{return null}},M=(e,n,t)=>{try{const s=`${t}_${e}`,r={data:n,timestamp:Date.now()};localStorage.setItem(s,JSON.stringify(r))}catch(s){console.warn("Failed to cache dismissible item:",s)}},W=(e,n)=>{try{const t=`${n}_${e}`;localStorage.removeItem(t)}catch(t){console.warn("Failed to remove cached dismissible item:",t)}},oe=ie(),J=Z({baseUrl:oe.baseUrl}),ae="dismissible",G=(e,n={})=>{const{initialData:t,enableCache:s=!0,cachePrefix:r=ae,cacheExpiration:i}=n,c=E.useRef({enableCache:s,cachePrefix:r,cacheExpiration:i}),f=E.useRef(e),[v,d]=E.useState(!1),[h,a]=E.useState(null),[o,p]=E.useState(()=>{if(t)return t;if(s){const l=B(e,r,i);if(l)return l}}),R=E.useCallback(async()=>{if(s){const l=B(e,r,i);if(l!=null&&l.dismissedAt){p(l),d(!1);return}}d(!0),a(null);try{const{data:l,error:b}=await J.GET("/v1/dismissible/{itemId}",{params:{path:{itemId:e}}});if(b)throw new Error(b.error.message||"Failed to fetch dismissible item");p(l.data),s&&l.data&&M(e,l.data,r)}catch(l){a(l instanceof Error?l:new Error("Unknown error occurred"))}finally{d(!1)}},[e,s,r,i]);E.useEffect(()=>{f.current!==e?(f.current=e,R()):t||R()},[e,t]),E.useEffect(()=>{const l=c.current;(l.enableCache!==s||l.cachePrefix!==r||l.cacheExpiration!==i)&&(l.cachePrefix!==r&&W(e,l.cachePrefix),!s&&l.enableCache&&W(e,r),c.current={enableCache:s,cachePrefix:r,cacheExpiration:i},R())},[s,r,i,e]);const $=E.useCallback(async()=>{a(null);try{const{data:l,error:b}=await J.DELETE("/v1/dismissible/{itemId}",{params:{path:{itemId:e}}});if(b)throw new Error(b.error.message||"Failed to dismiss item");p(l.data),s&&l.data&&M(e,l.data,r)}catch(l){throw a(l instanceof Error?l:new Error("Failed to dismiss item")),l}},[e,s,r]);return{dismissedOn:(o==null?void 0:o.dismissedAt)??null,dismiss:$,isLoading:v,error:h,item:o}},le=()=>g.jsx("div",{className:"dismissible-loading","aria-live":"polite",children:"Loading..."}),ce=({error:e})=>g.jsxs("div",{className:"dismissible-error",role:"alert",children:["Error loading dismissible item: ",e.message]}),fe=({id:e,onDismiss:n,ariaLabel:t})=>g.jsx("button",{id:e,className:"dismissible-button",onClick:n,"aria-label":t,type:"button",children:"Γ"}),ue=({id:e,children:n,onDismiss:t,LoadingComponent:s=le,ErrorComponent:r=ce,DismissButtonComponent:i=fe,enableCache:c,cachePrefix:f,cacheExpiration:v})=>{const{dismissedOn:d,isLoading:h,error:a,dismiss:o}=G(e,{enableCache:c,cachePrefix:f,cacheExpiration:v}),[p,R]=E.useState(!1),$=async()=>{R(!0);try{await o(),t==null||t()}catch{R(!1)}};return h&&s?g.jsx(s,{id:e}):h&&!s?null:a&&r?g.jsx(r,{id:e,error:a}):d||p?null:g.jsxs("div",{className:"dismissible-container",children:[g.jsx("div",{className:"dismissible-content",children:n}),i?g.jsx(i,{id:e,onDismiss:$,ariaLabel:`Dismiss ${e}`}):null]})},de="0.1.0";w.Dismissible=ue,w.VERSION=de,w.useDismissibleItem=G,Object.defineProperty(w,Symbol.toStringTag,{value:"Module"})});
|
|
1
|
+
(function(m,w){typeof exports=="object"&&typeof module<"u"?w(exports,require("react/jsx-runtime"),require("react")):typeof define=="function"&&define.amd?define(["exports","react/jsx-runtime","react"],w):(m=typeof globalThis<"u"?globalThis:m||self,w(m.DismissibleClient={},m.React.jsxRuntime,m.React))})(this,function(m,w,h){"use strict";const Z=/\{[^{}]+\}/g,ee=()=>{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 te(){return Math.random().toString(36).slice(2,11)}function re(e){let{baseUrl:r="",Request:t=globalThis.Request,fetch:n=globalThis.fetch,querySerializer:s,bodySerializer:o,headers:i,requestInitExt:u=void 0,...d}={...e};u=ee()?u:void 0,r=B(r);const b=[];async function p(l,c){const{baseUrl:v,fetch:S=n,Request:j=t,headers:I,params:C={},parseAs:D="json",querySerializer:$,bodySerializer:a=o??ne,body:E,...T}=c||{};let P=r;v&&(P=B(v)??r);let k=typeof s=="function"?s:M(s);$&&(k=typeof $=="function"?$:M({...typeof s=="object"?s:{},...$}));const F=E===void 0?void 0:a(E,_(i,I,C.header)),pe=_(F===void 0||F instanceof FormData?{}:{"Content-Type":"application/json"},i,I,C.header),ge={redirect:"follow",...d,...T,body:F,headers:pe};let O,x,R=new t(ie(l,{baseUrl:P,params:C,querySerializer:k}),ge),f;for(const g in T)g in R||(R[g]=T[g]);if(b.length){O=te(),x=Object.freeze({baseUrl:P,fetch:S,parseAs:D,querySerializer:k,bodySerializer:a});for(const g of b)if(g&&typeof g=="object"&&typeof g.onRequest=="function"){const y=await g.onRequest({request:R,schemaPath:l,params:C,options:x,id:O});if(y)if(y instanceof t)R=y;else if(y instanceof Response){f=y;break}else throw new Error("onRequest: must return new Request() or Response() when modifying the request")}}if(!f){try{f=await S(R,u)}catch(g){let y=g;if(b.length)for(let A=b.length-1;A>=0;A--){const z=b[A];if(z&&typeof z=="object"&&typeof z.onError=="function"){const U=await z.onError({request:R,error:y,schemaPath:l,params:C,options:x,id:O});if(U){if(U instanceof Response){y=void 0,f=U;break}if(U instanceof Error){y=U;continue}throw new Error("onError: must return new Response() or instance of Error")}}}if(y)throw y}if(b.length)for(let g=b.length-1;g>=0;g--){const y=b[g];if(y&&typeof y=="object"&&typeof y.onResponse=="function"){const A=await y.onResponse({request:R,response:f,schemaPath:l,params:C,options:x,id:O});if(A){if(!(A instanceof Response))throw new Error("onResponse: must return new Response() when modifying the response");f=A}}}}if(f.status===204||R.method==="HEAD"||f.headers.get("Content-Length")==="0")return f.ok?{data:void 0,response:f}:{error:void 0,response:f};if(f.ok)return D==="stream"?{data:f.body,response:f}:{data:await f[D](),response:f};let N=await f.text();try{N=JSON.parse(N)}catch{}return{error:N,response:f}}return{request(l,c,v){return p(c,{...v,method:l.toUpperCase()})},GET(l,c){return p(l,{...c,method:"GET"})},PUT(l,c){return p(l,{...c,method:"PUT"})},POST(l,c){return p(l,{...c,method:"POST"})},DELETE(l,c){return p(l,{...c,method:"DELETE"})},OPTIONS(l,c){return p(l,{...c,method:"OPTIONS"})},HEAD(l,c){return p(l,{...c,method:"HEAD"})},PATCH(l,c){return p(l,{...c,method:"PATCH"})},TRACE(l,c){return p(l,{...c,method:"TRACE"})},use(...l){for(const c of l)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()`");b.push(c)}},eject(...l){for(const c of l){const v=b.indexOf(c);v!==-1&&b.splice(v,1)}}}}function q(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 L(e,r,t){if(!r||typeof r!="object")return"";const n=[],s={simple:",",label:".",matrix:";"}[t.style]||"&";if(t.style!=="deepObject"&&t.explode===!1){for(const u in r)n.push(u,t.allowReserved===!0?r[u]:encodeURIComponent(r[u]));const i=n.join(",");switch(t.style){case"form":return`${e}=${i}`;case"label":return`.${i}`;case"matrix":return`;${e}=${i}`;default:return i}}for(const i in r){const u=t.style==="deepObject"?`${e}[${i}]`:i;n.push(q(u,r[i],t))}const o=n.join(s);return t.style==="label"||t.style==="matrix"?`${s}${o}`:o}function J(e,r,t){if(!Array.isArray(r))return"";if(t.explode===!1){const o={form:",",spaceDelimited:"%20",pipeDelimited:"|"}[t.style]||",",i=(t.allowReserved===!0?r:r.map(u=>encodeURIComponent(u))).join(o);switch(t.style){case"simple":return i;case"label":return`.${i}`;case"matrix":return`;${e}=${i}`;default:return`${e}=${i}`}}const n={simple:",",label:".",matrix:";"}[t.style]||"&",s=[];for(const o of r)t.style==="simple"||t.style==="label"?s.push(t.allowReserved===!0?o:encodeURIComponent(o)):s.push(q(e,o,t));return t.style==="label"||t.style==="matrix"?`${n}${s.join(n)}`:s.join(n)}function M(e){return function(t){const n=[];if(t&&typeof t=="object")for(const s in t){const o=t[s];if(o!=null){if(Array.isArray(o)){if(o.length===0)continue;n.push(J(s,o,{style:"form",explode:!0,...e==null?void 0:e.array,allowReserved:(e==null?void 0:e.allowReserved)||!1}));continue}if(typeof o=="object"){n.push(L(s,o,{style:"deepObject",explode:!0,...e==null?void 0:e.object,allowReserved:(e==null?void 0:e.allowReserved)||!1}));continue}n.push(q(s,o,e))}}return n.join("&")}}function se(e,r){let t=e;for(const n of e.match(Z)??[]){let s=n.substring(1,n.length-1),o=!1,i="simple";if(s.endsWith("*")&&(o=!0,s=s.substring(0,s.length-1)),s.startsWith(".")?(i="label",s=s.substring(1)):s.startsWith(";")&&(i="matrix",s=s.substring(1)),!r||r[s]===void 0||r[s]===null)continue;const u=r[s];if(Array.isArray(u)){t=t.replace(n,J(s,u,{style:i,explode:o}));continue}if(typeof u=="object"){t=t.replace(n,L(s,u,{style:i,explode:o}));continue}if(i==="matrix"){t=t.replace(n,`;${q(s,u)}`);continue}t=t.replace(n,i==="label"?`.${encodeURIComponent(u)}`:encodeURIComponent(u))}return t}function ne(e,r){return e instanceof FormData?e:r&&(r.get instanceof Function?r.get("Content-Type")??r.get("content-type"):r["Content-Type"]??r["content-type"])==="application/x-www-form-urlencoded"?new URLSearchParams(e).toString():JSON.stringify(e)}function ie(e,r){var s;let t=`${r.baseUrl}${e}`;(s=r.params)!=null&&s.path&&(t=se(t,r.params.path));let n=r.querySerializer(r.params.query??{});return n.startsWith("?")&&(n=n.substring(1)),n&&(t+=`?${n}`),t}function _(...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[s,o]of n)if(o===null)r.delete(s);else if(Array.isArray(o))for(const i of o)r.append(s,i);else o!==void 0&&r.set(s,o)}return r}function B(e){return e.endsWith("/")?e.substring(0,e.length-1):e}const oe={baseUrl:"http://localhost:3200"},ae={development:{baseUrl:"http://localhost:3200"},staging:{baseUrl:"https://api.staging.dismissible.io"},production:{baseUrl:"https://api.dismissible.io"}},le=()=>ae["production"]||oe,W=(e,r,t)=>{try{const n=`${r}_${e}`,s=localStorage.getItem(n);if(!s)return null;const{data:o,timestamp:i}=JSON.parse(s);return t&&Date.now()-i>t?(localStorage.removeItem(n),null):o}catch{return null}},V=(e,r,t)=>{try{const n=`${t}_${e}`,s={data:r,timestamp:Date.now()};localStorage.setItem(n,JSON.stringify(s))}catch(n){console.warn("Failed to cache dismissible item:",n)}},G=(e,r)=>{try{const t=`${r}_${e}`;localStorage.removeItem(t)}catch(t){console.warn("Failed to remove cached dismissible item:",t)}},H=h.createContext(null),K=()=>h.useContext(H),ce="dismissible",Q=(e,r={})=>{const{initialData:t,enableCache:n=!0,cachePrefix:s=ce,cacheExpiration:o}=r,i=K(),u=h.useMemo(()=>{const a=le(),E=(i==null?void 0:i.baseUrl)||a.baseUrl,T=(i==null?void 0:i.getAuthHeaders())||{};return re({baseUrl:E,headers:{...T}})},[i]),d=h.useMemo(()=>!!(i!=null&&i.jwt)?`${e}-auth`:e,[e,i==null?void 0:i.jwt]),b=h.useRef({enableCache:n,cachePrefix:s,cacheExpiration:o}),p=h.useRef(e),l=h.useRef(d),[c,v]=h.useState(!1),[S,j]=h.useState(null),[I,C]=h.useState(()=>{if(t)return t;if(n){const a=W(d,s,o);if(a)return a}}),D=h.useCallback(async()=>{if(n){const a=W(d,s,o);if(a!=null&&a.dismissedAt){C(a),v(!1);return}}v(!0),j(null);try{const{data:a,error:E}=await u.GET("/v1/dismissible/{itemId}",{params:{path:{itemId:e}}});if(E)throw new Error(E.error.message||"Failed to fetch dismissible item");C(a.data),n&&a.data&&V(d,a.data,s)}catch(a){j(a instanceof Error?a:new Error("Unknown error occurred"))}finally{v(!1)}},[e,d,n,s,o,u]);h.useEffect(()=>{const a=p.current!==e,E=l.current!==d;a||E?(p.current=e,l.current=d,D()):t||D()},[e,d,t]),h.useEffect(()=>{const a=b.current;(a.enableCache!==n||a.cachePrefix!==s||a.cacheExpiration!==o)&&(a.cachePrefix!==s&&G(d,a.cachePrefix),!n&&a.enableCache&&G(d,s),b.current={enableCache:n,cachePrefix:s,cacheExpiration:o},D())},[n,s,o,d]);const $=h.useCallback(async()=>{j(null);try{const{data:a,error:E}=await u.DELETE("/v1/dismissible/{itemId}",{params:{path:{itemId:e}}});if(E)throw new Error(E.error.message||"Failed to dismiss item");C(a.data),n&&a.data&&V(d,a.data,s)}catch(a){throw j(a instanceof Error?a:new Error("Failed to dismiss item")),a}},[d,n,s,u]);return{dismissedOn:(I==null?void 0:I.dismissedAt)??null,dismiss:$,isLoading:c,error:S,item:I}},ue=()=>w.jsx("div",{className:"dismissible-loading","aria-live":"polite",children:"Loading..."}),fe=({error:e})=>w.jsxs("div",{className:"dismissible-error",role:"alert",children:["Error loading dismissible item: ",e.message]}),de=({id:e,onDismiss:r,ariaLabel:t})=>w.jsx("button",{id:e,className:"dismissible-button",onClick:r,"aria-label":t,type:"button",children:"Γ"}),me=({id:e,children:r,onDismiss:t,LoadingComponent:n=ue,ErrorComponent:s=fe,DismissButtonComponent:o=de,enableCache:i,cachePrefix:u,cacheExpiration:d})=>{const{dismissedOn:b,isLoading:p,error:l,dismiss:c}=Q(e,{enableCache:i,cachePrefix:u,cacheExpiration:d}),[v,S]=h.useState(!1),j=async()=>{S(!0);try{await c(),t==null||t()}catch{S(!1)}};return p&&n?w.jsx(n,{id:e}):p&&!n?null:l&&s?w.jsx(s,{id:e,error:l}):b||v?null:w.jsxs("div",{className:"dismissible-container",children:[w.jsx("div",{className:"dismissible-content",children:r}),o?w.jsx(o,{id:e,onDismiss:j,ariaLabel:`Dismiss ${e}`}):null]})},X=e=>{if(typeof e=="function")try{return e()}catch(r){console.warn("Failed to resolve JWT from function:",r);return}return e},Y=e=>{const r=X(e);return r?{Authorization:`Bearer ${r}`}:{}},he=e=>{const r=e.split(".");return r.length===3&&r.every(t=>t.length>0)},be=({jwt:e,baseUrl:r,children:t})=>{const n=h.useMemo(()=>({jwt:e,baseUrl:r,getAuthHeaders:()=>Y(e)}),[e,r]);return w.jsx(H.Provider,{value:n,children:t})},ye="0.1.0";m.Dismissible=me,m.DismissibleContext=H,m.DismissibleProvider=be,m.VERSION=ye,m.getAuthHeaders=Y,m.isValidJwtFormat=he,m.resolveJwt=X,m.useDismissibleContext=K,m.useDismissibleItem=Q,Object.defineProperty(m,Symbol.toStringTag,{value:"Module"})});
|
package/dist/root.d.ts
CHANGED
|
@@ -5,4 +5,8 @@
|
|
|
5
5
|
*/
|
|
6
6
|
export * from './components/Dismissible';
|
|
7
7
|
export * from './hooks/useDismissibleItem';
|
|
8
|
+
export * from './contexts/DismissibleContext';
|
|
9
|
+
export * from './contexts/DismissibleProvider';
|
|
10
|
+
export * from './types/dismissible.types';
|
|
11
|
+
export * from './utils/auth.utils';
|
|
8
12
|
export declare const VERSION = "0.1.0";
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TypeScript types for the Dismissible Provider system
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* JWT token can be either a static string or a function that returns a string
|
|
6
|
+
*/
|
|
7
|
+
export type JwtToken = string | (() => string);
|
|
8
|
+
/**
|
|
9
|
+
* Configuration options for the DismissibleProvider
|
|
10
|
+
*/
|
|
11
|
+
export interface DismissibleProviderProps {
|
|
12
|
+
/** JWT token for authentication - can be static string or function */
|
|
13
|
+
jwt?: JwtToken;
|
|
14
|
+
/** Base URL for API requests - overrides default configuration */
|
|
15
|
+
baseUrl?: string;
|
|
16
|
+
/** Child components */
|
|
17
|
+
children: React.ReactNode;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Context value provided by DismissibleProvider
|
|
21
|
+
*/
|
|
22
|
+
export interface DismissibleContextValue {
|
|
23
|
+
/** JWT token for authentication */
|
|
24
|
+
jwt?: JwtToken;
|
|
25
|
+
/** Base URL for API requests */
|
|
26
|
+
baseUrl?: string;
|
|
27
|
+
/** Helper function to get authentication headers */
|
|
28
|
+
getAuthHeaders: () => AuthHeaders;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Authentication headers type
|
|
32
|
+
*/
|
|
33
|
+
export interface AuthHeaders {
|
|
34
|
+
Authorization?: string;
|
|
35
|
+
[key: string]: string | undefined;
|
|
36
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { JwtToken, AuthHeaders } from '../types/dismissible.types';
|
|
2
|
+
/**
|
|
3
|
+
* Resolves a JWT token from either a static string or a function
|
|
4
|
+
* @param jwt - The JWT token (string or function)
|
|
5
|
+
* @returns The resolved JWT token or undefined
|
|
6
|
+
*/
|
|
7
|
+
export declare const resolveJwt: (jwt: JwtToken | undefined) => string | undefined;
|
|
8
|
+
/**
|
|
9
|
+
* Creates authentication headers from a JWT token
|
|
10
|
+
* @param jwt - The JWT token (string or function)
|
|
11
|
+
* @returns Headers object with Authorization header if JWT is available
|
|
12
|
+
*/
|
|
13
|
+
export declare const getAuthHeaders: (jwt?: JwtToken) => AuthHeaders;
|
|
14
|
+
/**
|
|
15
|
+
* Validates that a JWT token is properly formatted
|
|
16
|
+
* @param token - The JWT token to validate
|
|
17
|
+
* @returns True if token appears to be a valid JWT format
|
|
18
|
+
*/
|
|
19
|
+
export declare const isValidJwtFormat: (token: string) => boolean;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dismissible/react-client",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist",
|
|
@@ -11,9 +11,9 @@
|
|
|
11
11
|
"types": "./dist/root.d.ts",
|
|
12
12
|
"exports": {
|
|
13
13
|
".": {
|
|
14
|
+
"types": "./dist/root.d.ts",
|
|
14
15
|
"import": "./dist/dismissible-client.es.js",
|
|
15
|
-
"require": "./dist/dismissible-client.umd.js"
|
|
16
|
-
"types": "./dist/root.d.ts"
|
|
16
|
+
"require": "./dist/dismissible-client.umd.js"
|
|
17
17
|
}
|
|
18
18
|
},
|
|
19
19
|
"scripts": {
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { default as React } from 'react';
|
|
2
|
-
interface MSWContextType {
|
|
3
|
-
isMSWEnabled: boolean;
|
|
4
|
-
toggleMSW: (enabled: boolean) => void;
|
|
5
|
-
}
|
|
6
|
-
export declare const useMSW: () => MSWContextType;
|
|
7
|
-
interface MSWProviderProps {
|
|
8
|
-
children: React.ReactNode;
|
|
9
|
-
initialEnabled?: boolean;
|
|
10
|
-
}
|
|
11
|
-
export declare const MSWProvider: React.FC<MSWProviderProps>;
|
|
12
|
-
export declare const MSWStatus: React.FC;
|
|
13
|
-
export {};
|