@dismissible/react-client 1.0.0-canary.4.a9fb4a5 → 1.0.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 CHANGED
@@ -1,37 +1,26 @@
1
- <p align="center">
2
- <a href="https://dismissible.io" target="_blank"><img src="https://raw.githubusercontent.com/DismissibleIo/dismissible-api/main/docs/images/dismissible_logo.png" width="240" alt="Dismissible" /></a>
3
- </p>
4
-
5
- <p align="center">Never Show The Same Thing Twice!</p>
6
- <p align="center">
7
- <a href="https://www.npmjs.com/package/@dismissible/react-client" target="_blank"><img src="https://img.shields.io/npm/v/@dismissible/react-client.svg" alt="NPM Version" /></a>
8
- <a href="https://github.com/dismissibleio/dismissible-react-client/blob/main/LICENSE" target="_blank"><img src="https://img.shields.io/npm/l/@dismissible/react-client.svg" alt="Package License" /></a>
9
- <a href="https://www.npmjs.com/package/@dismissible/react-client" target="_blank"><img src="https://img.shields.io/npm/dm/@dismissible/react-client.svg" alt="NPM Downloads" /></a>
10
- <a href="https://github.com/dismissibleio/dismissible-react-client" target="_blank"><img alt="GitHub Actions Workflow Status" src="https://img.shields.io/github/actions/workflow/status/dismissibleio/dismissible-react-client/publish.yml" /></a>
11
- <a href="https://paypal.me/joshstuartx" target="_blank"><img src="https://img.shields.io/badge/Donate-PayPal-ff3f59.svg" /></a>
12
- </p>
13
-
14
- Dismissible manages the state of your UI elements across sessions, so your users see what matters, once! No more onboarding messages reappearing on every tab, no more notifications haunting users across devices. Dismissible syncs dismissal state everywhere, so every message is intentional, never repetitive.
15
-
16
1
  # @dismissible/react-client
17
2
 
18
- This is the 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.
19
4
 
