@dismissible/react-client 0.3.2-canary.3.c1b8c41 → 0.3.2-canary.4.578bcba

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -100,7 +100,7 @@ import { Dismissible } from '@dismissible/react-client';
100
100
 
101
101
  function WelcomeBanner() {
102
102
  return (
103
- <Dismissible id="welcome-banner">
103
+ <Dismissible itemId="welcome-banner">
104
104
  <div className="banner">
105
105
  <h2>Welcome to our app!</h2>
106
106
  <p>This banner can be dismissed and won't show again.</p>
@@ -193,22 +193,42 @@ The main component for creating dismissible content.
193
193
 
194
194
  | Prop | Type | Required | Description |
195
195
  |------|------|----------|-------------|
196
- | `id` | `string` | ✅ | Unique identifier for the dismissible item |
196
+ | `itemId` | `string` | ✅ | Unique identifier for the dismissible item |
197
197
  | `children` | `ReactNode` | ✅ | Content to render when not dismissed |
198
198
  | `onDismiss` | `() => void` | ❌ | Callback fired when item is dismissed |
199
- | `LoadingComponent` | `ComponentType<{id: string}>` | ❌ | Custom loading component |
200
- | `ErrorComponent` | `ComponentType<{id: string, error: Error}>` | ❌ | Custom error component |
201
- | `DismissButtonComponent` | `ComponentType<{id: string, onDismiss: () => Promise<void>, ariaLabel: string}>` | ❌ | Custom dismiss button |
199
+ | `LoadingComponent` | `ComponentType<{itemId: string}>` | ❌ | Custom loading component |
200
+ | `ErrorComponent` | `ComponentType<{itemId: string, error: Error}>` | ❌ | Custom error component |
201
+ | `DismissButtonComponent` | `ComponentType<{onDismiss: () => Promise<void>, ariaLabel: string}>` | ❌ | Custom dismiss button |
202
202
  | `ignoreErrors` | `boolean` | ❌ | Ignore errors and display component anyway (default: false) |
203
203
  | `enableCache` | `boolean` | ❌ | Enable localStorage caching (default: true) |
204
204
  | `cachePrefix` | `string` | ❌ | Cache key prefix (default: 'dismissible') |
205
205
  | `cacheExpiration` | `number` | ❌ | Cache expiration time in milliseconds |
206
+ | `metadata` | `string[]` | ❌ | Optional metadata as key:value pairs (can be repeated) |
206
207
 
207
208
  #### Example
208
209
 
209
210
  ```tsx
210
211
  <Dismissible
211
- id="promo-banner"
212
+ itemId="promo-banner"
213
+ onDismiss={() => console.log('Banner dismissed')}
214
+ >
215
+ <div className="promo">
216
+ <h3>Special Offer!</h3>
217
+ <p>Get 50% off your first order</p>
218
+ </div>
219
+ </Dismissible>
220
+ ```
221
+
222
+ #### Example with Metadata
223
+
224
+ ```tsx
225
+ <Dismissible
226
+ itemId="promo-banner"
227
+ metadata={{
228
+ version: 2,
229
+ category: "promotional",
230
+ campaign: "summer-sale"
231
+ }}
212
232
  onDismiss={() => console.log('Banner dismissed')}
213
233
  >
214
234
  <div className="promo">
@@ -226,8 +246,18 @@ For custom implementations and advanced use cases.
226
246
 
227
247
  | Parameter | Type | Required | Description |
228
248
  |-----------|------|----------|-------------|
229
- | `id` | `string` | ✅ | Unique identifier for the dismissible item |
230
- | `options` | `object` | ❌ | Cache configuration options |
249
+ | `itemId` | `string` | ✅ | Unique identifier for the dismissible item |
250
+ | `options` | `object` | ❌ | Configuration options |
251
+
252
+ #### Options
253
+
254
+ | Option | Type | Required | Description |
255
+ |--------|------|----------|-------------|
256
+ | `enableCache` | `boolean` | ❌ | Enable localStorage caching (default: true) |
257
+ | `cachePrefix` | `string` | ❌ | Cache key prefix (default: 'dismissible') |
258
+ | `cacheExpiration` | `number` | ❌ | Cache expiration time in milliseconds |
259
+ | `metadata` | `IMetadata` | ❌ | Optional metadata object (`{ [key: string]: string \| number }`) |
260
+ | `initialData` | `IDismissibleItem` | ❌ | Initial data for the dismissible item |
231
261
 
232
262
  #### Returns
233
263
 
@@ -245,8 +275,8 @@ For custom implementations and advanced use cases.
245
275
  ```tsx
246
276
  import { useDismissibleItem } from '@dismissible/react-client';
247
277
 
248
- function CustomDismissible({ id, children }) {
249
- const { dismissedOn, dismiss, restore, isLoading, error } = useDismissibleItem(id);
278
+ function CustomDismissible({ itemId, children }) {
279
+ const { dismissedOn, dismiss, restore, isLoading, error } = useDismissibleItem(itemId);
250
280
 
251
281
  if (isLoading) {
252
282
  return <div>Loading...</div>;
@@ -295,7 +325,7 @@ function App() {
295
325
 
296
326
  function Dashboard() {
297
327
  return (
298
- <Dismissible id="welcome-banner">
328
+ <Dismissible itemId="welcome-banner">
299
329
  <div className="alert alert-info">
300
330
  <h4>Welcome!</h4>
301
331
  <p>Thanks for joining our platform. Here are some quick tips to get started.</p>
@@ -330,7 +360,7 @@ function Dashboard() {
330
360
  return (
331
361
  <div>
332
362
  {/* Dismissible state is tracked per user */}
333
- <Dismissible id="user-welcome-banner">
363
+ <Dismissible itemId="user-welcome-banner">
334
364
  <div className="alert alert-info">
335
365
  <h4>Welcome back!</h4>
336
366
  <p>You have 3 new notifications.</p>
@@ -359,7 +389,7 @@ const CustomDismissButton = ({ onDismiss, ariaLabel }) => (
359
389
  function CustomBanner() {
360
390
  return (
361
391
  <Dismissible
362
- id="custom-banner"
392
+ itemId="custom-banner"
363
393
  DismissButtonComponent={CustomDismissButton}
364
394
  >
365
395
  <div className="banner">
@@ -375,7 +405,7 @@ function CustomBanner() {
375
405
  ```tsx
376
406
  import { Dismissible } from '@dismissible/react-client';
377
407
 
378
- const CustomLoader = ({ id }) => (
408
+ const CustomLoader = ({ itemId }) => (
379
409
  <div className="spinner">
380
410
  <div className="bounce1"></div>
381
411
  <div className="bounce2"></div>
@@ -396,7 +426,7 @@ const CustomError = ({ error }) => (
396
426
  function AdvancedBanner() {
397
427
  return (
398
428
  <Dismissible
399
- id="advanced-banner"
429
+ itemId="advanced-banner"
400
430
  LoadingComponent={CustomLoader}
401
431
  ErrorComponent={CustomError}
402
432
  >
@@ -416,19 +446,19 @@ import { Dismissible } from '@dismissible/react-client';
416
446
  function Dashboard() {
417
447
  return (
418
448
  <div>
419
- <Dismissible id="feature-announcement">
449
+ <Dismissible itemId="feature-announcement">
420
450
  <div className="alert alert-success">
421
451
  🎉 New feature: Dark mode is now available!
422
452
  </div>
423
453
  </Dismissible>
424
454
 
425
- <Dismissible id="maintenance-notice">
455
+ <Dismissible itemId="maintenance-notice">
426
456
  <div className="alert alert-warning">
427
457
  ⚠️ Scheduled maintenance: Sunday 2AM-4AM EST
428
458
  </div>
429
459
  </Dismissible>
430
460
 
431
- <Dismissible id="survey-request">
461
+ <Dismissible itemId="survey-request">
432
462
  <div className="alert alert-info">
433
463
  📝 Help us improve! Take our 2-minute survey.
434
464
  </div>
@@ -447,7 +477,7 @@ import { Dismissible } from '@dismissible/react-client';
447
477
  function RobustBanner() {
448
478
  return (
449
479
  <Dismissible
450
- id="important-announcement"
480
+ itemId="important-announcement"
451
481
  ignoreErrors={true}
452
482
  >
453
483
  <div className="important-banner">
@@ -533,8 +563,8 @@ function AppWithTokenRefresh() {
533
563
  import { useDismissibleItem } from '@dismissible/react-client';
534
564
  import { useState, useEffect } from 'react';
535
565
 
536
- function SmartNotification({ id, message, type = 'info' }) {
537
- const { dismissedOn, dismiss, isLoading } = useDismissibleItem(id);
566
+ function SmartNotification({ itemId, message, type = 'info' }) {
567
+ const { dismissedOn, dismiss, isLoading } = useDismissibleItem(itemId);
538
568
  const [autoHide, setAutoHide] = useState(false);
539
569
 
540
570
  // Auto-hide after 10 seconds for info messages
@@ -568,6 +598,56 @@ function SmartNotification({ id, message, type = 'info' }) {
568
598
  }
569
599
  ```
570
600
 
601
+ ### Using Metadata with Dismissible Items
602
+
603
+ Metadata allows you to attach additional information to dismissible items, which can be useful for analytics, filtering, or conditional logic:
604
+
605
+ ```tsx
606
+ import { Dismissible, useDismissibleItem } from '@dismissible/react-client';
607
+
608
+ // Using metadata with the Dismissible component (object format)
609
+ function PromotionalBanner({ campaignId, version }) {
610
+ return (
611
+ <Dismissible
612
+ itemId={`promo-${campaignId}`}
613
+ metadata={{
614
+ version: version,
615
+ category: "promotional",
616
+ campaign: campaignId,
617
+ }}
618
+ >
619
+ <div className="promo-banner">
620
+ <h3>Special Offer!</h3>
621
+ <p>Limited time promotion</p>
622
+ </div>
623
+ </Dismissible>
624
+ );
625
+ }
626
+
627
+ // Using metadata with the hook (same object format)
628
+ function CustomNotification({ itemId, category, priority }) {
629
+ const { dismissedOn, dismiss, isLoading } = useDismissibleItem(itemId, {
630
+ metadata: {
631
+ category,
632
+ priority,
633
+ },
634
+ });
635
+
636
+ if (dismissedOn) {
637
+ return null;
638
+ }
639
+
640
+ return (
641
+ <div className={`notification notification-${category}`}>
642
+ <span>Notification content</span>
643
+ <button onClick={dismiss} disabled={isLoading}>
644
+ Dismiss
645
+ </button>
646
+ </div>
647
+ );
648
+ }
649
+ ```
650
+
571
651
  ### Restoring Dismissed Items
572
652
 
573
653
  Use the `restore` function to bring back previously dismissed content:
@@ -575,8 +655,8 @@ Use the `restore` function to bring back previously dismissed content:
575
655
  ```tsx
576
656
  import { useDismissibleItem } from '@dismissible/react-client';
577
657
 
578
- function RestorableBanner({ id }) {
579
- const { dismissedOn, dismiss, restore, isLoading } = useDismissibleItem(id);
658
+ function RestorableBanner({ itemId }) {
659
+ const { dismissedOn, dismiss, restore, isLoading } = useDismissibleItem(itemId);
580
660
 
581
661
  if (dismissedOn) {
582
662
  return (
@@ -674,10 +754,11 @@ The library includes minimal default styles. You can override them or provide yo
674
754
  The library is written in TypeScript and exports all type definitions:
675
755
 
676
756
  ```tsx
677
- import type {
757
+ import type {
678
758
  DismissibleProps,
679
759
  DismissibleProviderProps,
680
760
  JwtToken,
761
+ IMetadata,
681
762
  } from '@dismissible/react-client';
682
763
 
683
764
  // Custom provider wrapper
@@ -1,4 +1,5 @@
1
1
  import { default as React } from 'react';
2
+ import { IMetadata } from '../hooks/useDismissibleItem';
2
3
  /**
3
4
  * Props for the Dismissible component
4
5
  */
@@ -31,6 +32,8 @@ export interface DismissibleProps {
31
32
  cacheExpiration?: number;
32
33
  /** Ignore errors and display the component anyway (default: false) */
33
34
  ignoreErrors?: boolean;
35
+ /** Optional metadata object that will be converted to key:value string pairs */
36
+ metadata?: IMetadata;
34
37
  }
35
38
  /**
36
39
  * A wrapper component that can be dismissed and hidden by users
@@ -46,6 +49,7 @@ export interface DismissibleProps {
46
49
  * @param cachePrefix - Cache key prefix
47
50
  * @param cacheExpiration - Cache expiration time in milliseconds
48
51
  * @param ignoreErrors - Ignore errors and display the component anyway
52
+ * @param metadata - Optional metadata object that will be converted to key:value string pairs
49
53
  * @returns JSX element or null if dismissed
50
54
  */
51
55
  export declare const Dismissible: React.FC<DismissibleProps>;
@@ -1,59 +1,59 @@
1
1
  var he = Object.defineProperty, me = Object.defineProperties;
2
2
  var ye = Object.getOwnPropertyDescriptors;
3
3
  var M = Object.getOwnPropertySymbols;
4
- var re = Object.prototype.hasOwnProperty, ne = Object.prototype.propertyIsEnumerable;
5
- var te = (e, r, t) => r in e ? he(e, r, { enumerable: !0, configurable: !0, writable: !0, value: t }) : e[r] = t, b = (e, r) => {
4
+ var ne = Object.prototype.hasOwnProperty, se = Object.prototype.propertyIsEnumerable;
5
+ var re = (e, r, t) => r in e ? he(e, r, { enumerable: !0, configurable: !0, writable: !0, value: t }) : e[r] = t, p = (e, r) => {
6
6
  for (var t in r || (r = {}))
7
- re.call(r, t) && te(e, t, r[t]);
7
+ ne.call(r, t) && re(e, t, r[t]);
8
8
  if (M)
9
9
  for (var t of M(r))
10
- ne.call(r, t) && te(e, t, r[t]);
10
+ se.call(r, t) && re(e, t, r[t]);
11
11
  return e;
12
- }, E = (e, r) => me(e, ye(r));
13
- var Q = (e, r) => {
12
+ }, R = (e, r) => me(e, ye(r));
13
+ var V = (e, r) => {
14
14
  var t = {};
15
15
  for (var n in e)
16
- re.call(e, n) && r.indexOf(n) < 0 && (t[n] = e[n]);
16
+ ne.call(e, n) && r.indexOf(n) < 0 && (t[n] = e[n]);
17
17
  if (e != null && M)
18
18
  for (var n of M(e))
19
- r.indexOf(n) < 0 && ne.call(e, n) && (t[n] = e[n]);
19
+ r.indexOf(n) < 0 && se.call(e, n) && (t[n] = e[n]);
20
20
  return t;
21
21
  };
22
22
  var $ = (e, r, t) => new Promise((n, o) => {
23
23
  var s = (f) => {
24
24
  try {
25
- l(t.next(f));
26
- } catch (d) {
27
- o(d);
25
+ i(t.next(f));
26
+ } catch (y) {
27
+ o(y);
28
28
  }
29
- }, i = (f) => {
29
+ }, u = (f) => {
30
30
  try {
31
- l(t.throw(f));
32
- } catch (d) {
33
- o(d);
31
+ i(t.throw(f));
32
+ } catch (y) {
33
+ o(y);
34
34
  }
35
- }, l = (f) => f.done ? n(f.value) : Promise.resolve(f.value).then(s, i);
36
- l((t = t.apply(e, r)).next());
35
+ }, i = (f) => f.done ? n(f.value) : Promise.resolve(f.value).then(s, u);
36
+ i((t = t.apply(e, r)).next());
37
37
  });
38
- import { jsx as U, jsxs as be } from "react/jsx-runtime";
39
- import { createContext as pe, useContext as we, useMemo as Y, useRef as J, useState as W, useCallback as V, useEffect as _ } from "react";
38
+ import { jsx as T, jsxs as be } from "react/jsx-runtime";
39
+ import { createContext as pe, useContext as we, useMemo as Z, useRef as J, useState as W, useCallback as X, useEffect as _ } from "react";
40
40
  const ge = /\{[^{}]+\}/g, Ee = () => {
41
41
  var e, r;
42
42
  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;
43
43
  };
44
- function Re() {
44
+ function ve() {
45
45
  return Math.random().toString(36).slice(2, 11);
46
46
  }
47
- function ve(e) {
48
- let A = b({}, e), {
47
+ function Re(e) {
48
+ let U = p({}, e), {
49
49
  baseUrl: r = "",
50
50
  Request: t = globalThis.Request,
51
51
  fetch: n = globalThis.fetch,
52
52
  querySerializer: o,
53
53
  bodySerializer: s,
54
- headers: i,
55
- requestInitExt: l = void 0
56
- } = A, f = Q(A, [
54
+ headers: u,
55
+ requestInitExt: i = void 0
56
+ } = U, f = V(U, [
57
57
  "baseUrl",
58
58
  "Request",
59
59
  "fetch",
@@ -62,23 +62,23 @@ function ve(e) {
62
62
  "headers",
63
63
  "requestInitExt"
64
64
  ]);
65
- l = Ee() ? l : void 0, r = ie(r);
66
- const d = [];
67
- function g(u, a) {
65
+ i = Ee() ? i : void 0, r = ae(r);
66
+ const y = [];
67
+ function d(l, a) {
68
68
  return $(this, null, function* () {
69
- var ee;
70
- const Z = a || {}, {
71
- baseUrl: R,
72
- fetch: C = n,
73
- Request: O = t,
74
- headers: x,
75
- params: v = {},
76
- parseAs: j = "json",
69
+ var te;
70
+ const ee = a || {}, {
71
+ baseUrl: v,
72
+ fetch: H = n,
73
+ Request: x = t,
74
+ headers: O,
75
+ params: E = {},
76
+ parseAs: A = "json",
77
77
  querySerializer: S,
78
- bodySerializer: P = s != null ? s : xe,
78
+ bodySerializer: j = s != null ? s : xe,
79
79
  body: z,
80
- middleware: k = []
81
- } = Z, c = Q(Z, [
80
+ middleware: G = []
81
+ } = ee, I = V(ee, [
82
82
  "baseUrl",
83
83
  "fetch",
84
84
  "Request",
@@ -90,61 +90,61 @@ function ve(e) {
90
90
  "body",
91
91
  "middleware"
92
92
  ]);
93
- let y = r;
94
- R && (y = (ee = ie(R)) != null ? ee : r);
95
- let h = typeof o == "function" ? o : se(o);
96
- S && (h = typeof S == "function" ? S : se(b(b({}, typeof o == "object" ? o : {}), S)));
97
- const H = z === void 0 ? void 0 : P(
93
+ let c = r;
94
+ v && (c = (te = ae(v)) != null ? te : r);
95
+ let b = typeof o == "function" ? o : oe(o);
96
+ S && (b = typeof S == "function" ? S : oe(p(p({}, typeof o == "object" ? o : {}), S)));
97
+ const h = z === void 0 ? void 0 : j(
98
98
  z,
99
99
  // Note: we declare mergeHeaders() both here and below because it’s a bit of a chicken-or-egg situation:
100
100
  // bodySerializer() needs all headers so we aren’t dropping ones set by the user, however,
101
101
  // the result of this ALSO sets the lowest-priority content-type header. So we re-merge below,
102
102
  // setting the content-type at the very beginning to be overwritten.
103
103
  // Lastly, based on the way headers work, it’s not a simple “present-or-not” check becauase null intentionally un-sets headers.
104
- oe(i, x, v.header)
105
- ), G = oe(
104
+ ie(u, O, E.header)
105
+ ), k = ie(
106
106
  // with no body, we should not to set Content-Type
107
- H === void 0 || // if serialized body is FormData; browser will correctly set Content-Type & boundary expression
108
- H instanceof FormData ? {} : {
107
+ h === void 0 || // if serialized body is FormData; browser will correctly set Content-Type & boundary expression
108
+ h instanceof FormData ? {} : {
109
109
  "Content-Type": "application/json"
110
110
  },
111
- i,
112
- x,
113
- v.header
114
- ), D = [...d, ...k], de = E(b(b({
111
+ u,
112
+ O,
113
+ E.header
114
+ ), C = [...y, ...G], K = R(p(p({
115
115
  redirect: "follow"
116
- }, f), c), {
117
- body: H,
118
- headers: G
116
+ }, f), I), {
117
+ body: h,
118
+ headers: k
119
119
  });
120
- let F, L, T = new O(
121
- Se(u, { baseUrl: y, params: v, querySerializer: h }),
122
- de
120
+ let F, L, D = new x(
121
+ Se(l, { baseUrl: c, params: E, querySerializer: b }),
122
+ K
123
123
  ), m;
124
- for (const w in c)
125
- w in T || (T[w] = c[w]);
126
- if (D.length) {
127
- F = Re(), L = Object.freeze({
128
- baseUrl: y,
129
- fetch: C,
130
- parseAs: j,
131
- querySerializer: h,
132
- bodySerializer: P
124
+ for (const g in I)
125
+ g in D || (D[g] = I[g]);
126
+ if (C.length) {
127
+ F = ve(), L = Object.freeze({
128
+ baseUrl: c,
129
+ fetch: H,
130
+ parseAs: A,
131
+ querySerializer: b,
132
+ bodySerializer: j
133
133
  });
134
- for (const w of D)
135
- if (w && typeof w == "object" && typeof w.onRequest == "function") {
136
- const p = yield w.onRequest({
137
- request: T,
138
- schemaPath: u,
139
- params: v,
134
+ for (const g of C)
135
+ if (g && typeof g == "object" && typeof g.onRequest == "function") {
136
+ const w = yield g.onRequest({
137
+ request: D,
138
+ schemaPath: l,
139
+ params: E,
140
140
  options: L,
141
141
  id: F
142
142
  });
143
- if (p)
144
- if (p instanceof O)
145
- T = p;
146
- else if (p instanceof Response) {
147
- m = p;
143
+ if (w)
144
+ if (w instanceof x)
145
+ D = w;
146
+ else if (w instanceof Response) {
147
+ m = w;
148
148
  break;
149
149
  } else
150
150
  throw new Error("onRequest: must return new Request() or Response() when modifying the request");
@@ -152,46 +152,46 @@ function ve(e) {
152
152
  }
153
153
  if (!m) {
154
154
  try {
155
- m = yield C(T, l);
156
- } catch (w) {
157
- let p = w;
158
- if (D.length)
159
- for (let q = D.length - 1; q >= 0; q--) {
160
- const N = D[q];
155
+ m = yield H(D, i);
156
+ } catch (g) {
157
+ let w = g;
158
+ if (C.length)
159
+ for (let q = C.length - 1; q >= 0; q--) {
160
+ const N = C[q];
161
161
  if (N && typeof N == "object" && typeof N.onError == "function") {
162
- const I = yield N.onError({
163
- request: T,
164
- error: p,
165
- schemaPath: u,
166
- params: v,
162
+ const P = yield N.onError({
163
+ request: D,
164
+ error: w,
165
+ schemaPath: l,
166
+ params: E,
167
167
  options: L,
168
168
  id: F
169
169
  });
170
- if (I) {
171
- if (I instanceof Response) {
172
- p = void 0, m = I;
170
+ if (P) {
171
+ if (P instanceof Response) {
172
+ w = void 0, m = P;
173
173
  break;
174
174
  }
175
- if (I instanceof Error) {
176
- p = I;
175
+ if (P instanceof Error) {
176
+ w = P;
177
177
  continue;
178
178
  }
179
179
  throw new Error("onError: must return new Response() or instance of Error");
180
180
  }
181
181
  }
182
182
  }
183
- if (p)
184
- throw p;
183
+ if (w)
184
+ throw w;
185
185
  }
186
- if (D.length)
187
- for (let w = D.length - 1; w >= 0; w--) {
188
- const p = D[w];
189
- if (p && typeof p == "object" && typeof p.onResponse == "function") {
190
- const q = yield p.onResponse({
191
- request: T,
186
+ if (C.length)
187
+ for (let g = C.length - 1; g >= 0; g--) {
188
+ const w = C[g];
189
+ if (w && typeof w == "object" && typeof w.onResponse == "function") {
190
+ const q = yield w.onResponse({
191
+ request: D,
192
192
  response: m,
193
- schemaPath: u,
194
- params: v,
193
+ schemaPath: l,
194
+ params: E,
195
195
  options: L,
196
196
  id: F
197
197
  });
@@ -203,68 +203,68 @@ function ve(e) {
203
203
  }
204
204
  }
205
205
  }
206
- if (m.status === 204 || T.method === "HEAD" || m.headers.get("Content-Length") === "0")
206
+ if (m.status === 204 || D.method === "HEAD" || m.headers.get("Content-Length") === "0")
207
207
  return m.ok ? { data: void 0, response: m } : { error: void 0, response: m };
208
208
  if (m.ok)
209
- return j === "stream" ? { data: m.body, response: m } : { data: yield m[j](), response: m };
210
- let K = yield m.text();
209
+ return A === "stream" ? { data: m.body, response: m } : { data: yield m[A](), response: m };
210
+ let Q = yield m.text();
211
211
  try {
212
- K = JSON.parse(K);
213
- } catch (w) {
212
+ Q = JSON.parse(Q);
213
+ } catch (g) {
214
214
  }
215
- return { error: K, response: m };
215
+ return { error: Q, response: m };
216
216
  });
217
217
  }
218
218
  return {
219
- request(u, a, R) {
220
- return g(a, E(b({}, R), { method: u.toUpperCase() }));
219
+ request(l, a, v) {
220
+ return d(a, R(p({}, v), { method: l.toUpperCase() }));
221
221
  },
222
222
  /** Call a GET endpoint */
223
- GET(u, a) {
224
- return g(u, E(b({}, a), { method: "GET" }));
223
+ GET(l, a) {
224
+ return d(l, R(p({}, a), { method: "GET" }));
225
225
  },
226
226
  /** Call a PUT endpoint */
227
- PUT(u, a) {
228
- return g(u, E(b({}, a), { method: "PUT" }));
227
+ PUT(l, a) {
228
+ return d(l, R(p({}, a), { method: "PUT" }));
229
229
  },
230
230
  /** Call a POST endpoint */
231
- POST(u, a) {
232
- return g(u, E(b({}, a), { method: "POST" }));
231
+ POST(l, a) {
232
+ return d(l, R(p({}, a), { method: "POST" }));
233
233
  },
234
234
  /** Call a DELETE endpoint */
235
- DELETE(u, a) {
236
- return g(u, E(b({}, a), { method: "DELETE" }));
235
+ DELETE(l, a) {
236
+ return d(l, R(p({}, a), { method: "DELETE" }));
237
237
  },
238
238
  /** Call a OPTIONS endpoint */
239
- OPTIONS(u, a) {
240
- return g(u, E(b({}, a), { method: "OPTIONS" }));
239
+ OPTIONS(l, a) {
240
+ return d(l, R(p({}, a), { method: "OPTIONS" }));
241
241
  },
242
242
  /** Call a HEAD endpoint */
243
- HEAD(u, a) {
244
- return g(u, E(b({}, a), { method: "HEAD" }));
243
+ HEAD(l, a) {
244
+ return d(l, R(p({}, a), { method: "HEAD" }));
245
245
  },
246
246
  /** Call a PATCH endpoint */
247
- PATCH(u, a) {
248
- return g(u, E(b({}, a), { method: "PATCH" }));
247
+ PATCH(l, a) {
248
+ return d(l, R(p({}, a), { method: "PATCH" }));
249
249
  },
250
250
  /** Call a TRACE endpoint */
251
- TRACE(u, a) {
252
- return g(u, E(b({}, a), { method: "TRACE" }));
251
+ TRACE(l, a) {
252
+ return d(l, R(p({}, a), { method: "TRACE" }));
253
253
  },
254
254
  /** Register middleware */
255
- use(...u) {
256
- for (const a of u)
255
+ use(...l) {
256
+ for (const a of l)
257
257
  if (a) {
258
258
  if (typeof a != "object" || !("onRequest" in a || "onResponse" in a || "onError" in a))
259
259
  throw new Error("Middleware must be an object with one of `onRequest()`, `onResponse() or `onError()`");
260
- d.push(a);
260
+ y.push(a);
261
261
  }
262
262
  },
263
263
  /** Unregister middleware */
264
- eject(...u) {
265
- for (const a of u) {
266
- const R = d.indexOf(a);
267
- R !== -1 && d.splice(R, 1);
264
+ eject(...l) {
265
+ for (const a of l) {
266
+ const v = y.indexOf(a);
267
+ v !== -1 && y.splice(v, 1);
268
268
  }
269
269
  }
270
270
  };
@@ -278,7 +278,7 @@ function B(e, r, t) {
278
278
  );
279
279
  return `${e}=${(t == null ? void 0 : t.allowReserved) === !0 ? r : encodeURIComponent(r)}`;
280
280
  }
281
- function le(e, r, t) {
281
+ function ue(e, r, t) {
282
282
  if (!r || typeof r != "object")
283
283
  return "";
284
284
  const n = [], o = {
@@ -287,41 +287,41 @@ function le(e, r, t) {
287
287
  matrix: ";"
288
288
  }[t.style] || "&";
289
289
  if (t.style !== "deepObject" && t.explode === !1) {
290
- for (const l in r)
291
- n.push(l, t.allowReserved === !0 ? r[l] : encodeURIComponent(r[l]));
292
- const i = n.join(",");
290
+ for (const i in r)
291
+ n.push(i, t.allowReserved === !0 ? r[i] : encodeURIComponent(r[i]));
292
+ const u = n.join(",");
293
293
  switch (t.style) {
294
294
  case "form":
295
- return `${e}=${i}`;
295
+ return `${e}=${u}`;
296
296
  case "label":
297
- return `.${i}`;
297
+ return `.${u}`;
298
298
  case "matrix":
299
- return `;${e}=${i}`;
299
+ return `;${e}=${u}`;
300
300
  default:
301
- return i;
301
+ return u;
302
302
  }
303
303
  }
304
- for (const i in r) {
305
- const l = t.style === "deepObject" ? `${e}[${i}]` : i;
306
- n.push(B(l, r[i], t));
304
+ for (const u in r) {
305
+ const i = t.style === "deepObject" ? `${e}[${u}]` : u;
306
+ n.push(B(i, r[u], t));
307
307
  }
308
308
  const s = n.join(o);
309
309
  return t.style === "label" || t.style === "matrix" ? `${o}${s}` : s;
310
310
  }
311
- function ue(e, r, t) {
311
+ function fe(e, r, t) {
312
312
  if (!Array.isArray(r))
313
313
  return "";
314
314
  if (t.explode === !1) {
315
- const s = { form: ",", spaceDelimited: "%20", pipeDelimited: "|" }[t.style] || ",", i = (t.allowReserved === !0 ? r : r.map((l) => encodeURIComponent(l))).join(s);
315
+ const s = { form: ",", spaceDelimited: "%20", pipeDelimited: "|" }[t.style] || ",", u = (t.allowReserved === !0 ? r : r.map((i) => encodeURIComponent(i))).join(s);
316
316
  switch (t.style) {
317
317
  case "simple":
318
- return i;
318
+ return u;
319
319
  case "label":
320
- return `.${i}`;
320
+ return `.${u}`;
321
321
  case "matrix":
322
- return `;${e}=${i}`;
322
+ return `;${e}=${u}`;
323
323
  default:
324
- return `${e}=${i}`;
324
+ return `${e}=${u}`;
325
325
  }
326
326
  }
327
327
  const n = { simple: ",", label: ".", matrix: ";" }[t.style] || "&", o = [];
@@ -329,7 +329,7 @@ function ue(e, r, t) {
329
329
  t.style === "simple" || t.style === "label" ? o.push(t.allowReserved === !0 ? s : encodeURIComponent(s)) : o.push(B(e, s, t));
330
330
  return t.style === "label" || t.style === "matrix" ? `${n}${o.join(n)}` : o.join(n);
331
331
  }
332
- function se(e) {
332
+ function oe(e) {
333
333
  return function(t) {
334
334
  const n = [];
335
335
  if (t && typeof t == "object")
@@ -340,7 +340,7 @@ function se(e) {
340
340
  if (s.length === 0)
341
341
  continue;
342
342
  n.push(
343
- ue(o, s, E(b({
343
+ fe(o, s, R(p({
344
344
  style: "form",
345
345
  explode: !0
346
346
  }, e == null ? void 0 : e.array), {
@@ -351,7 +351,7 @@ function se(e) {
351
351
  }
352
352
  if (typeof s == "object") {
353
353
  n.push(
354
- le(o, s, E(b({
354
+ ue(o, s, R(p({
355
355
  style: "deepObject",
356
356
  explode: !0
357
357
  }, e == null ? void 0 : e.object), {
@@ -370,23 +370,23 @@ function Ce(e, r) {
370
370
  var n;
371
371
  let t = e;
372
372
  for (const o of (n = e.match(ge)) != null ? n : []) {
373
- let s = o.substring(1, o.length - 1), i = !1, l = "simple";
374
- if (s.endsWith("*") && (i = !0, s = s.substring(0, s.length - 1)), s.startsWith(".") ? (l = "label", s = s.substring(1)) : s.startsWith(";") && (l = "matrix", s = s.substring(1)), !r || r[s] === void 0 || r[s] === null)
373
+ let s = o.substring(1, o.length - 1), u = !1, i = "simple";
374
+ if (s.endsWith("*") && (u = !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)
375
375
  continue;
376
376
  const f = r[s];
377
377
  if (Array.isArray(f)) {
378
- t = t.replace(o, ue(s, f, { style: l, explode: i }));
378
+ t = t.replace(o, fe(s, f, { style: i, explode: u }));
379
379
  continue;
380
380
  }
381
381
  if (typeof f == "object") {
382
- t = t.replace(o, le(s, f, { style: l, explode: i }));
382
+ t = t.replace(o, ue(s, f, { style: i, explode: u }));
383
383
  continue;
384
384
  }
385
- if (l === "matrix") {
385
+ if (i === "matrix") {
386
386
  t = t.replace(o, `;${B(s, f)}`);
387
387
  continue;
388
388
  }
389
- t = t.replace(o, l === "label" ? `.${encodeURIComponent(f)}` : encodeURIComponent(f));
389
+ t = t.replace(o, i === "label" ? `.${encodeURIComponent(f)}` : encodeURIComponent(f));
390
390
  }
391
391
  return t;
392
392
  }
@@ -401,7 +401,7 @@ function Se(e, r) {
401
401
  let n = r.querySerializer((s = r.params.query) != null ? s : {});
402
402
  return n.startsWith("?") && (n = n.substring(1)), n && (t += `?${n}`), t;
403
403
  }
404
- function oe(...e) {
404
+ function ie(...e) {
405
405
  const r = new Headers();
406
406
  for (const t of e) {
407
407
  if (!t || typeof t != "object")
@@ -411,25 +411,25 @@ function oe(...e) {
411
411
  if (s === null)
412
412
  r.delete(o);
413
413
  else if (Array.isArray(s))
414
- for (const i of s)
415
- r.append(o, i);
414
+ for (const u of s)
415
+ r.append(o, u);
416
416
  else s !== void 0 && r.set(o, s);
417
417
  }
418
418
  return r;
419
419
  }
420
- function ie(e) {
420
+ function ae(e) {
421
421
  return e.endsWith("/") ? e.substring(0, e.length - 1) : e;
422
422
  }
423
- const ae = (e, r, t) => {
423
+ const ce = (e, r, t) => {
424
424
  try {
425
425
  const n = `${r}_${e}`, o = localStorage.getItem(n);
426
426
  if (!o) return null;
427
- const { data: s, timestamp: i } = JSON.parse(o);
428
- return t && Date.now() - i > t ? (localStorage.removeItem(n), null) : s;
427
+ const { data: s, timestamp: u } = JSON.parse(o);
428
+ return t && Date.now() - u > t ? (localStorage.removeItem(n), null) : s;
429
429
  } catch (n) {
430
430
  return null;
431
431
  }
432
- }, X = (e, r, t) => {
432
+ }, Y = (e, r, t) => {
433
433
  try {
434
434
  const n = `${t}_${e}`, o = {
435
435
  data: r,
@@ -439,184 +439,190 @@ const ae = (e, r, t) => {
439
439
  } catch (n) {
440
440
  console.warn("Failed to cache dismissible item:", n);
441
441
  }
442
- }, ce = (e, r) => {
442
+ }, le = (e, r) => {
443
443
  try {
444
444
  const t = `${r}_${e}`;
445
445
  localStorage.removeItem(t);
446
446
  } catch (t) {
447
447
  console.warn("Failed to remove cached dismissible item:", t);
448
448
  }
449
- }, fe = pe(
449
+ }, de = pe(
450
450
  null
451
451
  ), $e = () => {
452
- const e = we(fe);
452
+ const e = we(de);
453
453
  if (!e)
454
454
  throw new Error(
455
455
  "useDismissibleContext must be used within a DismissibleProvider"
456
456
  );
457
457
  return e;
458
- }, Ae = "dismissible", je = (e, r = {}) => {
459
- var k;
458
+ }, Ae = (e) => {
459
+ if (e)
460
+ return Object.entries(e).map(([r, t]) => `${r}:${t}`);
461
+ }, je = "dismissible", De = (e, r = {}) => {
462
+ var I;
460
463
  const {
461
464
  initialData: t,
462
465
  enableCache: n = !0,
463
- cachePrefix: o = Ae,
464
- cacheExpiration: s
465
- } = r, i = $e(), { userId: l } = i, f = Y(() => ve({
466
+ cachePrefix: o = je,
467
+ cacheExpiration: s,
468
+ metadata: u
469
+ } = r, i = $e(), { userId: f } = i, y = Z(() => Re({
466
470
  baseUrl: i.baseUrl,
467
471
  headers: {}
468
- }), [i.baseUrl]), d = Y(() => `${l}-${e}`, [l, e]), g = J({
472
+ }), [i.baseUrl]), d = Z(() => `${f}-${e}`, [f, e]), U = J({
469
473
  enableCache: n,
470
474
  cachePrefix: o,
471
475
  cacheExpiration: s
472
- }), A = J(e), u = J(d), a = J(null), [R, C] = W(!1), [O, x] = W(null), [v, j] = W(() => {
476
+ }), l = J(e), a = J(d), v = J(null), [H, x] = W(!1), [O, E] = W(null), [A, S] = W(() => {
473
477
  if (t) return t;
474
478
  if (n) {
475
- const c = ae(
479
+ const c = ce(
476
480
  d,
477
481
  o,
478
482
  s
479
483
  );
480
484
  if (c) return c;
481
485
  }
482
- }), S = V(() => $(void 0, null, function* () {
483
- var y;
486
+ }), j = X(() => $(void 0, null, function* () {
487
+ var b;
484
488
  if (n) {
485
- const h = ae(
489
+ const h = ce(
486
490
  d,
487
491
  o,
488
492
  s
489
493
  );
490
494
  if (h != null && h.dismissedAt) {
491
- j(h), C(!1);
495
+ S(h), x(!1);
492
496
  return;
493
497
  }
494
498
  }
495
- (y = a.current) == null || y.abort();
499
+ (b = v.current) == null || b.abort();
496
500
  const c = new AbortController();
497
- a.current = c, C(!0), x(null);
501
+ v.current = c, x(!0), E(null);
498
502
  try {
499
- const h = yield i.getAuthHeaders(), { data: H, error: G } = yield f.GET(
500
- "/v1/user/{userId}/dismissible-item/{itemId}",
503
+ const h = yield i.getAuthHeaders(), k = Ae(u), { data: C, error: K } = yield y.GET(
504
+ "/v1/users/{userId}/items/{itemId}",
501
505
  {
502
506
  params: {
503
507
  path: {
504
- userId: l,
508
+ userId: f,
505
509
  itemId: e
506
- }
510
+ },
511
+ query: k ? { metadata: k } : void 0
507
512
  },
508
513
  headers: h,
509
514
  signal: c.signal
510
515
  }
511
516
  );
512
- if (G || !H)
517
+ if (K || !C)
513
518
  throw new Error("Failed to fetch dismissible item");
514
- j(H.data), n && X(d, H.data, o);
519
+ S(C.data), n && Y(d, C.data, o);
515
520
  } catch (h) {
516
521
  if (h instanceof Error && h.name === "AbortError")
517
522
  return;
518
- x(
523
+ E(
519
524
  h instanceof Error ? h : new Error("Unknown error occurred")
520
525
  );
521
526
  } finally {
522
- C(!1);
527
+ x(!1);
523
528
  }
524
529
  }), [
525
530
  e,
526
- l,
531
+ f,
527
532
  d,
528
533
  n,
529
534
  o,
530
535
  s,
531
- f,
536
+ u,
537
+ y,
532
538
  i
533
539
  ]);
534
540
  _(() => {
535
- const c = A.current !== e, y = u.current !== d;
536
- c || y ? (A.current = e, u.current = d, S()) : t || S();
537
- }, [e, d, t, S]), _(() => () => {
541
+ const c = l.current !== e, b = a.current !== d;
542
+ c || b ? (l.current = e, a.current = d, j()) : t || j();
543
+ }, [e, d, t, j]), _(() => () => {
538
544
  var c;
539
- (c = a.current) == null || c.abort();
545
+ (c = v.current) == null || c.abort();
540
546
  }, []), _(() => {
541
- const c = g.current;
542
- (c.enableCache !== n || c.cachePrefix !== o || c.cacheExpiration !== s) && (c.cachePrefix !== o && ce(d, c.cachePrefix), !n && c.enableCache && ce(d, c.cachePrefix), g.current = {
547
+ const c = U.current;
548
+ (c.enableCache !== n || c.cachePrefix !== o || c.cacheExpiration !== s) && (c.cachePrefix !== o && le(d, c.cachePrefix), !n && c.enableCache && le(d, c.cachePrefix), U.current = {
543
549
  enableCache: n,
544
550
  cachePrefix: o,
545
551
  cacheExpiration: s
546
- }, S());
547
- }, [n, o, s, d, S]);
548
- const P = V(() => $(void 0, null, function* () {
549
- x(null);
552
+ }, j());
553
+ }, [n, o, s, d, j]);
554
+ const z = X(() => $(void 0, null, function* () {
555
+ E(null);
550
556
  try {
551
- const c = yield i.getAuthHeaders(), { data: y, error: h } = yield f.DELETE(
552
- "/v1/user/{userId}/dismissible-item/{itemId}",
557
+ const c = yield i.getAuthHeaders(), { data: b, error: h } = yield y.DELETE(
558
+ "/v1/users/{userId}/items/{itemId}",
553
559
  {
554
560
  params: {
555
561
  path: {
556
- userId: l,
562
+ userId: f,
557
563
  itemId: e
558
564
  }
559
565
  },
560
566
  headers: c
561
567
  }
562
568
  );
563
- if (h || !y)
569
+ if (h || !b)
564
570
  throw new Error("Failed to dismiss item");
565
- j(y.data), n && X(d, y.data, o);
571
+ S(b.data), n && Y(d, b.data, o);
566
572
  } catch (c) {
567
- throw x(
573
+ throw E(
568
574
  c instanceof Error ? c : new Error("Failed to dismiss item")
569
575
  ), c;
570
576
  }
571
577
  }), [
572
578
  e,
573
- l,
579
+ f,
574
580
  d,
575
581
  n,
576
582
  o,
577
- f,
583
+ y,
578
584
  i
579
- ]), z = V(() => $(void 0, null, function* () {
580
- x(null);
585
+ ]), G = X(() => $(void 0, null, function* () {
586
+ E(null);
581
587
  try {
582
- const c = yield i.getAuthHeaders(), { data: y, error: h } = yield f.POST(
583
- "/v1/user/{userId}/dismissible-item/{itemId}",
588
+ const c = yield i.getAuthHeaders(), { data: b, error: h } = yield y.POST(
589
+ "/v1/users/{userId}/items/{itemId}",
584
590
  {
585
591
  params: {
586
592
  path: {
587
- userId: l,
593
+ userId: f,
588
594
  itemId: e
589
595
  }
590
596
  },
591
597
  headers: c
592
598
  }
593
599
  );
594
- if (h || !y)
600
+ if (h || !b)
595
601
  throw new Error("Failed to restore item");
596
- j(y.data), n && X(d, y.data, o);
602
+ S(b.data), n && Y(d, b.data, o);
597
603
  } catch (c) {
598
- throw x(
604
+ throw E(
599
605
  c instanceof Error ? c : new Error("Failed to restore item")
600
606
  ), c;
601
607
  }
602
608
  }), [
603
609
  e,
604
- l,
610
+ f,
605
611
  d,
606
612
  n,
607
613
  o,
608
- f,
614
+ y,
609
615
  i
610
616
  ]);
611
617
  return {
612
- dismissedOn: (k = v == null ? void 0 : v.dismissedAt) != null ? k : null,
613
- dismiss: P,
614
- restore: z,
615
- isLoading: R,
618
+ dismissedOn: (I = A == null ? void 0 : A.dismissedAt) != null ? I : null,
619
+ dismiss: z,
620
+ restore: G,
621
+ isLoading: H,
616
622
  error: O,
617
- item: v
623
+ item: A
618
624
  };
619
- }, De = () => /* @__PURE__ */ U("div", { className: "dismissible-loading", "aria-live": "polite", children: "Loading..." }), Te = () => /* @__PURE__ */ U("div", { className: "dismissible-error", role: "alert", children: "Unable to load content. Please try again later." }), Ue = ({ onDismiss: e, ariaLabel: r }) => /* @__PURE__ */ U(
625
+ }, Te = () => /* @__PURE__ */ T("div", { className: "dismissible-loading", "aria-live": "polite", children: "Loading..." }), Ue = () => /* @__PURE__ */ T("div", { className: "dismissible-error", role: "alert", children: "Unable to load content. Please try again later." }), qe = ({ onDismiss: e, ariaLabel: r }) => /* @__PURE__ */ T(
620
626
  "button",
621
627
  {
622
628
  className: "dismissible-button",
@@ -625,40 +631,42 @@ const ae = (e, r, t) => {
625
631
  type: "button",
626
632
  children: "×"
627
633
  }
628
- ), ke = ({
634
+ ), Fe = ({
629
635
  itemId: e,
630
636
  children: r,
631
637
  onDismiss: t,
632
- LoadingComponent: n = De,
633
- ErrorComponent: o = Te,
634
- DismissButtonComponent: s = Ue,
635
- enableCache: i,
636
- cachePrefix: l,
638
+ LoadingComponent: n = Te,
639
+ ErrorComponent: o = Ue,
640
+ DismissButtonComponent: s = qe,
641
+ enableCache: u,
642
+ cachePrefix: i,
637
643
  cacheExpiration: f,
638
- ignoreErrors: d = !1
644
+ ignoreErrors: y = !1,
645
+ metadata: d
639
646
  }) => {
640
- const { dismissedOn: g, isLoading: A, error: u, dismiss: a } = je(
647
+ const { dismissedOn: U, isLoading: l, error: a, dismiss: v } = De(
641
648
  e,
642
649
  {
643
- enableCache: i,
644
- cachePrefix: l,
645
- cacheExpiration: f
650
+ enableCache: u,
651
+ cachePrefix: i,
652
+ cacheExpiration: f,
653
+ metadata: d
646
654
  }
647
- ), [R, C] = W(!1);
655
+ ), [H, x] = W(!1);
648
656
  _(() => {
649
- C(!1);
657
+ x(!1);
650
658
  }, [e]);
651
659
  const O = () => $(void 0, null, function* () {
652
- C(!0);
660
+ x(!0);
653
661
  try {
654
- yield a(), t == null || t();
655
- } catch (x) {
656
- C(!1);
662
+ yield v(), t == null || t();
663
+ } catch (E) {
664
+ x(!1);
657
665
  }
658
666
  });
659
- return A && n ? /* @__PURE__ */ U(n, { itemId: e }) : A && !n ? null : u && o && !d ? /* @__PURE__ */ U(o, { itemId: e, error: u }) : g || R ? null : /* @__PURE__ */ be("div", { className: "dismissible-container", children: [
660
- /* @__PURE__ */ U("div", { className: "dismissible-content", children: r }),
661
- s ? /* @__PURE__ */ U(
667
+ return l && n ? /* @__PURE__ */ T(n, { itemId: e }) : l && !n ? null : a && o && !y ? /* @__PURE__ */ T(o, { itemId: e, error: a }) : U || H ? null : /* @__PURE__ */ be("div", { className: "dismissible-container", children: [
668
+ /* @__PURE__ */ T("div", { className: "dismissible-content", children: r }),
669
+ s ? /* @__PURE__ */ T(
662
670
  s,
663
671
  {
664
672
  onDismiss: O,
@@ -676,45 +684,45 @@ const ae = (e, r, t) => {
676
684
  return;
677
685
  }
678
686
  return e;
679
- }), qe = (e) => $(void 0, null, function* () {
687
+ }), Oe = (e) => $(void 0, null, function* () {
680
688
  const r = yield He(e);
681
689
  return r ? { Authorization: `Bearer ${r}` } : {};
682
- }), Oe = (e) => {
690
+ }), Ie = (e) => {
683
691
  try {
684
692
  const r = new URL(e), t = r.hostname === "localhost" || r.hostname === "127.0.0.1" || r.hostname === "[::1]", n = r.protocol === "https:";
685
693
  return { isSecure: n || t, isLocalhost: t, isHttps: n };
686
694
  } catch (r) {
687
695
  return { isSecure: !1, isLocalhost: !1, isHttps: !1 };
688
696
  }
689
- }, Fe = ({
697
+ }, Le = ({
690
698
  userId: e,
691
699
  jwt: r,
692
700
  baseUrl: t,
693
701
  children: n
694
702
  }) => {
695
- const { isSecure: o } = Oe(t);
703
+ const { isSecure: o } = Ie(t);
696
704
  o || console.warn(
697
705
  `[dismissible] Insecure baseUrl "${t}". Use https:// in production (or localhost for development). JWT tokens may be exposed over insecure connections.`
698
706
  );
699
- const s = Y(
707
+ const s = Z(
700
708
  () => ({
701
709
  userId: e,
702
710
  jwt: r,
703
711
  baseUrl: t,
704
712
  getAuthHeaders: () => $(void 0, null, function* () {
705
- return yield qe(r);
713
+ return yield Oe(r);
706
714
  })
707
715
  }),
708
716
  [e, r, t]
709
717
  );
710
- return /* @__PURE__ */ U(fe.Provider, { value: s, children: n });
718
+ return /* @__PURE__ */ T(de.Provider, { value: s, children: n });
711
719
  };
712
720
  export {
713
- ke as Dismissible,
714
- fe as DismissibleContext,
715
- Fe as DismissibleProvider,
716
- qe as getAuthHeaders,
721
+ Fe as Dismissible,
722
+ de as DismissibleContext,
723
+ Le as DismissibleProvider,
724
+ Oe as getAuthHeaders,
717
725
  He as resolveJwt,
718
726
  $e as useDismissibleContext,
719
- je as useDismissibleItem
727
+ De as useDismissibleItem
720
728
  };
@@ -1 +1 @@
1
- (function(c,d){typeof exports=="object"&&typeof module!="undefined"?d(exports,require("react/jsx-runtime"),require("react")):typeof define=="function"&&define.amd?define(["exports","react/jsx-runtime","react"],d):(c=typeof globalThis!="undefined"?globalThis:c||self,d(c.DismissibleClient={},c.React.jsxRuntime,c.React))})(this,function(c,d,o){"use strict";var Ae=Object.defineProperty,$e=Object.defineProperties;var Te=Object.getOwnPropertyDescriptors;var Q=Object.getOwnPropertySymbols;var ye=Object.prototype.hasOwnProperty,be=Object.prototype.propertyIsEnumerable;var me=(c,d,o)=>d in c?Ae(c,d,{enumerable:!0,configurable:!0,writable:!0,value:o}):c[d]=o,g=(c,d)=>{for(var o in d||(d={}))ye.call(d,o)&&me(c,o,d[o]);if(Q)for(var o of Q(d))be.call(d,o)&&me(c,o,d[o]);return c},S=(c,d)=>$e(c,Te(d));var re=(c,d)=>{var o={};for(var R in c)ye.call(c,R)&&d.indexOf(R)<0&&(o[R]=c[R]);if(c!=null&&Q)for(var R of Q(c))d.indexOf(R)<0&&be.call(c,R)&&(o[R]=c[R]);return o};var U=(c,d,o)=>new Promise((R,M)=>{var V=j=>{try{q(o.next(j))}catch(F){M(F)}},X=j=>{try{q(o.throw(j))}catch(F){M(F)}},q=j=>j.done?R(j.value):Promise.resolve(j.value).then(V,X);q((o=o.apply(c,d)).next())});const R=/\{[^{}]+\}/g,M=()=>{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 X(e){let H=g({},e),{baseUrl:r="",Request:t=globalThis.Request,fetch:n=globalThis.fetch,querySerializer:i,bodySerializer:s,headers:a,requestInitExt:h=void 0}=H,b=re(H,["baseUrl","Request","fetch","querySerializer","bodySerializer","headers","requestInitExt"]);h=M()?h:void 0,r=ie(r);const m=[];function C(f,l){return U(this,null,function*(){var he;const de=l||{},{baseUrl:x,fetch:A=n,Request:L=t,headers:$,params:D={},parseAs:O="json",querySerializer:T,bodySerializer:J=s!=null?s:pe,body:W,middleware:_=[]}=de,u=re(de,["baseUrl","fetch","Request","headers","params","parseAs","querySerializer","bodySerializer","body","middleware"]);let p=r;x&&(p=(he=ie(x))!=null?he:r);let y=typeof i=="function"?i:se(i);T&&(y=typeof T=="function"?T:se(g(g({},typeof i=="object"?i:{}),T)));const k=W===void 0?void 0:J(W,ne(a,$,D.header)),ee=ne(k===void 0||k instanceof FormData?{}:{"Content-Type":"application/json"},a,$,D.header),P=[...m,..._],je=S(g(g({redirect:"follow"},b),u),{body:k,headers:ee});let B,G,I=new L(ge(f,{baseUrl:p,params:D,querySerializer:y}),je),w;for(const v in u)v in I||(I[v]=u[v]);if(P.length){B=V(),G=Object.freeze({baseUrl:p,fetch:A,parseAs:O,querySerializer:y,bodySerializer:J});for(const v of P)if(v&&typeof v=="object"&&typeof v.onRequest=="function"){const E=yield v.onRequest({request:I,schemaPath:f,params:D,options:G,id:B});if(E)if(E instanceof L)I=E;else if(E instanceof Response){w=E;break}else throw new Error("onRequest: must return new Request() or Response() when modifying the request")}}if(!w){try{w=yield A(I,h)}catch(v){let E=v;if(P.length)for(let z=P.length-1;z>=0;z--){const K=P[z];if(K&&typeof K=="object"&&typeof K.onError=="function"){const N=yield K.onError({request:I,error:E,schemaPath:f,params:D,options:G,id:B});if(N){if(N instanceof Response){E=void 0,w=N;break}if(N instanceof Error){E=N;continue}throw new Error("onError: must return new Response() or instance of Error")}}}if(E)throw E}if(P.length)for(let v=P.length-1;v>=0;v--){const E=P[v];if(E&&typeof E=="object"&&typeof E.onResponse=="function"){const z=yield E.onResponse({request:I,response:w,schemaPath:f,params:D,options:G,id:B});if(z){if(!(z instanceof Response))throw new Error("onResponse: must return new Response() when modifying the response");w=z}}}}if(w.status===204||I.method==="HEAD"||w.headers.get("Content-Length")==="0")return w.ok?{data:void 0,response:w}:{error:void 0,response:w};if(w.ok)return O==="stream"?{data:w.body,response:w}:{data:yield w[O](),response:w};let te=yield w.text();try{te=JSON.parse(te)}catch(v){}return{error:te,response:w}})}return{request(f,l,x){return C(l,S(g({},x),{method:f.toUpperCase()}))},GET(f,l){return C(f,S(g({},l),{method:"GET"}))},PUT(f,l){return C(f,S(g({},l),{method:"PUT"}))},POST(f,l){return C(f,S(g({},l),{method:"POST"}))},DELETE(f,l){return C(f,S(g({},l),{method:"DELETE"}))},OPTIONS(f,l){return C(f,S(g({},l),{method:"OPTIONS"}))},HEAD(f,l){return C(f,S(g({},l),{method:"HEAD"}))},PATCH(f,l){return C(f,S(g({},l),{method:"PATCH"}))},TRACE(f,l){return C(f,S(g({},l),{method:"TRACE"}))},use(...f){for(const l of f)if(l){if(typeof l!="object"||!("onRequest"in l||"onResponse"in l||"onError"in l))throw new Error("Middleware must be an object with one of `onRequest()`, `onResponse() or `onError()`");m.push(l)}},eject(...f){for(const l of f){const x=m.indexOf(l);x!==-1&&m.splice(x,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 j(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 h in r)n.push(h,t.allowReserved===!0?r[h]:encodeURIComponent(r[h]));const a=n.join(",");switch(t.style){case"form":return`${e}=${a}`;case"label":return`.${a}`;case"matrix":return`;${e}=${a}`;default:return a}}for(const a in r){const h=t.style==="deepObject"?`${e}[${a}]`:a;n.push(q(h,r[a],t))}const s=n.join(i);return t.style==="label"||t.style==="matrix"?`${i}${s}`:s}function F(e,r,t){if(!Array.isArray(r))return"";if(t.explode===!1){const s={form:",",spaceDelimited:"%20",pipeDelimited:"|"}[t.style]||",",a=(t.allowReserved===!0?r:r.map(h=>encodeURIComponent(h))).join(s);switch(t.style){case"simple":return a;case"label":return`.${a}`;case"matrix":return`;${e}=${a}`;default:return`${e}=${a}`}}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(q(e,s,t));return t.style==="label"||t.style==="matrix"?`${n}${i.join(n)}`:i.join(n)}function se(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(F(i,s,S(g({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(j(i,s,S(g({style:"deepObject",explode:!0},e==null?void 0:e.object),{allowReserved:(e==null?void 0:e.allowReserved)||!1})));continue}n.push(q(i,s,e))}}return n.join("&")}}function we(e,r){var n;let t=e;for(const i of(n=e.match(R))!=null?n:[]){let s=i.substring(1,i.length-1),a=!1,h="simple";if(s.endsWith("*")&&(a=!0,s=s.substring(0,s.length-1)),s.startsWith(".")?(h="label",s=s.substring(1)):s.startsWith(";")&&(h="matrix",s=s.substring(1)),!r||r[s]===void 0||r[s]===null)continue;const b=r[s];if(Array.isArray(b)){t=t.replace(i,F(s,b,{style:h,explode:a}));continue}if(typeof b=="object"){t=t.replace(i,j(s,b,{style:h,explode:a}));continue}if(h==="matrix"){t=t.replace(i,`;${q(s,b)}`);continue}t=t.replace(i,h==="label"?`.${encodeURIComponent(b)}`:encodeURIComponent(b))}return t}function pe(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 ge(e,r){var i,s;let t=`${r.baseUrl}${e}`;(i=r.params)!=null&&i.path&&(t=we(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 ne(...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 a of s)r.append(i,a);else s!==void 0&&r.set(i,s)}return r}function ie(e){return e.endsWith("/")?e.substring(0,e.length-1):e}const oe=(e,r,t)=>{try{const n=`${r}_${e}`,i=localStorage.getItem(n);if(!i)return null;const{data:s,timestamp:a}=JSON.parse(i);return t&&Date.now()-a>t?(localStorage.removeItem(n),null):s}catch(n){return null}},Y=(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)}},ae=(e,r)=>{try{const t=`${r}_${e}`;localStorage.removeItem(t)}catch(t){console.warn("Failed to remove cached dismissible item:",t)}},Z=o.createContext(null),ce=()=>{const e=o.useContext(Z);if(!e)throw new Error("useDismissibleContext must be used within a DismissibleProvider");return e},Ee="dismissible",le=(e,r={})=>{var _;const{initialData:t,enableCache:n=!0,cachePrefix:i=Ee,cacheExpiration:s}=r,a=ce(),{userId:h}=a,b=o.useMemo(()=>X({baseUrl:a.baseUrl,headers:{}}),[a.baseUrl]),m=o.useMemo(()=>`${h}-${e}`,[h,e]),C=o.useRef({enableCache:n,cachePrefix:i,cacheExpiration:s}),H=o.useRef(e),f=o.useRef(m),l=o.useRef(null),[x,A]=o.useState(!1),[L,$]=o.useState(null),[D,O]=o.useState(()=>{if(t)return t;if(n){const u=oe(m,i,s);if(u)return u}}),T=o.useCallback(()=>U(this,null,function*(){var p;if(n){const y=oe(m,i,s);if(y!=null&&y.dismissedAt){O(y),A(!1);return}}(p=l.current)==null||p.abort();const u=new AbortController;l.current=u,A(!0),$(null);try{const y=yield a.getAuthHeaders(),{data:k,error:ee}=yield b.GET("/v1/user/{userId}/dismissible-item/{itemId}",{params:{path:{userId:h,itemId:e}},headers:y,signal:u.signal});if(ee||!k)throw new Error("Failed to fetch dismissible item");O(k.data),n&&Y(m,k.data,i)}catch(y){if(y instanceof Error&&y.name==="AbortError")return;$(y instanceof Error?y:new Error("Unknown error occurred"))}finally{A(!1)}}),[e,h,m,n,i,s,b,a]);o.useEffect(()=>{const u=H.current!==e,p=f.current!==m;u||p?(H.current=e,f.current=m,T()):t||T()},[e,m,t,T]),o.useEffect(()=>()=>{var u;(u=l.current)==null||u.abort()},[]),o.useEffect(()=>{const u=C.current;(u.enableCache!==n||u.cachePrefix!==i||u.cacheExpiration!==s)&&(u.cachePrefix!==i&&ae(m,u.cachePrefix),!n&&u.enableCache&&ae(m,u.cachePrefix),C.current={enableCache:n,cachePrefix:i,cacheExpiration:s},T())},[n,i,s,m,T]);const J=o.useCallback(()=>U(this,null,function*(){$(null);try{const u=yield a.getAuthHeaders(),{data:p,error:y}=yield b.DELETE("/v1/user/{userId}/dismissible-item/{itemId}",{params:{path:{userId:h,itemId:e}},headers:u});if(y||!p)throw new Error("Failed to dismiss item");O(p.data),n&&Y(m,p.data,i)}catch(u){throw $(u instanceof Error?u:new Error("Failed to dismiss item")),u}}),[e,h,m,n,i,b,a]),W=o.useCallback(()=>U(this,null,function*(){$(null);try{const u=yield a.getAuthHeaders(),{data:p,error:y}=yield b.POST("/v1/user/{userId}/dismissible-item/{itemId}",{params:{path:{userId:h,itemId:e}},headers:u});if(y||!p)throw new Error("Failed to restore item");O(p.data),n&&Y(m,p.data,i)}catch(u){throw $(u instanceof Error?u:new Error("Failed to restore item")),u}}),[e,h,m,n,i,b,a]);return{dismissedOn:(_=D==null?void 0:D.dismissedAt)!=null?_:null,dismiss:J,restore:W,isLoading:x,error:L,item:D}},ve=()=>d.jsx("div",{className:"dismissible-loading","aria-live":"polite",children:"Loading..."}),Ce=()=>d.jsx("div",{className:"dismissible-error",role:"alert",children:"Unable to load content. Please try again later."}),Re=({onDismiss:e,ariaLabel:r})=>d.jsx("button",{className:"dismissible-button",onClick:e,"aria-label":r,type:"button",children:"×"}),Se=({itemId:e,children:r,onDismiss:t,LoadingComponent:n=ve,ErrorComponent:i=Ce,DismissButtonComponent:s=Re,enableCache:a,cachePrefix:h,cacheExpiration:b,ignoreErrors:m=!1})=>{const{dismissedOn:C,isLoading:H,error:f,dismiss:l}=le(e,{enableCache:a,cachePrefix:h,cacheExpiration:b}),[x,A]=o.useState(!1);o.useEffect(()=>{A(!1)},[e]);const L=()=>U(this,null,function*(){A(!0);try{yield l(),t==null||t()}catch($){A(!1)}});return H&&n?d.jsx(n,{itemId:e}):H&&!n?null:f&&i&&!m?d.jsx(i,{itemId:e,error:f}):C||x?null:d.jsxs("div",{className:"dismissible-container",children:[d.jsx("div",{className:"dismissible-content",children:r}),s?d.jsx(s,{onDismiss:L,ariaLabel:`Dismiss ${e}`}):null]})},ue=e=>U(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}),fe=e=>U(this,null,function*(){const r=yield ue(e);return r?{Authorization:`Bearer ${r}`}:{}}),xe=e=>{try{const r=new URL(e),t=r.hostname==="localhost"||r.hostname==="127.0.0.1"||r.hostname==="[::1]",n=r.protocol==="https:";return{isSecure:n||t,isLocalhost:t,isHttps:n}}catch(r){return{isSecure:!1,isLocalhost:!1,isHttps:!1}}},De=({userId:e,jwt:r,baseUrl:t,children:n})=>{const{isSecure:i}=xe(t);i||console.warn(`[dismissible] Insecure baseUrl "${t}". Use https:// in production (or localhost for development). JWT tokens may be exposed over insecure connections.`);const s=o.useMemo(()=>({userId:e,jwt:r,baseUrl:t,getAuthHeaders:()=>U(this,null,function*(){return yield fe(r)})}),[e,r,t]);return d.jsx(Z.Provider,{value:s,children:n})};c.Dismissible=Se,c.DismissibleContext=Z,c.DismissibleProvider=De,c.getAuthHeaders=fe,c.resolveJwt=ue,c.useDismissibleContext=ce,c.useDismissibleItem=le,Object.defineProperty(c,Symbol.toStringTag,{value:"Module"})});
1
+ (function(a,f){typeof exports=="object"&&typeof module!="undefined"?f(exports,require("react/jsx-runtime"),require("react")):typeof define=="function"&&define.amd?define(["exports","react/jsx-runtime","react"],f):(a=typeof globalThis!="undefined"?globalThis:a||self,f(a.DismissibleClient={},a.React.jsxRuntime,a.React))})(this,function(a,f,o){"use strict";var $e=Object.defineProperty,Te=Object.defineProperties;var Ue=Object.getOwnPropertyDescriptors;var Q=Object.getOwnPropertySymbols;var be=Object.prototype.hasOwnProperty,we=Object.prototype.propertyIsEnumerable;var ye=(a,f,o)=>f in a?$e(a,f,{enumerable:!0,configurable:!0,writable:!0,value:o}):a[f]=o,g=(a,f)=>{for(var o in f||(f={}))be.call(f,o)&&ye(a,o,f[o]);if(Q)for(var o of Q(f))we.call(f,o)&&ye(a,o,f[o]);return a},x=(a,f)=>Te(a,Ue(f));var se=(a,f)=>{var o={};for(var R in a)be.call(a,R)&&f.indexOf(R)<0&&(o[R]=a[R]);if(a!=null&&Q)for(var R of Q(a))f.indexOf(R)<0&&we.call(a,R)&&(o[R]=a[R]);return o};var U=(a,f,o)=>new Promise((R,J)=>{var V=D=>{try{q(o.next(D))}catch(z){J(z)}},X=D=>{try{q(o.throw(D))}catch(z){J(z)}},q=D=>D.done?R(D.value):Promise.resolve(D.value).then(V,X);q((o=o.apply(a,f)).next())});const R=/\{[^{}]+\}/g,J=()=>{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 X(e){let I=g({},e),{baseUrl:r="",Request:t=globalThis.Request,fetch:n=globalThis.fetch,querySerializer:i,bodySerializer:s,headers:h,requestInitExt:d=void 0}=I,y=se(I,["baseUrl","Request","fetch","querySerializer","bodySerializer","headers","requestInitExt"]);d=J()?d:void 0,r=oe(r);const S=[];function m(u,c){return U(this,null,function*(){var me;const he=c||{},{baseUrl:j,fetch:F=n,Request:$=t,headers:L,params:C={},parseAs:H="json",querySerializer:T,bodySerializer:O=s!=null?s:ge,body:W,middleware:ee=[]}=he,N=se(he,["baseUrl","fetch","Request","headers","params","parseAs","querySerializer","bodySerializer","body","middleware"]);let l=r;j&&(l=(me=oe(j))!=null?me:r);let p=typeof i=="function"?i:ne(i);T&&(p=typeof T=="function"?T:ne(g(g({},typeof i=="object"?i:{}),T)));const b=W===void 0?void 0:O(W,ie(h,L,C.header)),_=ie(b===void 0||b instanceof FormData?{}:{"Content-Type":"application/json"},h,L,C.header),A=[...S,...ee],te=x(g(g({redirect:"follow"},y),N),{body:b,headers:_});let B,G,P=new $(Ee(u,{baseUrl:l,params:C,querySerializer:p}),te),w;for(const v in N)v in P||(P[v]=N[v]);if(A.length){B=V(),G=Object.freeze({baseUrl:l,fetch:F,parseAs:H,querySerializer:p,bodySerializer:O});for(const v of A)if(v&&typeof v=="object"&&typeof v.onRequest=="function"){const E=yield v.onRequest({request:P,schemaPath:u,params:C,options:G,id:B});if(E)if(E instanceof $)P=E;else if(E instanceof Response){w=E;break}else throw new Error("onRequest: must return new Request() or Response() when modifying the request")}}if(!w){try{w=yield F(P,d)}catch(v){let E=v;if(A.length)for(let k=A.length-1;k>=0;k--){const K=A[k];if(K&&typeof K=="object"&&typeof K.onError=="function"){const M=yield K.onError({request:P,error:E,schemaPath:u,params:C,options:G,id:B});if(M){if(M instanceof Response){E=void 0,w=M;break}if(M instanceof Error){E=M;continue}throw new Error("onError: must return new Response() or instance of Error")}}}if(E)throw E}if(A.length)for(let v=A.length-1;v>=0;v--){const E=A[v];if(E&&typeof E=="object"&&typeof E.onResponse=="function"){const k=yield E.onResponse({request:P,response:w,schemaPath:u,params:C,options:G,id:B});if(k){if(!(k instanceof Response))throw new Error("onResponse: must return new Response() when modifying the response");w=k}}}}if(w.status===204||P.method==="HEAD"||w.headers.get("Content-Length")==="0")return w.ok?{data:void 0,response:w}:{error:void 0,response:w};if(w.ok)return H==="stream"?{data:w.body,response:w}:{data:yield w[H](),response:w};let re=yield w.text();try{re=JSON.parse(re)}catch(v){}return{error:re,response:w}})}return{request(u,c,j){return m(c,x(g({},j),{method:u.toUpperCase()}))},GET(u,c){return m(u,x(g({},c),{method:"GET"}))},PUT(u,c){return m(u,x(g({},c),{method:"PUT"}))},POST(u,c){return m(u,x(g({},c),{method:"POST"}))},DELETE(u,c){return m(u,x(g({},c),{method:"DELETE"}))},OPTIONS(u,c){return m(u,x(g({},c),{method:"OPTIONS"}))},HEAD(u,c){return m(u,x(g({},c),{method:"HEAD"}))},PATCH(u,c){return m(u,x(g({},c),{method:"PATCH"}))},TRACE(u,c){return m(u,x(g({},c),{method:"TRACE"}))},use(...u){for(const c of u)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()`");S.push(c)}},eject(...u){for(const c of u){const j=S.indexOf(c);j!==-1&&S.splice(j,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 D(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 h=n.join(",");switch(t.style){case"form":return`${e}=${h}`;case"label":return`.${h}`;case"matrix":return`;${e}=${h}`;default:return h}}for(const h in r){const d=t.style==="deepObject"?`${e}[${h}]`:h;n.push(q(d,r[h],t))}const s=n.join(i);return t.style==="label"||t.style==="matrix"?`${i}${s}`:s}function z(e,r,t){if(!Array.isArray(r))return"";if(t.explode===!1){const s={form:",",spaceDelimited:"%20",pipeDelimited:"|"}[t.style]||",",h=(t.allowReserved===!0?r:r.map(d=>encodeURIComponent(d))).join(s);switch(t.style){case"simple":return h;case"label":return`.${h}`;case"matrix":return`;${e}=${h}`;default:return`${e}=${h}`}}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(q(e,s,t));return t.style==="label"||t.style==="matrix"?`${n}${i.join(n)}`:i.join(n)}function ne(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(z(i,s,x(g({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(D(i,s,x(g({style:"deepObject",explode:!0},e==null?void 0:e.object),{allowReserved:(e==null?void 0:e.allowReserved)||!1})));continue}n.push(q(i,s,e))}}return n.join("&")}}function pe(e,r){var n;let t=e;for(const i of(n=e.match(R))!=null?n:[]){let s=i.substring(1,i.length-1),h=!1,d="simple";if(s.endsWith("*")&&(h=!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 y=r[s];if(Array.isArray(y)){t=t.replace(i,z(s,y,{style:d,explode:h}));continue}if(typeof y=="object"){t=t.replace(i,D(s,y,{style:d,explode:h}));continue}if(d==="matrix"){t=t.replace(i,`;${q(s,y)}`);continue}t=t.replace(i,d==="label"?`.${encodeURIComponent(y)}`:encodeURIComponent(y))}return t}function ge(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 Ee(e,r){var i,s;let t=`${r.baseUrl}${e}`;(i=r.params)!=null&&i.path&&(t=pe(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 ie(...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 h of s)r.append(i,h);else s!==void 0&&r.set(i,s)}return r}function oe(e){return e.endsWith("/")?e.substring(0,e.length-1):e}const ae=(e,r,t)=>{try{const n=`${r}_${e}`,i=localStorage.getItem(n);if(!i)return null;const{data:s,timestamp:h}=JSON.parse(i);return t&&Date.now()-h>t?(localStorage.removeItem(n),null):s}catch(n){return null}},Y=(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)}},ce=(e,r)=>{try{const t=`${r}_${e}`;localStorage.removeItem(t)}catch(t){console.warn("Failed to remove cached dismissible item:",t)}},Z=o.createContext(null),le=()=>{const e=o.useContext(Z);if(!e)throw new Error("useDismissibleContext must be used within a DismissibleProvider");return e},ve=e=>{if(e)return Object.entries(e).map(([r,t])=>`${r}:${t}`)},Ce="dismissible",ue=(e,r={})=>{var N;const{initialData:t,enableCache:n=!0,cachePrefix:i=Ce,cacheExpiration:s,metadata:h}=r,d=le(),{userId:y}=d,S=o.useMemo(()=>X({baseUrl:d.baseUrl,headers:{}}),[d.baseUrl]),m=o.useMemo(()=>`${y}-${e}`,[y,e]),I=o.useRef({enableCache:n,cachePrefix:i,cacheExpiration:s}),u=o.useRef(e),c=o.useRef(m),j=o.useRef(null),[F,$]=o.useState(!1),[L,C]=o.useState(null),[H,T]=o.useState(()=>{if(t)return t;if(n){const l=ae(m,i,s);if(l)return l}}),O=o.useCallback(()=>U(this,null,function*(){var p;if(n){const b=ae(m,i,s);if(b!=null&&b.dismissedAt){T(b),$(!1);return}}(p=j.current)==null||p.abort();const l=new AbortController;j.current=l,$(!0),C(null);try{const b=yield d.getAuthHeaders(),_=ve(h),{data:A,error:te}=yield S.GET("/v1/users/{userId}/items/{itemId}",{params:{path:{userId:y,itemId:e},query:_?{metadata:_}:void 0},headers:b,signal:l.signal});if(te||!A)throw new Error("Failed to fetch dismissible item");T(A.data),n&&Y(m,A.data,i)}catch(b){if(b instanceof Error&&b.name==="AbortError")return;C(b instanceof Error?b:new Error("Unknown error occurred"))}finally{$(!1)}}),[e,y,m,n,i,s,h,S,d]);o.useEffect(()=>{const l=u.current!==e,p=c.current!==m;l||p?(u.current=e,c.current=m,O()):t||O()},[e,m,t,O]),o.useEffect(()=>()=>{var l;(l=j.current)==null||l.abort()},[]),o.useEffect(()=>{const l=I.current;(l.enableCache!==n||l.cachePrefix!==i||l.cacheExpiration!==s)&&(l.cachePrefix!==i&&ce(m,l.cachePrefix),!n&&l.enableCache&&ce(m,l.cachePrefix),I.current={enableCache:n,cachePrefix:i,cacheExpiration:s},O())},[n,i,s,m,O]);const W=o.useCallback(()=>U(this,null,function*(){C(null);try{const l=yield d.getAuthHeaders(),{data:p,error:b}=yield S.DELETE("/v1/users/{userId}/items/{itemId}",{params:{path:{userId:y,itemId:e}},headers:l});if(b||!p)throw new Error("Failed to dismiss item");T(p.data),n&&Y(m,p.data,i)}catch(l){throw C(l instanceof Error?l:new Error("Failed to dismiss item")),l}}),[e,y,m,n,i,S,d]),ee=o.useCallback(()=>U(this,null,function*(){C(null);try{const l=yield d.getAuthHeaders(),{data:p,error:b}=yield S.POST("/v1/users/{userId}/items/{itemId}",{params:{path:{userId:y,itemId:e}},headers:l});if(b||!p)throw new Error("Failed to restore item");T(p.data),n&&Y(m,p.data,i)}catch(l){throw C(l instanceof Error?l:new Error("Failed to restore item")),l}}),[e,y,m,n,i,S,d]);return{dismissedOn:(N=H==null?void 0:H.dismissedAt)!=null?N:null,dismiss:W,restore:ee,isLoading:F,error:L,item:H}},Re=()=>f.jsx("div",{className:"dismissible-loading","aria-live":"polite",children:"Loading..."}),Se=()=>f.jsx("div",{className:"dismissible-error",role:"alert",children:"Unable to load content. Please try again later."}),je=({onDismiss:e,ariaLabel:r})=>f.jsx("button",{className:"dismissible-button",onClick:e,"aria-label":r,type:"button",children:"×"}),xe=({itemId:e,children:r,onDismiss:t,LoadingComponent:n=Re,ErrorComponent:i=Se,DismissButtonComponent:s=je,enableCache:h,cachePrefix:d,cacheExpiration:y,ignoreErrors:S=!1,metadata:m})=>{const{dismissedOn:I,isLoading:u,error:c,dismiss:j}=ue(e,{enableCache:h,cachePrefix:d,cacheExpiration:y,metadata:m}),[F,$]=o.useState(!1);o.useEffect(()=>{$(!1)},[e]);const L=()=>U(this,null,function*(){$(!0);try{yield j(),t==null||t()}catch(C){$(!1)}});return u&&n?f.jsx(n,{itemId:e}):u&&!n?null:c&&i&&!S?f.jsx(i,{itemId:e,error:c}):I||F?null:f.jsxs("div",{className:"dismissible-container",children:[f.jsx("div",{className:"dismissible-content",children:r}),s?f.jsx(s,{onDismiss:L,ariaLabel:`Dismiss ${e}`}):null]})},fe=e=>U(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}),de=e=>U(this,null,function*(){const r=yield fe(e);return r?{Authorization:`Bearer ${r}`}:{}}),Ae=e=>{try{const r=new URL(e),t=r.hostname==="localhost"||r.hostname==="127.0.0.1"||r.hostname==="[::1]",n=r.protocol==="https:";return{isSecure:n||t,isLocalhost:t,isHttps:n}}catch(r){return{isSecure:!1,isLocalhost:!1,isHttps:!1}}},De=({userId:e,jwt:r,baseUrl:t,children:n})=>{const{isSecure:i}=Ae(t);i||console.warn(`[dismissible] Insecure baseUrl "${t}". Use https:// in production (or localhost for development). JWT tokens may be exposed over insecure connections.`);const s=o.useMemo(()=>({userId:e,jwt:r,baseUrl:t,getAuthHeaders:()=>U(this,null,function*(){return yield de(r)})}),[e,r,t]);return f.jsx(Z.Provider,{value:s,children:n})};a.Dismissible=xe,a.DismissibleContext=Z,a.DismissibleProvider=De,a.getAuthHeaders=de,a.resolveJwt=fe,a.useDismissibleContext=le,a.useDismissibleItem=ue,Object.defineProperty(a,Symbol.toStringTag,{value:"Module"})});
@@ -1,6 +1,10 @@
1
1
  import { components } from '../generated/contract';
2
2
  type DismissibleItem = components["schemas"]["DismissibleItemResponseDto"];
3
3
  export type IDismissibleItem = DismissibleItem;
4
+ /** Metadata object with string or number values */
5
+ export type IMetadata = {
6
+ [key: string]: string | number;
7
+ };
4
8
  export interface UseDismissibleItemOptions {
5
9
  /** Initial data for the dismissible item */
6
10
  initialData?: IDismissibleItem;
@@ -10,6 +14,8 @@ export interface UseDismissibleItemOptions {
10
14
  cachePrefix?: string;
11
15
  /** Cache expiration time in milliseconds (default: never expires) */
12
16
  cacheExpiration?: number;
17
+ /** Optional metadata object that will be converted to key:value string pairs */
18
+ metadata?: IMetadata;
13
19
  }
14
20
  /**
15
21
  * Hook for managing dismissible items
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dismissible/react-client",
3
- "version": "0.3.2-canary.3.c1b8c41",
3
+ "version": "0.3.2-canary.4.578bcba",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist",