@dismissible/react-client 0.3.0 → 0.3.2-canary.2.38782c4

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
@@ -1,6 +1,10 @@
1
1
  # @dismissible/react-client
2
2
 
3
- A React component library for creating dismissible UI elements with persistent state management.
3
+ A React component library for creating dismissible UI elements with persistent state management.
4
+
5
+ Use this in combination with [dismissible.io](https://dismissible.io). Get your free account now!
6
+
7
+ 🌐 **[dismissible.io](https://dismissible.io)** | 💰 **[View Pricing](https://dismissible.io/pricing)** | 📖 **[Documentation](https://docs.dismissible.io)**
4
8
 
5
9
  [![npm version](https://badge.fury.io/js/@dismissible%2Freact-client.svg)](https://badge.fury.io/js/@dismissible%2Freact-client)
6
10
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
@@ -9,7 +13,7 @@ A React component library for creating dismissible UI elements with persistent s
9
13
 
10
14
  - 🎯 **Easy to use** - Simple component API for dismissible content
11
15
  - 💾 **Persistent state** - Dismissal state is saved and restored across sessions
12
- - 🔐 **JWT Authentication** - Built-in support for JWT-based user authentication
16
+ - 🔐 **JWT Authentication** - Built-in support for JWT-based user authentication (Enterprise only)
13
17
  - 🎨 **Customizable** - Custom loading, error, and dismiss button components
14
18
  - ♿ **Accessible** - Built with accessibility best practices
15
19
  - 🪝 **Hook-based** - Includes `useDismissibleItem` hook for custom implementations
@@ -54,11 +58,13 @@ function App() {
54
58
 
55
59
  Context provider for JWT authentication and configuration. Wrap your app or components that need JWT authentication.
56
60
 
61
+ > **Note:** JWT authentication is only available for **Enterprise customers**. For standard usage, you can use the `<Dismissible>` component directly without a provider. [View pricing →](https://dismissible.io/pricing)
62
+
57
63
  #### Props
58
64
 
59
65
  | Prop | Type | Required | Description |
60
66
  |------|------|----------|-------------|
61
- | `jwt` | `string \| (() => string)` | ❌ | JWT token (static string or function) |
67
+ | `jwt` | `string \| (() => string) \| (() => Promise<string>)` | ❌ | JWT token for user-specific dismissals (**Enterprise only**) |
62
68
  | `baseUrl` | `string` | ❌ | Custom API base URL override |
63
69
  | `children` | `ReactNode` | ✅ | Components that will use the dismissible functionality |
64
70
 
@@ -85,6 +91,15 @@ function AppWithDynamicAuth() {
85
91
  );
86
92
  }
87
93
 
94
+ // With async JWT function
95
+ function AppWithAsyncAuth() {
96
+ return (
97
+ <DismissibleProvider jwt={async () => await fetchAccessToken()}>
98
+ <YourApp />
99
+ </DismissibleProvider>
100
+ );
101
+ }
102
+
88
103
  // Without JWT (anonymous/backwards compatible)
89
104
  function AppWithoutAuth() {
90
105
  return (
@@ -109,6 +124,7 @@ The main component for creating dismissible content.
109
124
  | `LoadingComponent` | `ComponentType<{id: string}>` | ❌ | Custom loading component |
110
125
  | `ErrorComponent` | `ComponentType<{id: string, error: Error}>` | ❌ | Custom error component |
111
126
  | `DismissButtonComponent` | `ComponentType<{id: string, onDismiss: () => Promise<void>, ariaLabel: string}>` | ❌ | Custom dismiss button |
127
+ | `ignoreErrors` | `boolean` | ❌ | Ignore errors and display component anyway (default: false) |
112
128
 
113
129
  #### Example
114
130
 
@@ -177,7 +193,9 @@ function CustomDismissible({ id, children }) {
177
193
 
178
194
  ## Usage Examples
179
195
 
180
- ### JWT Authentication Setup
196
+ ### JWT Authentication Setup (Enterprise Only)
197
+
198
+ > **Enterprise Feature:** JWT authentication allows user-specific dismissible state management. This feature requires an Enterprise subscription. [Learn more about Enterprise features →](https://dismissible.io/pricing)
181
199
 
182
200
  For enterprise accounts that require user-specific dismissible state, wrap your app with the `DismissibleProvider`:
183
201
 
@@ -216,6 +234,7 @@ function Dashboard() {
216
234
  import { DismissibleProvider } from '@dismissible/react-client';
217
235
  import { useAuth } from './auth'; // Your auth context
218
236
 
237
+ // Synchronous JWT function
219
238
  function App() {
220
239
  const { getAccessToken } = useAuth();
221
240
 
@@ -225,6 +244,17 @@ function App() {
225
244
  </DismissibleProvider>
226
245
  );
227
246
  }
247
+
248
+ // Asynchronous JWT function
249
+ function AppWithAsyncAuth() {
250
+ const { refreshAndGetToken } = useAuth();
251
+
252
+ return (
253
+ <DismissibleProvider jwt={async () => await refreshAndGetToken()}>
254
+ <YourApp />
255
+ </DismissibleProvider>
256
+ );
257
+ }
228
258
  ```
229
259
 
230
260
  ### Basic Dismissible Banner
@@ -341,36 +371,12 @@ function Dashboard() {
341
371
  }
342
372
  ```
343
373
 
344
- ### Conditional Dismissible Content
345
-
346
- ```tsx
347
- import { Dismissible } from '@dismissible/react-client';
348
-
349
- function ConditionalBanner({ user }) {
350
- // Only show to new users
351
- if (user.isReturning) {
352
- return null;
353
- }
354
-
355
- return (
356
- <Dismissible id={`onboarding-${user.id}`}>
357
- <div className="onboarding-tips">
358
- <h3>Getting Started</h3>
359
- <ul>
360
- <li>Complete your profile</li>
361
- <li>Connect with friends</li>
362
- <li>Explore our features</li>
363
- </ul>
364
- </div>
365
- </Dismissible>
366
- );
367
- }
368
- ```
369
-
370
374
  ### User-Specific vs Anonymous Dismissible Items
371
375
 
372
376
  The behavior changes based on whether JWT authentication is configured:
373
377
 
378
+ > **Enterprise vs Standard:** JWT authentication for user-specific dismissals is an Enterprise feature. Standard accounts use anonymous (account-level) dismissals. [Compare plans →](https://dismissible.io/pricing)
379
+
374
380
  ```tsx
375
381
  import { DismissibleProvider, Dismissible } from '@dismissible/react-client';
376
382
 
@@ -392,16 +398,82 @@ function AuthenticatedApp() {
392
398
  </DismissibleProvider>
393
399
  );
394
400
  }
401
+ ```
402
+
403
+ ### Error Handling with ignoreErrors
404
+
405
+ ```tsx
406
+ import { Dismissible } from '@dismissible/react-client';
395
407
 
396
- // Without JWT - dismissible state is account-level (anonymous)
397
- function AnonymousApp() {
408
+ // Show content even if API fails
409
+ function RobustBanner() {
398
410
  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>
411
+ <Dismissible
412
+ id="important-announcement"
413
+ ignoreErrors={true}
414
+ >
415
+ <div className="important-banner">
416
+ <h3>Critical System Update</h3>
417
+ <p>System maintenance scheduled for tonight. Please save your work.</p>
418
+ </div>
419
+ </Dismissible>
420
+ );
421
+ }
422
+ ```
423
+
424
+ ### Async JWT Authentication Examples
425
+
426
+ ```tsx
427
+ import { DismissibleProvider } from '@dismissible/react-client';
428
+
429
+ // With token refresh logic
430
+ function AppWithTokenRefresh() {
431
+ return (
432
+ <DismissibleProvider
433
+ jwt={async () => {
434
+ try {
435
+ const token = await fetch('/api/auth/refresh', {
436
+ method: 'POST',
437
+ credentials: 'include'
438
+ });
439
+ const { accessToken } = await token.json();
440
+ return accessToken;
441
+ } catch (error) {
442
+ console.error('Failed to refresh token:', error);
443
+ throw error;
444
+ }
445
+ }}
446
+ >
447
+ <YourApp />
448
+ </DismissibleProvider>
449
+ );
450
+ }
451
+
452
+ // With Firebase Auth
453
+ function AppWithFirebase() {
454
+ return (
455
+ <DismissibleProvider
456
+ jwt={async () => {
457
+ const user = firebase.auth().currentUser;
458
+ if (user) {
459
+ return await user.getIdToken();
460
+ }
461
+ throw new Error('User not authenticated');
462
+ }}
463
+ >
464
+ <YourApp />
465
+ </DismissibleProvider>
466
+ );
467
+ }
468
+
469
+ // With Auth0
470
+ function AppWithAuth0() {
471
+ const { getAccessTokenSilently } = useAuth0();
472
+
473
+ return (
474
+ <DismissibleProvider jwt={async () => await getAccessTokenSilently()}>
475
+ <YourApp />
476
+ </DismissibleProvider>
405
477
  );
406
478
  }
407
479
  ```
@@ -446,10 +518,10 @@ function SmartNotification({ id, message, type = 'info' }) {
446
518
  );
447
519
  }
448
520
 
449
- // Usage with authentication
521
+ // Usage with async authentication
450
522
  function App() {
451
523
  return (
452
- <DismissibleProvider jwt={() => getUserToken()}>
524
+ <DismissibleProvider jwt={async () => await getUserToken()}>
453
525
  <SmartNotification
454
526
  id="user-specific-notification"
455
527
  message="Welcome back!"
@@ -510,79 +582,6 @@ const AuthProvider: React.FC<DismissibleProviderProps> = ({ children, jwt }) =>
510
582
  };
511
583
  ```
512
584
 
513
- ## Development
514
-
515
- ### Prerequisites
516
-
517
- - Node.js 18+
518
- - npm or yarn
519
-
520
- ### Setup
521
-
522
- ```bash
523
- # Clone the repository
524
- git clone https://github.com/your-org/dismissible.git
525
- cd dismissible/react-client
526
-
527
- # Install dependencies
528
- npm install
529
-
530
- # Start development server
531
- npm run dev
532
- ```
533
-
534
- ### Available Scripts
535
-
536
- - `npm run dev` - Start development server with Vite
537
- - `npm run build` - Build the library for production
538
- - `npm run test` - Run tests with Vitest
539
- - `npm run test:watch` - Run tests in watch mode
540
- - `npm run lint` - Run ESLint
541
- - `npm run format` - Format code with Prettier
542
- - `npm run storybook` - Start Storybook development server
543
- - `npm run build-storybook` - Build Storybook for production
544
-
545
- ### Testing
546
-
547
- ```bash
548
- # Run all tests
549
- npm run test
550
-
551
- # Run tests in watch mode
552
- npm run test:watch
553
-
554
- # Run tests with coverage
555
- npm run test -- --coverage
556
- ```
557
-
558
- ### Storybook
559
-
560
- The library includes Storybook for component development and documentation:
561
-
562
- ```bash
563
- npm run storybook
564
- ```
565
-
566
- ## Contributing
567
-
568
- We welcome contributions! Please see our [Contributing Guide](../CONTRIBUTING.md) for details.
569
-
570
- ### Development Workflow
571
-
572
- 1. Fork the repository
573
- 2. Create a feature branch: `git checkout -b feature/my-new-feature`
574
- 3. Make your changes
575
- 4. Add tests for new functionality
576
- 5. Run tests: `npm run test`
577
- 6. Run linting: `npm run lint`
578
- 7. Commit your changes: `git commit -am 'Add new feature'`
579
- 8. Push to the branch: `git push origin feature/my-new-feature`
580
- 9. Submit a pull request
581
-
582
- ## License
583
-
584
- MIT © [Dismissible](https://github.com/joshystuart)
585
-
586
585
  ## Support
587
586
 
588
587
  - 📖 [Documentation](https://docs.dismissible.io)
@@ -5,6 +5,7 @@ import { DismissibleContextValue } from '../types/dismissible.types';
5
5
  export declare const DismissibleContext: import('react').Context<DismissibleContextValue | null>;
6
6
  /**
7
7
  * Hook to consume the DismissibleContext
8
- * @returns The context value or null if not within a provider
8
+ * @throws Error if used outside of a DismissibleProvider
9
+ * @returns The context value
9
10
  */
10
- export declare const useDismissibleContext: () => DismissibleContextValue | null;
11
+ export declare const useDismissibleContext: () => DismissibleContextValue;
@@ -6,12 +6,13 @@ import { DismissibleProviderProps } from '../types/dismissible.types';
6
6
  * @example
7
7
  * ```tsx
8
8
  * // With static JWT
9
- * <DismissibleProvider jwt="eyJhbGciOiJ..." baseUrl="https://api.dismissible.io">
9
+ * <DismissibleProvider userId="user-123" jwt="eyJhbGciOiJ..." baseUrl="https://api.dismissible.io">
10
10
  * <App />
11
11
  * </DismissibleProvider>
12
12
  *
13
13
  * // With synchronous JWT function
14
14
  * <DismissibleProvider
15
+ * userId="user-123"
15
16
  * jwt={() => getAccessToken()}
16
17
  * baseUrl="https://api.dismissible.io"
17
18
  * >
@@ -20,6 +21,7 @@ import { DismissibleProviderProps } from '../types/dismissible.types';
20
21
  *
21
22
  * // With asynchronous JWT function
22
23
  * <DismissibleProvider
24
+ * userId="user-123"
23
25
  * jwt={async () => await fetchAccessToken()}
24
26
  * baseUrl="https://api.dismissible.io"
25
27
  * >