20
- This component is used with the [Dismissible API Server](https://github.com/DismissibleIo/dismissible-api), which you can self-host with Docker or integrate into your NestJS application.
5
+ **Free and open source** - use with the [Dismissible API Server](https://github.com/DismissibleIo/dismissible-api) that you can self-host with Docker or integrate into your NestJS application.
21
6
 
22
- **[dismissible.io](https://dismissible.io)** | **[Documentation](https://dismissible.io/docs)** | **[API Server](https://github.com/DismissibleIo/dismissible-api)**
7
+ 🌐 **[dismissible.io](https://dismissible.io)** | 📖 **[Documentation](https://dismissible.io/docs)** | 🐙 **[API Server](https://github.com/DismissibleIo/dismissible-api)**
8
+
9
+ [![npm version](https://badge.fury.io/js/@dismissible%2Freact-client.svg)](https://badge.fury.io/js/@dismissible%2Freact-client)
10
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
23
11
 
24
12
  ## Features
25
13
 
26
- - **Easy to use** - Simple component API for dismissible content
27
- - **Persistent state** - Dismissal state is saved and restored across sessions when using the [Dismissible API Server](https://github.com/DismissibleIo/dismissible-api)
28
- - **Restore support** - Restore previously dismissed items programmatically
29
- - **JWT Authentication** - Built-in support for secure JWT-based authentication
30
- - **Customizable** - Custom loading, error, and dismiss button components
31
- - **Accessible** - Built with accessibility best practices
32
- - **Hook-based** - Includes `useDismissibleItem` hook for custom implementations
33
- - **Lightweight** - Minimal bundle size with tree-shaking support
34
- - **TypeScript** - Full TypeScript support with complete type definitions
14
+ - 🎯 **Easy to use** - Simple component API for dismissible content
15
+ - 💾 **Persistent state** - Dismissal state is saved and restored across sessions
16
+ - 🔄 **Restore support** - Restore previously dismissed items programmatically
17
+ - 🔐 **JWT Authentication** - Built-in support for secure JWT-based authentication
18
+ - 🎨 **Customizable** - Custom loading, error, and dismiss button components
19
+ - **Accessible** - Built with accessibility best practices
20
+ - 🪝 **Hook-based** - Includes `useDismissibleItem` hook for custom implementations
21
+ - 📦 **Lightweight** - Minimal bundle size with tree-shaking support
22
+ - 🔧 **TypeScript** - Full TypeScript support with complete type definitions
23
+ - 🐳 **Self-hosted** - Works with your own Dismissible API server
35
24
 
36
25
  ## Installation
37
26
 
@@ -51,7 +40,7 @@ npm install react react-dom
51
40
 
52
41
  ### 1. Set up the Dismissible API Server
53
42
 
54
- First, you need a [Dismissible API Server](https://github.com/DismissibleIo/dismissible-api). The easiest way is with Docker:
43
+ First, you need a Dismissible API server running. The easiest way is with Docker:
55
44
 
56
45
  ```yaml
57
46
  # docker-compose.yml
@@ -63,29 +52,38 @@ services:
63
52
  - '3001:3001'
64
53
  environment:
65
54
  DISMISSIBLE_PORT: 3001
66
- ```
55
+ DISMISSIBLE_POSTGRES_STORAGE_CONNECTION_STRING: postgresql://postgres:postgres@db:5432/dismissible
56
+ depends_on:
57
+ - db
67
58
 
68
- ```bash
69
- docker-compose up -d
59
+ db:
60
+ image: postgres:15
61
+ environment:
62
+ POSTGRES_USER: postgres
63
+ POSTGRES_PASSWORD: postgres
64
+ POSTGRES_DB: dismissible
65
+ volumes:
66
+ - postgres_data:/var/lib/postgresql/data
67
+
68
+ volumes:
69
+ postgres_data:
70
70
  ```
71
71
 
72
- OR
73
-
74
72
  ```bash
75
- docker run -p 3001:3001 -e DISMISSIBLE_PORT=3001 dismissibleio/dismissible-api:latest
73
+ docker-compose up -d
76
74
  ```
77
75
 
78
- See the [API Server documentation](https://github.com/DismissibleIo/dismissible-api) for more deployment options including NestJS integration, public Docker image and more.
76
+ See the [API Server documentation](https://github.com/DismissibleIo/dismissible-api) for more deployment options including NestJS integration.
79
77
 
80
78
  ### 2. Configure the Provider
81
79
 
82
- Wrap your app with `DismissibleProvider`. The `userId` prop is **required** to track all your dismissals per user:
80
+ Wrap your app with `DismissibleProvider`. The `userId` prop is **required** to track dismissals per user:
83
81
 
84
82
  ```tsx
85
83
  import { DismissibleProvider } from '@dismissible/react-client';
86
84
 
87
85
  function App() {
88
- const userId = getCurrentUserId();
86
+ const userId = getCurrentUserId(); // Get from your auth system
89
87
 
90
88
  return (
91
89
  <DismissibleProvider userId={userId} baseUrl="http://localhost:3001">
@@ -96,7 +94,6 @@ function App() {
96
94
  ```
97
95
 
98
96
  ### 3. Use Dismissible Components
99
- Now wrap any component you want to be dismissible with the `<Dismissible>` component, and the `itemId`, along with the `userId`, will become the unique key that is tracked across sessions and devices.
100
97
 
101
98
  ```tsx
102
99
  import { Dismissible } from '@dismissible/react-client';
@@ -245,11 +242,11 @@ For custom implementations and advanced use cases.
245
242
 
246
243
  | Property | Type | Description |
247
244
  |----------|------|-------------|
248
- | `dismissedAt` | `string \| undefined` | ISO date string when item was dismissed, or undefined |
245
+ | `dismissedOn` | `string \| null` | ISO date string when item was dismissed, or null |
249
246
  | `dismiss` | `() => Promise<void>` | Function to dismiss the item |
250
247
  | `restore` | `() => Promise<void>` | Function to restore a dismissed item |
251
248
  | `isLoading` | `boolean` | Loading state indicator |
252
- | `error` | `Error \| undefined` | Error state, if any |
249
+ | `error` | `Error \| null` | Error state, if any |
253
250
  | `item` | `IDismissibleItem \| undefined` | The full dismissible item object |
254
251
 
255
252
  #### Example
@@ -258,7 +255,7 @@ For custom implementations and advanced use cases.
258
255
  import { useDismissibleItem } from '@dismissible/react-client';
259
256
 
260
257
  function CustomDismissible({ itemId, children }) {
261
- const { dismissedAt, dismiss, restore, isLoading, error } = useDismissibleItem(itemId);
258
+ const { dismissedOn, dismiss, restore, isLoading, error } = useDismissibleItem(itemId);
262
259
 
263
260
  if (isLoading) {
264
261
  return <div>Loading...</div>;
@@ -268,7 +265,7 @@ function CustomDismissible({ itemId, children }) {
268
265
  return <div>Error: {error.message}</div>;
269
266
  }
270
267
 
271
- if (dismissedAt) {
268
+ if (dismissedOn) {
272
269
  return (
273
270
  <div>
274
271
  <p>This item was dismissed.</p>
@@ -341,6 +338,7 @@ function App() {
341
338
  function Dashboard() {
342
339
  return (
343
340
  <div>
341
+ {/* Dismissible state is tracked per user */}
344
342
  <Dismissible itemId="user-welcome-banner">
345
343
  <div className="alert alert-info">
346
344
  <h4>Welcome back!</h4>
@@ -429,19 +427,19 @@ function Dashboard() {
429
427
  <div>
430
428
  <Dismissible itemId="feature-announcement">
431
429
  <div className="alert alert-success">
432
- New feature: Dark mode is now available!
430
+ 🎉 New feature: Dark mode is now available!
433
431
  </div>
434
432
  </Dismissible>
435
433
 
436
434
  <Dismissible itemId="maintenance-notice">
437
435
  <div className="alert alert-warning">
438
- Scheduled maintenance: Sunday 2AM-4AM EST
436
+ ⚠️ Scheduled maintenance: Sunday 2AM-4AM EST
439
437
  </div>
440
438
  </Dismissible>
441
439
 
442
440
  <Dismissible itemId="survey-request">
443
441
  <div className="alert alert-info">
444
- Help us improve! Take our 2-minute survey.
442
+ 📝 Help us improve! Take our 2-minute survey.
445
443
  </div>
446
444
  </Dismissible>
447
445
  </div>
@@ -470,6 +468,74 @@ function RobustBanner() {
470
468
  }
471
469
  ```
472
470
 
471
+ ### Integration with Auth Providers
472
+
473
+ ```tsx
474
+ import { DismissibleProvider } from '@dismissible/react-client';
475
+
476
+ // With Firebase Auth
477
+ function AppWithFirebase() {
478
+ const user = firebase.auth().currentUser;
479
+
480
+ return (
481
+ <DismissibleProvider
482
+ userId={user.uid}
483
+ jwt={async () => {
484
+ if (user) {
485
+ return await user.getIdToken();
486
+ }
487
+ throw new Error('User not authenticated');
488
+ }}
489
+ baseUrl="https://api.yourapp.com"
490
+ >
491
+ <YourApp />
492
+ </DismissibleProvider>
493
+ );
494
+ }
495
+
496
+ // With Auth0
497
+ function AppWithAuth0() {
498
+ const { user, getAccessTokenSilently } = useAuth0();
499
+
500
+ return (
501
+ <DismissibleProvider
502
+ userId={user.sub}
503
+ jwt={async () => await getAccessTokenSilently()}
504
+ baseUrl="https://api.yourapp.com"
505
+ >
506
+ <YourApp />
507
+ </DismissibleProvider>
508
+ );
509
+ }
510
+
511
+ // With token refresh logic
512
+ function AppWithTokenRefresh() {
513
+ const { user } = useAuth();
514
+
515
+ return (
516
+ <DismissibleProvider
517
+ userId={user.id}
518
+ jwt={async () => {
519
+ try {
520
+ const response = await fetch('/api/auth/refresh', {
521
+ method: 'POST',
522
+ credentials: 'include'
523
+ });
524
+ const { accessToken } = await response.json();
525
+ return accessToken;
526
+ } catch (error) {
527
+ console.error('Failed to refresh token:', error);
528
+ throw error;
529
+ }
530
+ }}
531
+ baseUrl="https://api.yourapp.com"
532
+ >
533
+ <YourApp />
534
+ </DismissibleProvider>
535
+ );
536
+ }
537
+ ```
538
+
473
539
  ### Using the Hook for Complex Logic
474
540
 
475
541
  ```tsx
@@ -477,12 +543,12 @@ import { useDismissibleItem } from '@dismissible/react-client';
477
543
  import { useState, useEffect } from 'react';
478
544
 
479
545
  function SmartNotification({ itemId, message, type = 'info' }) {
480
- const { dismissedAt, dismiss, isLoading } = useDismissibleItem(itemId);
546
+ const { dismissedOn, dismiss, isLoading } = useDismissibleItem(itemId);
481
547
  const [autoHide, setAutoHide] = useState(false);
482
548
 
483
549
  // Auto-hide after 10 seconds for info messages
484
550
  useEffect(() => {
485
- if (type === 'info' && !dismissedAt) {
551
+ if (type === 'info' && !dismissedOn) {
486
552
  const timer = setTimeout(() => {
487
553
  setAutoHide(true);
488
554
  dismiss();
@@ -490,9 +556,9 @@ function SmartNotification({ itemId, message, type = 'info' }) {
490
556
 
491
557
  return () => clearTimeout(timer);
492
558
  }
493
- }, [type, dismissedAt, dismiss]);
559
+ }, [type, dismissedOn, dismiss]);
494
560
 
495
- if (dismissedAt || autoHide) {
561
+ if (dismissedOn || autoHide) {
496
562
  return null;
497
563
  }
498
564
 
@@ -519,12 +585,12 @@ Use the `restore` function to bring back previously dismissed content:
519
585
  import { useDismissibleItem } from '@dismissible/react-client';
520
586
 
521
587
  function RestorableBanner({ itemId }) {
522
- const { dismissedAt, dismiss, restore, isLoading } = useDismissibleItem(itemId);
588
+ const { dismissedOn, dismiss, restore, isLoading } = useDismissibleItem(itemId);
523
589
 
524
- if (dismissedAt) {
590
+ if (dismissedOn) {
525
591
  return (
526
592
  <div className="dismissed-placeholder">
527
- <p>Banner was dismissed on {new Date(dismissedAt).toLocaleDateString()}</p>
593
+ <p>Banner was dismissed on {new Date(dismissedOn).toLocaleDateString()}</p>
528
594
  <button onClick={restore} disabled={isLoading}>
529
595
  {isLoading ? 'Restoring...' : 'Show Banner Again'}
530
596
  </button>
@@ -544,6 +610,51 @@ function RestorableBanner({ itemId }) {
544
610
  }
545
611
  ```
546
612
 
613
+ ### Admin Panel with Restore Capability
614
+
615
+ ```tsx
616
+ import { useDismissibleItem } from '@dismissible/react-client';
617
+
618
+ function AdminNotificationManager({ notificationId }) {
619
+ const { dismissedOn, dismiss, restore, item, isLoading, error } =
620
+ useDismissibleItem(notificationId);
621
+
622
+ if (error) {
623
+ return <div className="error">Error: {error.message}</div>;
624
+ }
625
+
626
+ return (
627
+ <div className="admin-panel">
628
+ <h4>Notification: {notificationId}</h4>
629
+ <p>Status: {dismissedOn ? 'Dismissed' : 'Active'}</p>
630
+ {dismissedOn && (
631
+ <p>Dismissed at: {new Date(dismissedOn).toLocaleString()}</p>
632
+ )}
633
+
634
+ <div className="actions">
635
+ {dismissedOn ? (
636
+ <button
637
+ onClick={restore}
638
+ disabled={isLoading}
639
+ className="btn-restore"
640
+ >
641
+ Restore
642
+ </button>
643
+ ) : (
644
+ <button
645
+ onClick={dismiss}
646
+ disabled={isLoading}
647
+ className="btn-dismiss"
648
+ >
649
+ Dismiss
650
+ </button>
651
+ )}
652
+ </div>
653
+ </div>
654
+ );
655
+ }
656
+ ```
657
+
547
658
  ## Styling
548
659
 
549
660
  The library includes minimal default styles. You can override them or provide your own:
@@ -567,6 +678,35 @@ The library includes minimal default styles. You can override them or provide yo
567
678
  }
568
679
  ```
569
680
 
681
+ ## TypeScript Support
682
+
683
+ The library is written in TypeScript and exports all type definitions:
684
+
685
+ ```tsx
686
+ import type {
687
+ DismissibleProps,
688
+ DismissibleProviderProps,
689
+ JwtToken,
690
+ } from '@dismissible/react-client';
691
+
692
+ // Custom provider wrapper
693
+ const AuthenticatedDismissibleProvider: React.FC<{
694
+ children: React.ReactNode;
695
+ }> = ({ children }) => {
696
+ const { user, getToken } = useAuth();
697
+
698
+ return (
699
+ <DismissibleProvider
700
+ userId={user.id}
701
+ jwt={getToken}
702
+ baseUrl={process.env.DISMISSIBLE_API_URL}
703
+ >
704
+ {children}
705
+ </DismissibleProvider>
706
+ );
707
+ };
708
+ ```
709
+
570
710
  ## Self-Hosting
571
711
 
572
712
  Dismissible is designed to be self-hosted. You have full control over your data.
@@ -593,9 +733,9 @@ See the [NestJS documentation](https://dismissible.io/docs/nestjs) for setup ins
593
733
 
594
734
  ## Support
595
735
 
596
- - [Documentation](https://dismissible.io/docs)
597
- - [GitHub - React Client](https://github.com/DismissibleIo/dismissible-react-client)
598
- - [GitHub - API Server](https://github.com/DismissibleIo/dismissible-api)
736
+ - 📖 [Documentation](https://dismissible.io/docs)
737
+ - 🐙 [GitHub - React Client](https://github.com/DismissibleIo/dismissible-react-client)
738
+ - 🐙 [GitHub - API Server](https://github.com/DismissibleIo/dismissible-api)
599
739
 
600
740
  ## License
601
741
 
@@ -1,7 +1,21 @@
1
+ /**
2
+ * API configuration settings
3
+ */
4
+ /**
5
+ * Configuration interface for API settings
6
+ */
1
7
  export interface ApiConfig {
2
8
  /** Base URL for API requests */
3
9
  baseUrl: string;
4
10
  }
11
+ /**
12
+ * Returns the API configuration based on the current environment
13
+ * @returns The API configuration object
14
+ */
5
15
  export declare const getConfig: () => ApiConfig;
16
+ /**
17
+ * Gets the API base URL
18
+ * @returns The base URL for API requests
19
+ */
6
20
  export declare const getBaseUrl: () => string;
7
21
  export default getConfig;