@edusight/notification-widget 1.0.33 → 1.0.35
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 +38 -23
- package/dist/{components-Cfc2kMlt.js → components-Dq8aSwWR.js} +10 -4
- package/dist/{components-Cfc2kMlt.js.map → components-Dq8aSwWR.js.map} +1 -1
- package/dist/{components-CFhP5nWW.cjs → components-dwdMDd9K.cjs} +10 -9
- package/dist/{components-CFhP5nWW.cjs.map → components-dwdMDd9K.cjs.map} +1 -1
- package/dist/index.cjs.js +2 -2
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.css +1 -1
- package/dist/index.esm.js +88 -85
- package/dist/index.esm.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const s=require("react/jsx-runtime"),i=require("react"),F=require("socket.io-client"),U=require("@edusight/notification-sdk"),E=require("./components-
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const s=require("react/jsx-runtime"),i=require("react"),F=require("socket.io-client"),U=require("@edusight/notification-sdk"),E=require("./components-dwdMDd9K.cjs"),v=require("./hooks-kLhwdW29.cjs"),B=({error:t,onRetry:r})=>s.jsxs("div",{className:"p-4 bg-[var(--widget-error)]/10 border border-[var(--widget-error)]/20 rounded-lg",role:"alert","data-testid":"error-boundary-fallback",children:[s.jsxs("div",{className:"flex items-center mb-2",children:[s.jsx(E.MdError,{className:"w-6 h-6 text-[var(--widget-error)] mr-2","aria-hidden":"true"}),s.jsx("h3",{className:"text-sm font-medium text-[var(--widget-error)]",children:"Something went wrong"})]}),s.jsx("p",{className:"text-sm mb-3 text-[var(--widget-error)]/80",children:"The notification widget encountered an error and couldn't load properly."}),process.env.NODE_ENV==="development"&&t&&s.jsxs("details",{className:"mb-3",children:[s.jsx("summary",{className:"text-xs cursor-pointer text-[var(--widget-error)] hover:text-[var(--widget-error)]/80 transition-colors",children:"Error details (development only)"}),s.jsxs("pre",{className:"mt-2 text-xs bg-[var(--widget-error)]/5 p-2 rounded overflow-auto max-h-32 text-[var(--widget-error)]",children:[t.message,t.stack&&`
|
|
2
2
|
|
|
3
|
-
${t.stack}`]})]}),s.jsxs("button",{type:"button",className:"inline-flex items-center px-3 py-2 border border-transparent text-sm leading-4 font-medium rounded-md text-[var(--widget-error)] bg-[var(--widget-error)]/10 hover:bg-[var(--widget-error)]/20 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-[var(--widget-error)] transition-colors",onClick:r,"data-testid":"error-retry-button",children:[s.jsx(E.MdRefresh,{className:"mr-1 w-4 h-4","aria-hidden":"true"}),"Try again"]})]});class A extends i.Component{constructor(r){super(r),this.handleRetry=()=>{this.setState({hasError:!1,error:null,errorInfo:null})},this.state={hasError:!1,error:null,errorInfo:null}}static getDerivedStateFromError(r){return{hasError:!0,error:r}}componentDidCatch(r,u){this.setState({errorInfo:u}),this.props.onError&&this.props.onError(r,u)}render(){return this.state.hasError?s.jsx(B,{error:this.state.error,onRetry:this.handleRetry}):this.props.children}}const L=()=>window.__notificationSDK?.client,M=({onPreferencesLoaded:t,onError:r})=>{const u=L(),[w,c]=i.useState(!0),[o,n]=i.useState(null),[l,f]=i.useState(null),m=i.useCallback(async()=>{try{if(c(!0),n(null),!u)throw new Error("Notification client not available");const p=window.__notificationSDK?.config;if(!p)throw new Error("SDK configuration not available");const{subscriberId:S,tenantId:T,environmentId:b}=p;if(!S||!T||!b)throw new Error("SubscriberId, TenantId or EnvironmentId not available in config");const y=await u.preferences.get(T,S,b),C={channels:{email:y.emailEnabled??!0,push:y.pushEnabled??!0,sms:y.smsEnabled??!1,inApp:y.inAppEnabled??!0},subscriptions:[],deliverySchedule:{timezone:"UTC",quietHours:{start:y.quietHoursStart??"22:00",end:y.quietHoursEnd??"08:00"},weekdays:[!0,!0,!0,!0,!0,!1,!1]}};y.categories&&Object.entries(y.categories).forEach(([N,k])=>{C.subscriptions.push({workflowId:N,name:N,enabled:!0,channels:{email:k.emailEnabled??!0,push:k.pushEnabled??!0,sms:k.smsEnabled??!1,inApp:k.inAppEnabled??!0}})}),f(C),t(C)}catch(p){const S=p instanceof Error?p:new Error("Failed to load preferences");p?.response?.status===404||p?.status===404||(n(S),r?.(S));const b={channels:{email:!0,push:!0,sms:!1,inApp:!0},subscriptions:[],deliverySchedule:{timezone:"UTC",quietHours:{start:"22:00",end:"08:00"},weekdays:[!0,!0,!0,!0,!0,!1,!1]}};f(b),t(b)}finally{c(!1)}},[u,t,r]);return i.useEffect(()=>{u&&m()},[u,m]),{isLoading:w,error:o,preferences:l}},q=()=>window.__notificationSDK?.client,V=()=>{const t=q(),[r,u]=i.useState([]),[w,c]=i.useState(!0),[o,n]=i.useState(null),l=i.useCallback(async()=>{try{if(c(!0),n(null),!t)throw new Error("[useWorkflows] Notification client not available");const f=window.__notificationSDK?.config;if(!f)throw new Error("[useWorkflows] SDK configuration not available");const{tenantId:m,environmentId:p}=f;if(!m||!p)throw new Error("[useWorkflows] TenantId or EnvironmentId not available in config");const T=((await t.workflows.list({status:"active"},m,p))?.workflows||[]).map(b=>({workflowId:b.workflowId,name:b.name||b.workflowId,description:b.description}));u(T)}catch(f){const m=f instanceof Error?f:new Error("Failed to load workflows");n(m),u([])}finally{c(!1)}},[t]);return i.useEffect(()=>{t&&l()},[t,l]),{workflows:r,isLoading:w,error:o,refetch:l}},O=i.createContext(null),z=()=>{const t=i.useContext(O);if(!t)throw new Error("useSDK must be used within a NotificationWidget");return t},$={notifications:[],unreadCount:0,preferences:{channels:{email:!0,push:!0,sms:!1,inApp:!0},subscriptions:[],deliverySchedule:{timezone:"UTC",quietHours:{start:"22:00",end:"08:00"},weekdays:[!0,!0,!0,!0,!0,!1,!1]}},ui:{isOpen:!1,currentView:"notifications",selectedNotifications:[],isLoading:!1,error:null},websocket:{connected:!1,reconnecting:!1}},H=({config:t,children:r})=>{const[u,w]=i.useState({client:null,isInitialized:!1,error:null});return i.useEffect(()=>{let c=!0;return(async()=>{try{const n=window.__notificationSDK;if(n?.client&&JSON.stringify(n.config)===JSON.stringify(t)){c&&w({client:n.client,isInitialized:!0,error:null});return}const l=new U.NotificationClient({apiUrl:t.baseUrl,apiKey:t.apiKey,tenantId:t.tenantId,environmentId:t.environmentId});window.__notificationSDK={client:l,config:t},c&&w({client:l,isInitialized:!0,error:null})}catch(n){c&&w({client:null,isInitialized:!1,error:n})}})(),()=>{c=!1}},[t]),s.jsx(O.Provider,{value:u,children:r})},J=(t,r)=>{switch(r.type){case"SET_NOTIFICATIONS":return{...t,notifications:r.payload,unreadCount:r.payload.filter(o=>!o.isRead).length};case"ADD_NOTIFICATION":const u=[r.payload,...t.notifications];return{...t,notifications:u,unreadCount:u.filter(o=>!o.isRead).length};case"UPDATE_NOTIFICATION":const w=t.notifications.map(o=>o.id===r.payload.id?{...o,...r.payload.updates}:o);return{...t,notifications:w,unreadCount:w.filter(o=>!o.isRead).length};case"DELETE_NOTIFICATION":const c=t.notifications.filter(o=>o.id!==r.payload);return{...t,notifications:c,unreadCount:c.filter(o=>!o.isRead).length};case"SET_PREFERENCES":return{...t,preferences:r.payload};case"SET_UI_STATE":return{...t,ui:{...t.ui,...r.payload}};case"SET_WEBSOCKET_STATE":return{...t,websocket:{...t.websocket,...r.payload}};default:return t}},G=({position:t="right",size:r="medium",theme:u="light",className:w="",onError:c})=>{const[o,n]=i.useReducer(J,$),{client:l,isInitialized:f,error:m}=z(),p=i.useRef(null),S=i.useCallback(e=>{n({type:"SET_PREFERENCES",payload:e})},[]),T=i.useCallback(e=>{c&&c(e)},[c]),{error:b}=M({onPreferencesLoaded:S,onError:T}),{workflows:y,isLoading:C}=V(),{updatePreference:N,isSaving:k,error:x}=v.useLivePreferences({preferences:o.preferences,onPreferencesChange:S,onError:T});i.useEffect(()=>{if(!C&&y.length>0){const e=y.map(a=>o.preferences.subscriptions.find(g=>g.workflowId===a.workflowId)||{workflowId:a.workflowId,name:a.name,enabled:!0,channels:{email:!0,push:!0,sms:!1,inApp:!0}});JSON.stringify(e)!==JSON.stringify(o.preferences.subscriptions)&&n({type:"SET_PREFERENCES",payload:{...o.preferences,subscriptions:e}})}},[y,C,o.preferences]);const _=i.useCallback(e=>{try{const a=v.createNotificationMapper();switch(e.type){case"notification_received":{const d=e.data;if(!a.validateWebSocketPayload(d))break;const g=a.toWidgetNotificationFromWebSocket(d);n({type:"ADD_NOTIFICATION",payload:g});break}case"notification_updated":n({type:"UPDATE_NOTIFICATION",payload:{id:e.data.id||e.data.notificationId,updates:e.data}});break;case"notification_deleted":n({type:"DELETE_NOTIFICATION",payload:e.data.id||e.data.notificationId});break;case"preferences_updated":n({type:"SET_PREFERENCES",payload:e.data});break;default:}}catch{}},[]),D=i.useCallback(async()=>{if(!(!l||!f||p.current))try{n({type:"SET_WEBSOCKET_STATE",payload:{reconnecting:!0}});const e=window.__notificationSDK?.config;if(!e)throw new Error("SDK configuration not available for WebSocket connection");const g=`${l.getApiHost()}/v1/notifications`,h=F.io(g,{query:{tenantId:e.tenantId,subscriberId:e.subscriberId,environmentId:e.environmentId},transports:["websocket"],autoConnect:!1,reconnection:!0,reconnectionAttempts:10,reconnectionDelay:1e3,reconnectionDelayMax:5e3});p.current=h,h.on("notification",I=>{_({type:"notification_received",data:I})}),h.on("connect",()=>{n({type:"SET_WEBSOCKET_STATE",payload:{connected:!0,reconnecting:!1}})}),h.on("disconnect",I=>{n({type:"SET_WEBSOCKET_STATE",payload:{connected:!1,reconnecting:!1}})}),h.on("reconnect_attempt",I=>{n({type:"SET_WEBSOCKET_STATE",payload:{connected:!1,reconnecting:!0}})}),h.on("connect_error",I=>{n({type:"SET_WEBSOCKET_STATE",payload:{connected:!1,reconnecting:!1}}),c&&c(I)}),h.connect()}catch(e){n({type:"SET_WEBSOCKET_STATE",payload:{connected:!1,reconnecting:!1}}),c&&c(e)}},[l,f,_,c]),W=i.useCallback(()=>{if(p.current)try{p.current.disconnect&&p.current.disconnect(),p.current=null,n({type:"SET_WEBSOCKET_STATE",payload:{connected:!1,reconnecting:!1}})}catch{}},[]),K=i.useCallback(()=>{n({type:"SET_UI_STATE",payload:{isOpen:!o.ui.isOpen}})},[o.ui.isOpen]),j=i.useCallback(()=>{n({type:"SET_UI_STATE",payload:{isOpen:!1}})},[]),R=i.useCallback(e=>{n({type:"SET_UI_STATE",payload:{currentView:e}})},[]),P=i.useCallback(async(e,a)=>{if(!l||!f)return;const d=window.__notificationSDK?.config;if(d){if(!e)throw new Error("notificationId is required");try{switch(a.type){case"mark_read":await l.inbox.markAsRead(e,d.tenantId,d.environmentId,d.subscriberId);break;case"mark_unread":await l.inbox.markAsUnread(e,d.tenantId,d.environmentId,d.subscriberId);break;case"archive":await l.inbox.archive(e,d.tenantId,d.environmentId,d.subscriberId);break;case"delete":await l.inbox.delete(e,d.tenantId,d.environmentId,d.subscriberId);break;default:a.handler&&await a.handler(e);break}switch(a.type){case"mark_read":n({type:"UPDATE_NOTIFICATION",payload:{id:e,updates:{isRead:!0}}});break;case"mark_unread":n({type:"UPDATE_NOTIFICATION",payload:{id:e,updates:{isRead:!1}}});break;case"archive":n({type:"UPDATE_NOTIFICATION",payload:{id:e,updates:{isArchived:!0}}});break;case"delete":n({type:"DELETE_NOTIFICATION",payload:e});break}}catch(g){c&&c(g)}}},[l]);return i.useEffect(()=>{if(!l||!f)return;(async()=>{try{n({type:"SET_UI_STATE",payload:{isLoading:!0}});const a=window.__notificationSDK?.config;if(!a)throw new Error("SDK configuration not available");const d=v.createNotificationMapper(),h=((await l.inbox.getRenderedNotifications({channel:"in_app",limit:50,offset:0},a.tenantId,a.environmentId,a.subscriberId))?.items||[]).map(I=>d.toWidgetNotification(I));n({type:"SET_NOTIFICATIONS",payload:h}),n({type:"SET_UI_STATE",payload:{isLoading:!1,error:null}})}catch(a){n({type:"SET_UI_STATE",payload:{isLoading:!1,error:a}}),c&&c(a)}})()},[l,f,c]),i.useEffect(()=>(l&&f&&D(),()=>{W()}),[l]),i.useEffect(()=>{if(!l||!f||o.websocket.connected)return;const e=setInterval(async()=>{try{const a=window.__notificationSDK?.config;if(!a)return;const d=v.createNotificationMapper(),h=((await l.inbox.getRenderedNotifications({channel:"in_app",limit:50,offset:0},a.tenantId,a.environmentId,a.subscriberId))?.items||[]).map(I=>d.toWidgetNotification(I));n({type:"SET_NOTIFICATIONS",payload:h})}catch{}},3e4);return()=>clearInterval(e)},[l,o.websocket.connected]),i.useEffect(()=>{const e=a=>{if(a.key==="notification_widget_sync"&&a.newValue)try{const d=JSON.parse(a.newValue);_(d)}catch{}};return window.addEventListener("storage",e),()=>window.removeEventListener("storage",e)},[_]),i.useEffect(()=>{n({type:"SET_UI_STATE",payload:{isLoading:k}})},[k]),i.useEffect(()=>{const e=m||x||b;e&&n({type:"SET_UI_STATE",payload:{error:e}})},[m,x,b]),!f&&!m?s.jsx("div",{className:`relative inline-block ${w}`,"data-widget-size":r||"small","data-theme":u,"data-testid":"notification-widget",children:s.jsx(E.ComponentErrorBoundary,{componentName:"BellComponent",children:s.jsx(E.BellComponent,{unreadCount:0,onClick:()=>{},size:r,disabled:!0})})}):m?s.jsx("div",{className:`relative inline-block ${w}`,"data-widget-size":r||"small","data-theme":u,"data-testid":"notification-widget",children:s.jsx(E.ComponentErrorBoundary,{componentName:"BellComponent",fallback:s.jsx(E.SDKConnectionFallback,{error:m.message,onRetry:()=>window.location.reload()}),children:s.jsx(E.BellComponent,{unreadCount:0,onClick:()=>{},size:r,disabled:!0})})}):s.jsxs("div",{className:`relative inline-block ${w}`,"data-widget-size":r||"small","data-theme":u,"data-testid":"notification-widget",children:[s.jsx(E.ComponentErrorBoundary,{componentName:"BellComponent",children:s.jsx(E.BellComponent,{unreadCount:o.unreadCount,onClick:K,size:r,disabled:o.ui.isLoading})}),s.jsx(E.ComponentErrorBoundary,{componentName:"InboxPopover",fallback:s.jsx(E.LoadingFallback,{message:"Unable to load notifications"}),children:s.jsx(E.InboxPopover,{isOpen:o.ui.isOpen,onClose:j,position:t,currentView:o.ui.currentView,onViewChange:R,notifications:o.notifications,onNotificationAction:P,preferences:o.preferences,onPreferenceChange:N,isPreferencesLoading:k})})]})},Q=({sdkConfig:t,...r})=>s.jsx(A,{onError:r.onError,children:s.jsx(H,{config:t,children:s.jsx(G,{...r})})}),X="3.0.0",Y="@edusight/notification-widget";exports.BellComponent=E.BellComponent;exports.InboxPopover=E.InboxPopover;exports.NotificationItem=E.NotificationItem;exports.PreferencesView=E.PreferencesView;exports.NotificationWidget=Q;exports.NotificationWidgetErrorBoundary=A;exports.VERSION=X;exports.WIDGET_NAME=Y;
|
|
3
|
+
${t.stack}`]})]}),s.jsxs("button",{type:"button",className:"inline-flex items-center px-3 py-2 border border-transparent text-sm leading-4 font-medium rounded-md text-[var(--widget-error)] bg-[var(--widget-error)]/10 hover:bg-[var(--widget-error)]/20 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-[var(--widget-error)] transition-colors",onClick:r,"data-testid":"error-retry-button",children:[s.jsx(E.MdRefresh,{className:"mr-1 w-4 h-4","aria-hidden":"true"}),"Try again"]})]});class A extends i.Component{constructor(r){super(r),this.handleRetry=()=>{this.setState({hasError:!1,error:null,errorInfo:null})},this.state={hasError:!1,error:null,errorInfo:null}}static getDerivedStateFromError(r){return{hasError:!0,error:r}}componentDidCatch(r,u){this.setState({errorInfo:u}),this.props.onError&&this.props.onError(r,u)}render(){return this.state.hasError?s.jsx(B,{error:this.state.error,onRetry:this.handleRetry}):this.props.children}}const L=()=>window.__notificationSDK?.client,M=({onPreferencesLoaded:t,onError:r})=>{const u=L(),[w,c]=i.useState(!0),[o,n]=i.useState(null),[l,f]=i.useState(null),m=i.useCallback(async()=>{try{if(c(!0),n(null),!u)throw new Error("Notification client not available");const p=window.__notificationSDK?.config;if(!p)throw new Error("SDK configuration not available");const{subscriberId:g,tenantId:T,environmentId:b}=p;if(!g||!T||!b)throw new Error("SubscriberId, TenantId or EnvironmentId not available in config");const y=await u.preferences.get(T,g,b),C={channels:{email:y.emailEnabled??!0,push:y.pushEnabled??!0,sms:y.smsEnabled??!1,inApp:y.inAppEnabled??!0},subscriptions:[],deliverySchedule:{timezone:"UTC",quietHours:{start:y.quietHoursStart??"22:00",end:y.quietHoursEnd??"08:00"},weekdays:[!0,!0,!0,!0,!0,!1,!1]}};y.categories&&Object.entries(y.categories).forEach(([N,k])=>{C.subscriptions.push({workflowId:N,name:N,enabled:!0,channels:{email:k.emailEnabled??!0,push:k.pushEnabled??!0,sms:k.smsEnabled??!1,inApp:k.inAppEnabled??!0}})}),f(C),t(C)}catch(p){const g=p instanceof Error?p:new Error("Failed to load preferences");p?.response?.status===404||p?.status===404||(n(g),r?.(g));const b={channels:{email:!0,push:!0,sms:!1,inApp:!0},subscriptions:[],deliverySchedule:{timezone:"UTC",quietHours:{start:"22:00",end:"08:00"},weekdays:[!0,!0,!0,!0,!0,!1,!1]}};f(b),t(b)}finally{c(!1)}},[u,t,r]);return i.useEffect(()=>{u&&m()},[u,m]),{isLoading:w,error:o,preferences:l}},q=()=>window.__notificationSDK?.client,V=()=>{const t=q(),[r,u]=i.useState([]),[w,c]=i.useState(!0),[o,n]=i.useState(null),l=i.useCallback(async()=>{try{if(c(!0),n(null),!t)throw new Error("[useWorkflows] Notification client not available");const f=window.__notificationSDK?.config;if(!f)throw new Error("[useWorkflows] SDK configuration not available");const{tenantId:m,environmentId:p}=f;if(!m||!p)throw new Error("[useWorkflows] TenantId or EnvironmentId not available in config");const T=((await t.workflows.list({status:"active"},m,p))?.workflows||[]).map(b=>({workflowId:b.workflowId,name:b.name||b.workflowId,description:b.description}));u(T)}catch(f){const m=f instanceof Error?f:new Error("Failed to load workflows");n(m),u([])}finally{c(!1)}},[t]);return i.useEffect(()=>{t&&l()},[t,l]),{workflows:r,isLoading:w,error:o,refetch:l}},O=i.createContext(null),z=()=>{const t=i.useContext(O);if(!t)throw new Error("useSDK must be used within a NotificationWidget");return t},$={notifications:[],unreadCount:0,preferences:{channels:{email:!0,push:!0,sms:!1,inApp:!0},subscriptions:[],deliverySchedule:{timezone:"UTC",quietHours:{start:"22:00",end:"08:00"},weekdays:[!0,!0,!0,!0,!0,!1,!1]}},ui:{isOpen:!1,currentView:"notifications",selectedNotifications:[],isLoading:!1,error:null},websocket:{connected:!1,reconnecting:!1}},H=({config:t,children:r})=>{const[u,w]=i.useState({client:null,isInitialized:!1,error:null});return i.useEffect(()=>{let c=!0;return(async()=>{try{const n=window.__notificationSDK;if(n?.client&&JSON.stringify(n.config)===JSON.stringify(t)){c&&w({client:n.client,isInitialized:!0,error:null});return}const l=new U.NotificationClient({apiUrl:t.baseUrl,apiKey:t.apiKey,tenantId:t.tenantId,environmentId:t.environmentId});window.__notificationSDK={client:l,config:t},c&&w({client:l,isInitialized:!0,error:null})}catch(n){c&&w({client:null,isInitialized:!1,error:n})}})(),()=>{c=!1}},[t]),s.jsx(O.Provider,{value:u,children:r})},J=(t,r)=>{switch(r.type){case"SET_NOTIFICATIONS":return{...t,notifications:r.payload,unreadCount:r.payload.filter(o=>!o.isRead).length};case"ADD_NOTIFICATION":const u=[r.payload,...t.notifications];return{...t,notifications:u,unreadCount:u.filter(o=>!o.isRead).length};case"UPDATE_NOTIFICATION":const w=t.notifications.map(o=>o.id===r.payload.id?{...o,...r.payload.updates}:o);return{...t,notifications:w,unreadCount:w.filter(o=>!o.isRead).length};case"DELETE_NOTIFICATION":const c=t.notifications.filter(o=>o.id!==r.payload);return{...t,notifications:c,unreadCount:c.filter(o=>!o.isRead).length};case"SET_PREFERENCES":return{...t,preferences:r.payload};case"SET_UI_STATE":return{...t,ui:{...t.ui,...r.payload}};case"SET_WEBSOCKET_STATE":return{...t,websocket:{...t.websocket,...r.payload}};default:return t}},G=({position:t="right",size:r="medium",theme:u="light",className:w="",onError:c})=>{const[o,n]=i.useReducer(J,$),{client:l,isInitialized:f,error:m}=z(),p=i.useRef(null),g=i.useCallback(e=>{n({type:"SET_PREFERENCES",payload:e})},[]),T=i.useCallback(e=>{c&&c(e)},[c]),{error:b}=M({onPreferencesLoaded:g,onError:T}),{workflows:y,isLoading:C}=V(),{updatePreference:N,isSaving:k,error:x}=v.useLivePreferences({preferences:o.preferences,onPreferencesChange:g,onError:T});i.useEffect(()=>{if(!C&&y.length>0){const e=y.map(a=>o.preferences.subscriptions.find(S=>S.workflowId===a.workflowId)||{workflowId:a.workflowId,name:a.name,enabled:!0,channels:{email:!0,push:!0,sms:!1,inApp:!0}});JSON.stringify(e)!==JSON.stringify(o.preferences.subscriptions)&&n({type:"SET_PREFERENCES",payload:{...o.preferences,subscriptions:e}})}},[y,C,o.preferences]);const _=i.useCallback(e=>{try{const a=v.createNotificationMapper();switch(e.type){case"notification_received":{const d=e.data;if(!a.validateWebSocketPayload(d))break;const S=a.toWidgetNotificationFromWebSocket(d);n({type:"ADD_NOTIFICATION",payload:S});break}case"notification_updated":n({type:"UPDATE_NOTIFICATION",payload:{id:e.data.id||e.data.notificationId,updates:e.data}});break;case"notification_deleted":n({type:"DELETE_NOTIFICATION",payload:e.data.id||e.data.notificationId});break;case"preferences_updated":n({type:"SET_PREFERENCES",payload:e.data});break;default:}}catch{}},[]),D=i.useCallback(async()=>{if(!(!l||!f||p.current))try{n({type:"SET_WEBSOCKET_STATE",payload:{reconnecting:!0}});const e=window.__notificationSDK?.config;if(!e)throw new Error("SDK configuration not available for WebSocket connection");const S=`${l.getApiHost()}/v1/notifications`,h=F.io(S,{query:{tenantId:e.tenantId,subscriberId:e.subscriberId,environmentId:e.environmentId},transports:["websocket"],autoConnect:!1,reconnection:!0,reconnectionAttempts:10,reconnectionDelay:1e3,reconnectionDelayMax:5e3});p.current=h,h.on("notification",I=>{_({type:"notification_received",data:I})}),h.on("connect",()=>{n({type:"SET_WEBSOCKET_STATE",payload:{connected:!0,reconnecting:!1}})}),h.on("disconnect",I=>{n({type:"SET_WEBSOCKET_STATE",payload:{connected:!1,reconnecting:!1}})}),h.on("reconnect_attempt",I=>{n({type:"SET_WEBSOCKET_STATE",payload:{connected:!1,reconnecting:!0}})}),h.on("connect_error",I=>{n({type:"SET_WEBSOCKET_STATE",payload:{connected:!1,reconnecting:!1}}),c&&c(I)}),h.connect()}catch(e){n({type:"SET_WEBSOCKET_STATE",payload:{connected:!1,reconnecting:!1}}),c&&c(e)}},[l,f,_,c]),W=i.useCallback(()=>{if(p.current)try{p.current.disconnect&&p.current.disconnect(),p.current=null,n({type:"SET_WEBSOCKET_STATE",payload:{connected:!1,reconnecting:!1}})}catch{}},[]),K=i.useCallback(()=>{n({type:"SET_UI_STATE",payload:{isOpen:!o.ui.isOpen}})},[o.ui.isOpen]),j=i.useCallback(()=>{n({type:"SET_UI_STATE",payload:{isOpen:!1}})},[]),R=i.useCallback(e=>{n({type:"SET_UI_STATE",payload:{currentView:e}})},[]),P=i.useCallback(async(e,a)=>{if(!l||!f)return;const d=window.__notificationSDK?.config;if(d){if(!e)throw new Error("notificationId is required");try{switch(a.type){case"mark_read":await l.inbox.markAsRead(e,d.tenantId,d.environmentId,d.subscriberId);break;case"mark_unread":await l.inbox.markAsUnread(e,d.tenantId,d.environmentId,d.subscriberId);break;case"archive":await l.inbox.archive(e,d.tenantId,d.environmentId,d.subscriberId);break;case"delete":await l.inbox.delete(e,d.tenantId,d.environmentId,d.subscriberId);break;default:a.handler&&await a.handler(e);break}switch(a.type){case"mark_read":n({type:"UPDATE_NOTIFICATION",payload:{id:e,updates:{isRead:!0}}});break;case"mark_unread":n({type:"UPDATE_NOTIFICATION",payload:{id:e,updates:{isRead:!1}}});break;case"archive":n({type:"UPDATE_NOTIFICATION",payload:{id:e,updates:{isArchived:!0}}});break;case"delete":n({type:"DELETE_NOTIFICATION",payload:e});break}}catch(S){c&&c(S)}}},[l]);return i.useEffect(()=>{if(!l||!f)return;(async()=>{try{n({type:"SET_UI_STATE",payload:{isLoading:!0}});const a=window.__notificationSDK?.config;if(!a)throw new Error("SDK configuration not available");const d=v.createNotificationMapper(),h=((await l.inbox.getRenderedNotifications({channel:"in_app",limit:50,offset:0},a.tenantId,a.environmentId,a.subscriberId))?.items||[]).map(I=>d.toWidgetNotification(I));n({type:"SET_NOTIFICATIONS",payload:h}),n({type:"SET_UI_STATE",payload:{isLoading:!1,error:null}})}catch(a){n({type:"SET_UI_STATE",payload:{isLoading:!1,error:a}}),c&&c(a)}})()},[l,f,c]),i.useEffect(()=>(l&&f&&D(),()=>{W()}),[l]),i.useEffect(()=>{if(!l||!f||o.websocket.connected)return;const e=setInterval(async()=>{try{const a=window.__notificationSDK?.config;if(!a)return;const d=v.createNotificationMapper(),h=((await l.inbox.getRenderedNotifications({channel:"in_app",limit:50,offset:0},a.tenantId,a.environmentId,a.subscriberId))?.items||[]).map(I=>d.toWidgetNotification(I));n({type:"SET_NOTIFICATIONS",payload:h})}catch{}},3e4);return()=>clearInterval(e)},[l,o.websocket.connected]),i.useEffect(()=>{const e=a=>{if(a.key==="notification_widget_sync"&&a.newValue)try{const d=JSON.parse(a.newValue);_(d)}catch{}};return window.addEventListener("storage",e),()=>window.removeEventListener("storage",e)},[_]),i.useEffect(()=>{n({type:"SET_UI_STATE",payload:{isLoading:k}})},[k]),i.useEffect(()=>{const e=m||x||b;e&&n({type:"SET_UI_STATE",payload:{error:e}})},[m,x,b]),!f&&!m?s.jsx("div",{className:`mx-widget-root relative inline-block ${w}`,"data-mx-widget":"root","data-widget-size":r||"small","data-theme":u,"data-testid":"notification-widget",children:s.jsx(E.ComponentErrorBoundary,{componentName:"BellComponent",children:s.jsx(E.BellComponent,{unreadCount:0,onClick:()=>{},size:r,disabled:!0})})}):m?s.jsx("div",{className:`mx-widget-root relative inline-block ${w}`,"data-mx-widget":"root","data-widget-size":r||"small","data-theme":u,"data-testid":"notification-widget",children:s.jsx(E.ComponentErrorBoundary,{componentName:"BellComponent",fallback:s.jsx(E.SDKConnectionFallback,{error:m.message,onRetry:()=>window.location.reload()}),children:s.jsx(E.BellComponent,{unreadCount:0,onClick:()=>{},size:r,disabled:!0})})}):s.jsxs("div",{className:`mx-widget-root relative inline-block ${w}`,"data-mx-widget":"root","data-widget-size":r||"small","data-theme":u,"data-testid":"notification-widget",children:[s.jsx(E.ComponentErrorBoundary,{componentName:"BellComponent",children:s.jsx(E.BellComponent,{unreadCount:o.unreadCount,onClick:K,size:r,disabled:o.ui.isLoading})}),s.jsx(E.ComponentErrorBoundary,{componentName:"InboxPopover",fallback:s.jsx(E.LoadingFallback,{message:"Unable to load notifications"}),children:s.jsx(E.InboxPopover,{isOpen:o.ui.isOpen,onClose:j,position:t,currentView:o.ui.currentView,onViewChange:R,notifications:o.notifications,onNotificationAction:P,preferences:o.preferences,onPreferenceChange:N,isPreferencesLoading:k})})]})},Q=({sdkConfig:t,...r})=>s.jsx(A,{onError:r.onError,children:s.jsx(H,{config:t,children:s.jsx(G,{...r})})}),X="3.0.0",Y="@edusight/notification-widget";exports.BellComponent=E.BellComponent;exports.InboxPopover=E.InboxPopover;exports.NotificationItem=E.NotificationItem;exports.PreferencesView=E.PreferencesView;exports.NotificationWidget=Q;exports.NotificationWidgetErrorBoundary=A;exports.VERSION=X;exports.WIDGET_NAME=Y;
|
|
4
4
|
//# sourceMappingURL=index.cjs.js.map
|
package/dist/index.cjs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs.js","sources":["../src/components/ErrorBoundary.tsx","../src/hooks/usePreferencesSync.ts","../src/hooks/useWorkflows.ts","../src/components/NotificationWidget.tsx","../src/index.ts"],"sourcesContent":["import React, { Component, ErrorInfo, ReactNode } from 'react';\r\nimport { MdError, MdRefresh } from 'react-icons/md';\r\nimport { ErrorBoundaryState } from '../types/core';\r\n\r\ninterface ErrorBoundaryProps {\r\n children: ReactNode;\r\n onError?: (error: Error, errorInfo: ErrorInfo) => void;\r\n}\r\n\r\nconst ErrorFallback: React.FC<{\r\n error: Error | null;\r\n onRetry: () => void;\r\n}> = ({ error, onRetry }) => (\r\n <div\r\n className=\"p-4 bg-[var(--widget-error)]/10 border border-[var(--widget-error)]/20 rounded-lg\"\r\n role=\"alert\"\r\n data-testid=\"error-boundary-fallback\"\r\n >\r\n <div className=\"flex items-center mb-2\">\r\n <MdError\r\n className=\"w-6 h-6 text-[var(--widget-error)] mr-2\"\r\n aria-hidden=\"true\"\r\n />\r\n <h3\r\n className=\"text-sm font-medium text-[var(--widget-error)]\"\r\n >\r\n Something went wrong\r\n </h3>\r\n </div>\r\n\r\n <p\r\n className=\"text-sm mb-3 text-[var(--widget-error)]/80\"\r\n >\r\n The notification widget encountered an error and couldn't load properly.\r\n </p>\r\n\r\n {process.env.NODE_ENV === 'development' && error && (\r\n <details className=\"mb-3\">\r\n <summary\r\n className=\"text-xs cursor-pointer text-[var(--widget-error)] hover:text-[var(--widget-error)]/80 transition-colors\"\r\n >\r\n Error details (development only)\r\n </summary>\r\n <pre\r\n className=\"mt-2 text-xs bg-[var(--widget-error)]/5 p-2 rounded overflow-auto max-h-32 text-[var(--widget-error)]\"\r\n >\r\n {error.message}\r\n {error.stack && `\\n\\n${error.stack}`}\r\n </pre>\r\n </details>\r\n )}\r\n\r\n <button\r\n type=\"button\"\r\n className=\"inline-flex items-center px-3 py-2 border border-transparent text-sm leading-4 font-medium rounded-md text-[var(--widget-error)] bg-[var(--widget-error)]/10 hover:bg-[var(--widget-error)]/20 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-[var(--widget-error)] transition-colors\"\r\n onClick={onRetry}\r\n data-testid=\"error-retry-button\"\r\n >\r\n <MdRefresh\r\n className=\"mr-1 w-4 h-4\"\r\n aria-hidden=\"true\"\r\n />\r\n Try again\r\n </button>\r\n </div>\r\n);\r\n\r\nexport class NotificationWidgetErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {\r\n constructor(props: ErrorBoundaryProps) {\r\n super(props);\r\n this.state = {\r\n hasError: false,\r\n error: null,\r\n errorInfo: null,\r\n };\r\n }\r\n\r\n static getDerivedStateFromError(error: Error): Partial<ErrorBoundaryState> {\r\n return {\r\n hasError: true,\r\n error,\r\n };\r\n }\r\n\r\n componentDidCatch(error: Error, errorInfo: ErrorInfo) {\r\n this.setState({\r\n errorInfo,\r\n });\r\n\r\n console.error('NotificationWidget Error Boundary caught an error:', {\r\n message: error.message,\r\n stack: error.stack,\r\n componentStack: errorInfo.componentStack,\r\n timestamp: new Date().toISOString(),\r\n });\r\n\r\n if (this.props.onError) {\r\n this.props.onError(error, errorInfo);\r\n }\r\n }\r\n\r\n handleRetry = () => {\r\n this.setState({\r\n hasError: false,\r\n error: null,\r\n errorInfo: null,\r\n });\r\n };\r\n\r\n render() {\r\n if (this.state.hasError) {\r\n return (\r\n <ErrorFallback\r\n error={this.state.error}\r\n onRetry={this.handleRetry}\r\n />\r\n );\r\n }\r\n\r\n return this.props.children;\r\n }\r\n}\r\n\r\nexport const useErrorHandler = () => {\r\n return (error: Error, errorInfo?: ErrorInfo) => {\r\n console.error('Widget error:', {\r\n message: error.message,\r\n stack: error.stack,\r\n errorInfo,\r\n timestamp: new Date().toISOString(),\r\n });\r\n };\r\n};","import { useEffect, useState, useCallback } from 'react';\r\nimport { NotificationPreferences } from '../types/core';\r\n\r\nconst useNotificationsClient = () => {\r\n return (window as any).__notificationSDK?.client;\r\n};\r\n\r\nexport interface UsePreferencesSyncProps {\r\n onPreferencesLoaded: (preferences: NotificationPreferences) => void;\r\n onError?: (error: Error) => void;\r\n}\r\n\r\nexport interface UsePreferencesSyncResult {\r\n isLoading: boolean;\r\n error: Error | null;\r\n preferences: NotificationPreferences | null;\r\n}\r\n\r\nexport const usePreferencesSync = ({\r\n onPreferencesLoaded,\r\n onError,\r\n}: UsePreferencesSyncProps): UsePreferencesSyncResult => {\r\n const notificationClient = useNotificationsClient();\r\n const [isLoading, setIsLoading] = useState(true);\r\n const [error, setError] = useState<Error | null>(null);\r\n const [preferences, setPreferences] = useState<NotificationPreferences | null>(null);\r\n\r\n const loadPreferences = useCallback(async () => {\r\n try {\r\n setIsLoading(true);\r\n setError(null);\r\n\r\n if (!notificationClient) {\r\n throw new Error('Notification client not available');\r\n }\r\n\r\n const config = (window as any).__notificationSDK?.config;\r\n\r\n if (!config) {\r\n throw new Error('SDK configuration not available');\r\n }\r\n\r\n const { subscriberId, tenantId, environmentId } = config;\r\n\r\n if (!subscriberId || !tenantId || !environmentId) {\r\n throw new Error('SubscriberId, TenantId or EnvironmentId not available in config');\r\n }\r\n\r\n const servicePreferences = await notificationClient.preferences.get(\r\n tenantId,\r\n subscriberId,\r\n environmentId,\r\n );\r\n\r\n const mappedPreferences: NotificationPreferences = {\r\n channels: {\r\n email: servicePreferences.emailEnabled ?? true,\r\n push: servicePreferences.pushEnabled ?? true,\r\n sms: servicePreferences.smsEnabled ?? false,\r\n inApp: servicePreferences.inAppEnabled ?? true,\r\n },\r\n subscriptions: [],\r\n deliverySchedule: {\r\n timezone: 'UTC',\r\n quietHours: {\r\n start: servicePreferences.quietHoursStart ?? '22:00',\r\n end: servicePreferences.quietHoursEnd ?? '08:00',\r\n },\r\n weekdays: [true, true, true, true, true, false, false],\r\n },\r\n };\r\n\r\n if (servicePreferences.categories) {\r\n Object.entries(servicePreferences.categories).forEach(([workflowId, categoryPrefs]) => {\r\n mappedPreferences.subscriptions.push({\r\n workflowId,\r\n name: workflowId,\r\n enabled: true,\r\n channels: {\r\n email: (categoryPrefs as any).emailEnabled ?? true,\r\n push: (categoryPrefs as any).pushEnabled ?? true,\r\n sms: (categoryPrefs as any).smsEnabled ?? false,\r\n inApp: (categoryPrefs as any).inAppEnabled ?? true,\r\n },\r\n });\r\n });\r\n }\r\n\r\n setPreferences(mappedPreferences);\r\n onPreferencesLoaded(mappedPreferences);\r\n } catch (err: any) {\r\n const error = err instanceof Error ? err : new Error('Failed to load preferences');\r\n\r\n // If 404, it means preferences don't exist yet for this user. \r\n // We'll use defaults and suppress the error callback.\r\n const isNotFound = (err as any)?.response?.status === 404 || (err as any)?.status === 404;\r\n\r\n if (!isNotFound) {\r\n setError(error);\r\n onError?.(error);\r\n } else {\r\n console.warn('Preferences not found for user (404), using defaults.');\r\n }\r\n\r\n const defaultPreferences: NotificationPreferences = {\r\n channels: {\r\n email: true,\r\n push: true,\r\n sms: false,\r\n inApp: true,\r\n },\r\n subscriptions: [],\r\n deliverySchedule: {\r\n timezone: 'UTC',\r\n quietHours: {\r\n start: '22:00',\r\n end: '08:00',\r\n },\r\n weekdays: [true, true, true, true, true, false, false],\r\n },\r\n };\r\n setPreferences(defaultPreferences);\r\n onPreferencesLoaded(defaultPreferences);\r\n } finally {\r\n setIsLoading(false);\r\n }\r\n }, [notificationClient, onPreferencesLoaded, onError]);\r\n\r\n useEffect(() => {\r\n if (notificationClient) {\r\n loadPreferences();\r\n }\r\n }, [notificationClient, loadPreferences]);\r\n\r\n return {\r\n isLoading,\r\n error,\r\n preferences,\r\n };\r\n};\r\n","import { useEffect, useState, useCallback } from 'react';\r\n\r\nconst useNotificationsClient = () => {\r\n return (window as any).__notificationSDK?.client;\r\n};\r\n\r\nexport interface Workflow {\r\n workflowId: string;\r\n name: string;\r\n description?: string;\r\n}\r\n\r\nexport interface UseWorkflowsResult {\r\n workflows: Workflow[];\r\n isLoading: boolean;\r\n error: Error | null;\r\n refetch: () => void;\r\n}\r\n\r\nexport const useWorkflows = (): UseWorkflowsResult => {\r\n const notificationClient = useNotificationsClient();\r\n const [workflows, setWorkflows] = useState<Workflow[]>([]);\r\n const [isLoading, setIsLoading] = useState(true);\r\n const [error, setError] = useState<Error | null>(null);\r\n\r\n const loadWorkflows = useCallback(async () => {\r\n try {\r\n setIsLoading(true);\r\n setError(null);\r\n\r\n if (!notificationClient) {\r\n throw new Error('[useWorkflows] Notification client not available');\r\n }\r\n\r\n const config = (window as any).__notificationSDK?.config;\r\n\r\n if (!config) {\r\n throw new Error('[useWorkflows] SDK configuration not available');\r\n }\r\n\r\n const { tenantId, environmentId } = config;\r\n\r\n if (!tenantId || !environmentId) {\r\n throw new Error('[useWorkflows] TenantId or EnvironmentId not available in config');\r\n }\r\n\r\n const response = await notificationClient.workflows.list(\r\n { status: 'active' },\r\n tenantId,\r\n environmentId\r\n );\r\n\r\n const mappedWorkflows: Workflow[] = (response?.workflows || []).map((wf: any) => ({\r\n workflowId: wf.workflowId,\r\n name: wf.name || wf.workflowId,\r\n description: wf.description,\r\n }));\r\n\r\n setWorkflows(mappedWorkflows);\r\n } catch (err: any) {\r\n const error = err instanceof Error ? err : new Error('Failed to load workflows');\r\n\r\n console.warn('[useWorkflows] Failed to load workflows:', error);\r\n setError(error);\r\n setWorkflows([]);\r\n } finally {\r\n setIsLoading(false);\r\n }\r\n }, [notificationClient]);\r\n\r\n useEffect(() => {\r\n if (notificationClient) {\r\n loadWorkflows();\r\n }\r\n }, [notificationClient, loadWorkflows]);\r\n\r\n return {\r\n workflows,\r\n isLoading,\r\n error,\r\n refetch: loadWorkflows,\r\n };\r\n};\r\n","\r\nimport React, { useReducer, useEffect, useCallback, createContext, useContext, useRef } from 'react';\r\nimport { io as ioClient } from 'socket.io-client';\r\nimport { NotificationClient } from '@edusight/notification-sdk';\r\nimport { NotificationWidgetProps, WidgetState, WidgetAction, SDKConfiguration } from '../types/core';\r\nimport { BellComponent } from './BellComponent';\r\nimport { InboxPopover } from './InboxPopover';\r\nimport { NotificationWidgetErrorBoundary } from './ErrorBoundary';\r\nimport { ComponentErrorBoundary } from './ComponentErrorBoundary';\r\nimport { SDKConnectionFallback, LoadingFallback } from './FallbackComponents';\r\nimport { useLivePreferences } from '../hooks/useLivePreferences';\r\nimport { usePreferencesSync } from '../hooks/usePreferencesSync';\r\nimport { useWorkflows } from '../hooks/useWorkflows';\r\nimport { createNotificationMapper } from '../utils/notification-mapper';\r\n\r\ninterface SDKContextType {\r\n client: any;\r\n isInitialized: boolean;\r\n error: Error | null;\r\n}\r\n\r\nconst SDKContext = createContext<SDKContextType | null>(null);\r\n\r\nexport const useSDK = () => {\r\n const context = useContext(SDKContext);\r\n if (!context) {\r\n throw new Error('useSDK must be used within a NotificationWidget');\r\n }\r\n return context;\r\n};\r\n\r\nconst initialState: WidgetState = {\r\n notifications: [],\r\n unreadCount: 0,\r\n preferences: {\r\n channels: {\r\n email: true,\r\n push: true,\r\n sms: false,\r\n inApp: true,\r\n },\r\n subscriptions: [],\r\n deliverySchedule: {\r\n timezone: 'UTC',\r\n quietHours: {\r\n start: '22:00',\r\n end: '08:00',\r\n },\r\n weekdays: [true, true, true, true, true, false, false],\r\n },\r\n },\r\n ui: {\r\n isOpen: false,\r\n currentView: 'notifications',\r\n selectedNotifications: [],\r\n isLoading: false,\r\n error: null,\r\n },\r\n websocket: {\r\n connected: false,\r\n reconnecting: false,\r\n },\r\n};\r\n\r\nconst SDKProvider: React.FC<{ config: SDKConfiguration; children: React.ReactNode }> = ({\r\n config,\r\n children,\r\n}) => {\r\n const [sdkState, setSdkState] = React.useState<SDKContextType>({\r\n client: null,\r\n isInitialized: false,\r\n error: null,\r\n });\r\n\r\n useEffect(() => {\r\n let isMounted = true;\r\n\r\n const initializeSDK = async () => {\r\n try {\r\n const existingSDK = (window as any).__notificationSDK;\r\n\r\n // Check if we can reuse the existing SDK instance\r\n if (existingSDK?.client) {\r\n // Compare new config with existing config to determine if we need to re-initialize\r\n // We use simple JSON stringify as configs are simple objects with strings/numbers\r\n const isConfigMatch = JSON.stringify(existingSDK.config) === JSON.stringify(config);\r\n\r\n if (isConfigMatch) {\r\n if (isMounted) {\r\n setSdkState({\r\n client: existingSDK.client,\r\n isInitialized: true,\r\n error: null,\r\n });\r\n }\r\n return;\r\n } else {\r\n console.log('[NotificationWidget] Config changed, re-initializing SDK', { old: existingSDK.config, new: config });\r\n }\r\n }\r\n\r\n const client = new NotificationClient({\r\n apiUrl: config.baseUrl,\r\n apiKey: config.apiKey,\r\n tenantId: config.tenantId,\r\n environmentId: config.environmentId,\r\n });\r\n\r\n (window as any).__notificationSDK = { client, config };\r\n\r\n if (isMounted) {\r\n setSdkState({\r\n client,\r\n isInitialized: true,\r\n error: null,\r\n });\r\n }\r\n } catch (error) {\r\n console.error('Failed to initialize SDK:', error);\r\n if (isMounted) {\r\n setSdkState({\r\n client: null,\r\n isInitialized: false,\r\n error: error as Error,\r\n });\r\n }\r\n }\r\n };\r\n\r\n initializeSDK();\r\n\r\n return () => {\r\n isMounted = false;\r\n };\r\n }, [config]);\r\n\r\n return (\r\n <SDKContext.Provider value={sdkState}>\r\n {children}\r\n </SDKContext.Provider>\r\n );\r\n};\r\n\r\nconst widgetReducer = (state: WidgetState, action: WidgetAction): WidgetState => {\r\n switch (action.type) {\r\n case 'SET_NOTIFICATIONS':\r\n return {\r\n ...state,\r\n notifications: action.payload,\r\n unreadCount: action.payload.filter(n => !n.isRead).length,\r\n };\r\n\r\n case 'ADD_NOTIFICATION':\r\n const newNotifications = [action.payload, ...state.notifications];\r\n return {\r\n ...state,\r\n notifications: newNotifications,\r\n unreadCount: newNotifications.filter(n => !n.isRead).length,\r\n };\r\n\r\n case 'UPDATE_NOTIFICATION':\r\n const updatedNotifications = state.notifications.map(n =>\r\n n.id === action.payload.id ? { ...n, ...action.payload.updates } : n\r\n );\r\n return {\r\n ...state,\r\n notifications: updatedNotifications,\r\n unreadCount: updatedNotifications.filter(n => !n.isRead).length,\r\n };\r\n\r\n case 'DELETE_NOTIFICATION':\r\n const filteredNotifications = state.notifications.filter(n => n.id !== action.payload);\r\n return {\r\n ...state,\r\n notifications: filteredNotifications,\r\n unreadCount: filteredNotifications.filter(n => !n.isRead).length,\r\n };\r\n\r\n case 'SET_PREFERENCES':\r\n return {\r\n ...state,\r\n preferences: action.payload,\r\n };\r\n\r\n case 'SET_UI_STATE':\r\n return {\r\n ...state,\r\n ui: { ...state.ui, ...action.payload },\r\n };\r\n\r\n case 'SET_WEBSOCKET_STATE':\r\n return {\r\n ...state,\r\n websocket: { ...state.websocket, ...action.payload },\r\n };\r\n\r\n default:\r\n return state;\r\n }\r\n};\r\n\r\nconst NotificationWidgetInternal: React.FC<Omit<NotificationWidgetProps, 'sdkConfig'>> = ({\r\n position = 'right',\r\n size = 'medium',\r\n theme = 'light',\r\n className = '',\r\n onError,\r\n}) => {\r\n const [state, dispatch] = useReducer(widgetReducer, initialState);\r\n const { client, isInitialized, error: sdkError } = useSDK();\r\n const websocketRef = useRef<any>(null);\r\n\r\n const handlePreferencesChange = useCallback((preferences: any) => {\r\n dispatch({\r\n type: 'SET_PREFERENCES',\r\n payload: preferences,\r\n });\r\n }, []);\r\n\r\n const handleWidgetError = useCallback((error: Error) => {\r\n console.error('Widget error:', error);\r\n if (onError) {\r\n onError(error);\r\n }\r\n }, [onError]);\r\n\r\n const { isLoading: isPreferencesLoading, error: preferencesLoadError } = usePreferencesSync({\r\n onPreferencesLoaded: handlePreferencesChange,\r\n onError: handleWidgetError,\r\n });\r\n\r\n // Load available workflows to populate subscription preferences\r\n const { workflows, isLoading: isWorkflowsLoading } = useWorkflows();\r\n\r\n const { updatePreference, isSaving, error: preferencesError } = useLivePreferences({\r\n preferences: state.preferences,\r\n onPreferencesChange: handlePreferencesChange,\r\n onError: handleWidgetError,\r\n });\r\n\r\n // Merge workflows into preferences subscriptions when they load\r\n useEffect(() => {\r\n if (!isWorkflowsLoading && workflows.length > 0) {\r\n const updatedSubscriptions = workflows.map(wf => {\r\n // Find existing preference for this workflow\r\n const existing = state.preferences.subscriptions.find(s => s.workflowId === wf.workflowId);\r\n\r\n return existing || {\r\n workflowId: wf.workflowId,\r\n name: wf.name,\r\n enabled: true, // Default to enabled\r\n channels: {\r\n email: true,\r\n push: true,\r\n sms: false,\r\n inApp: true,\r\n },\r\n };\r\n });\r\n\r\n // Only update if different to avoid infinite loops\r\n if (JSON.stringify(updatedSubscriptions) !== JSON.stringify(state.preferences.subscriptions)) {\r\n dispatch({\r\n type: 'SET_PREFERENCES',\r\n payload: {\r\n ...state.preferences,\r\n subscriptions: updatedSubscriptions,\r\n },\r\n });\r\n }\r\n }\r\n }, [workflows, isWorkflowsLoading, state.preferences]);\r\n\r\n const handleWebSocketEvent = useCallback((event: any) => {\r\n try {\r\n const notificationMapper = createNotificationMapper();\r\n\r\n switch (event.type) {\r\n case 'notification_received': {\r\n const wsPayload = event.data;\r\n\r\n if (!notificationMapper.validateWebSocketPayload(wsPayload)) {\r\n console.error('Invalid WebSocket notification payload, skipping', wsPayload);\r\n break;\r\n }\r\n\r\n const mappedNotification = notificationMapper.toWidgetNotificationFromWebSocket(wsPayload);\r\n dispatch({\r\n type: 'ADD_NOTIFICATION',\r\n payload: mappedNotification,\r\n });\r\n break;\r\n }\r\n\r\n case 'notification_updated':\r\n dispatch({\r\n type: 'UPDATE_NOTIFICATION',\r\n payload: {\r\n id: event.data.id || event.data.notificationId,\r\n updates: event.data,\r\n },\r\n });\r\n break;\r\n\r\n case 'notification_deleted':\r\n dispatch({\r\n type: 'DELETE_NOTIFICATION',\r\n payload: event.data.id || event.data.notificationId,\r\n });\r\n break;\r\n\r\n case 'preferences_updated':\r\n dispatch({\r\n type: 'SET_PREFERENCES',\r\n payload: event.data,\r\n });\r\n break;\r\n\r\n default:\r\n console.log('Unknown WebSocket event type:', event.type);\r\n }\r\n } catch (error) {\r\n console.error('Error handling WebSocket event:', error);\r\n }\r\n }, []);\r\n\r\n const connectWebSocket = useCallback(async () => {\r\n if (!client || !isInitialized || websocketRef.current) return;\r\n\r\n try {\r\n dispatch({\r\n type: 'SET_WEBSOCKET_STATE',\r\n payload: { reconnecting: true },\r\n });\r\n\r\n const sdkConfig = (window as any).__notificationSDK?.config;\r\n if (!sdkConfig) {\r\n throw new Error('SDK configuration not available for WebSocket connection');\r\n }\r\n\r\n const baseUrl = client.getApiHost();\r\n const namespace = '/v1/notifications';\r\n const fullUrl = `${baseUrl}${namespace}`;\r\n\r\n console.log('Connecting to Socket.IO at:', fullUrl);\r\n\r\n const socket = ioClient(fullUrl, {\r\n query: {\r\n tenantId: sdkConfig.tenantId,\r\n subscriberId: sdkConfig.subscriberId,\r\n environmentId: sdkConfig.environmentId,\r\n },\r\n transports: ['websocket'],\r\n autoConnect: false,\r\n reconnection: true,\r\n reconnectionAttempts: 10,\r\n reconnectionDelay: 1000,\r\n reconnectionDelayMax: 5000,\r\n });\r\n\r\n websocketRef.current = socket;\r\n\r\n socket.on('notification', (payload: any) => {\r\n console.log('Received notification:', payload);\r\n handleWebSocketEvent({\r\n type: 'notification_received',\r\n data: payload,\r\n });\r\n });\r\n\r\n socket.on('connect', () => {\r\n console.log('Socket.IO connected successfully');\r\n dispatch({\r\n type: 'SET_WEBSOCKET_STATE',\r\n payload: { connected: true, reconnecting: false },\r\n });\r\n });\r\n\r\n socket.on('disconnect', (reason: any) => {\r\n console.log('Socket.IO disconnected:', reason);\r\n dispatch({\r\n type: 'SET_WEBSOCKET_STATE',\r\n payload: { connected: false, reconnecting: false },\r\n });\r\n });\r\n\r\n socket.on('reconnect_attempt', (attempt: any) => {\r\n console.log('Socket.IO reconnection attempt:', attempt);\r\n dispatch({\r\n type: 'SET_WEBSOCKET_STATE',\r\n payload: { connected: false, reconnecting: true },\r\n });\r\n });\r\n\r\n socket.on('connect_error', (error: any) => {\r\n console.error('Socket.IO connection error:', error);\r\n dispatch({\r\n type: 'SET_WEBSOCKET_STATE',\r\n payload: { connected: false, reconnecting: false },\r\n });\r\n if (onError) {\r\n onError(error);\r\n }\r\n });\r\n\r\n socket.connect();\r\n\r\n } catch (error) {\r\n console.error('Failed to connect WebSocket:', error);\r\n dispatch({\r\n type: 'SET_WEBSOCKET_STATE',\r\n payload: { connected: false, reconnecting: false },\r\n });\r\n if (onError) {\r\n onError(error as Error);\r\n }\r\n }\r\n }, [client, isInitialized, handleWebSocketEvent, onError]);\r\n\r\n const disconnectWebSocket = useCallback(() => {\r\n if (websocketRef.current) {\r\n try {\r\n if (websocketRef.current.disconnect) {\r\n websocketRef.current.disconnect();\r\n }\r\n websocketRef.current = null;\r\n dispatch({\r\n type: 'SET_WEBSOCKET_STATE',\r\n payload: { connected: false, reconnecting: false },\r\n });\r\n } catch (error) {\r\n console.error('Error disconnecting WebSocket:', error);\r\n }\r\n }\r\n }, []);\r\n\r\n const handleBellClick = useCallback(() => {\r\n dispatch({\r\n type: 'SET_UI_STATE',\r\n payload: { isOpen: !state.ui.isOpen },\r\n });\r\n }, [state.ui.isOpen]);\r\n\r\n const handlePopoverClose = useCallback(() => {\r\n dispatch({\r\n type: 'SET_UI_STATE',\r\n payload: { isOpen: false },\r\n });\r\n }, []);\r\n\r\n const handleViewChange = useCallback((view: 'notifications' | 'preferences') => {\r\n dispatch({\r\n type: 'SET_UI_STATE',\r\n payload: { currentView: view },\r\n });\r\n }, []);\r\n\r\n const handleNotificationAction = useCallback(async (id: string, action: any) => {\r\n if (!client || !isInitialized) {\r\n console.error('SDK not initialized');\r\n return;\r\n }\r\n\r\n const sdkConfig = (window as any).__notificationSDK?.config;\r\n if (!sdkConfig) {\r\n console.error('SDK configuration not available');\r\n return;\r\n }\r\n\r\n if (!id) {\r\n console.error('notificationId is required');\r\n throw new Error('notificationId is required');\r\n }\r\n\r\n try {\r\n switch (action.type) {\r\n case 'mark_read':\r\n await client.inbox.markAsRead(id, sdkConfig.tenantId, sdkConfig.environmentId, sdkConfig.subscriberId);\r\n break;\r\n case 'mark_unread':\r\n await client.inbox.markAsUnread(id, sdkConfig.tenantId, sdkConfig.environmentId, sdkConfig.subscriberId);\r\n break;\r\n case 'archive':\r\n await client.inbox.archive(id, sdkConfig.tenantId, sdkConfig.environmentId, sdkConfig.subscriberId);\r\n break;\r\n case 'delete':\r\n await client.inbox.delete(id, sdkConfig.tenantId, sdkConfig.environmentId, sdkConfig.subscriberId);\r\n break;\r\n default:\r\n if (action.handler) {\r\n await action.handler(id);\r\n }\r\n break;\r\n }\r\n\r\n switch (action.type) {\r\n case 'mark_read':\r\n dispatch({\r\n type: 'UPDATE_NOTIFICATION',\r\n payload: { id, updates: { isRead: true } },\r\n });\r\n break;\r\n case 'mark_unread':\r\n dispatch({\r\n type: 'UPDATE_NOTIFICATION',\r\n payload: { id, updates: { isRead: false } },\r\n });\r\n break;\r\n case 'archive':\r\n dispatch({\r\n type: 'UPDATE_NOTIFICATION',\r\n payload: { id, updates: { isArchived: true } },\r\n });\r\n break;\r\n case 'delete':\r\n dispatch({\r\n type: 'DELETE_NOTIFICATION',\r\n payload: id,\r\n });\r\n break;\r\n }\r\n } catch (error) {\r\n console.error('Error performing notification action:', error);\r\n if (onError) {\r\n onError(error as Error);\r\n }\r\n }\r\n }, [client]);\r\n\r\n useEffect(() => {\r\n if (!client || !isInitialized) return;\r\n\r\n const loadNotifications = async () => {\r\n try {\r\n dispatch({\r\n type: 'SET_UI_STATE',\r\n payload: { isLoading: true },\r\n });\r\n\r\n const sdkConfig = (window as any).__notificationSDK?.config;\r\n if (!sdkConfig) {\r\n throw new Error('SDK configuration not available');\r\n }\r\n\r\n const notificationMapper = createNotificationMapper();\r\n const response = await client.inbox.getRenderedNotifications(\r\n {\r\n channel: 'in_app',\r\n limit: 50,\r\n offset: 0,\r\n },\r\n sdkConfig.tenantId,\r\n sdkConfig.environmentId,\r\n sdkConfig.subscriberId,\r\n );\r\n\r\n const coreNotifications = (response?.items || []).map((item: any) =>\r\n notificationMapper.toWidgetNotification(item)\r\n );\r\n\r\n dispatch({\r\n type: 'SET_NOTIFICATIONS',\r\n payload: coreNotifications,\r\n });\r\n\r\n dispatch({\r\n type: 'SET_UI_STATE',\r\n payload: { isLoading: false, error: null },\r\n });\r\n } catch (error) {\r\n console.error('Failed to load notifications:', error);\r\n dispatch({\r\n type: 'SET_UI_STATE',\r\n payload: {\r\n isLoading: false,\r\n error: (error as Error)\r\n },\r\n });\r\n if (onError) {\r\n onError(error as Error);\r\n }\r\n }\r\n };\r\n\r\n loadNotifications();\r\n }, [client, isInitialized, onError]);\r\n\r\n useEffect(() => {\r\n if (client && isInitialized) {\r\n connectWebSocket();\r\n }\r\n\r\n return () => {\r\n disconnectWebSocket();\r\n };\r\n }, [client]);\r\n\r\n useEffect(() => {\r\n if (!client || !isInitialized) return;\r\n\r\n if (state.websocket.connected) return;\r\n\r\n const pollInterval = setInterval(async () => {\r\n try {\r\n const sdkConfig = (window as any).__notificationSDK?.config;\r\n if (!sdkConfig) {\r\n return;\r\n }\r\n\r\n const notificationMapper = createNotificationMapper();\r\n const response = await client.inbox.getRenderedNotifications(\r\n {\r\n channel: 'in_app',\r\n limit: 50,\r\n offset: 0,\r\n },\r\n sdkConfig.tenantId,\r\n sdkConfig.environmentId,\r\n sdkConfig.subscriberId,\r\n );\r\n\r\n const coreNotifications = (response?.items || []).map((item: any) =>\r\n notificationMapper.toWidgetNotification(item)\r\n );\r\n\r\n dispatch({\r\n type: 'SET_NOTIFICATIONS',\r\n payload: coreNotifications,\r\n });\r\n } catch (error) {\r\n console.error('Polling failed:', error);\r\n }\r\n }, 30000);\r\n\r\n return () => clearInterval(pollInterval);\r\n }, [client, state.websocket.connected]);\r\n\r\n useEffect(() => {\r\n const handleStorageChange = (event: StorageEvent) => {\r\n if (event.key === 'notification_widget_sync' && event.newValue) {\r\n try {\r\n const syncData = JSON.parse(event.newValue);\r\n handleWebSocketEvent(syncData);\r\n } catch (error) {\r\n console.error('Error parsing sync data:', error);\r\n }\r\n }\r\n };\r\n\r\n window.addEventListener('storage', handleStorageChange);\r\n return () => window.removeEventListener('storage', handleStorageChange);\r\n }, [handleWebSocketEvent]);\r\n\r\n useEffect(() => {\r\n dispatch({\r\n type: 'SET_UI_STATE',\r\n payload: { isLoading: isSaving },\r\n });\r\n }, [isSaving]);\r\n\r\n useEffect(() => {\r\n const error = sdkError || preferencesError || preferencesLoadError;\r\n if (error) {\r\n dispatch({\r\n type: 'SET_UI_STATE',\r\n payload: { error: error },\r\n });\r\n }\r\n }, [sdkError, preferencesError, preferencesLoadError]);\r\n\r\n if (!isInitialized && !sdkError) {\r\n return (\r\n <div\r\n className={`relative inline-block ${className}`}\r\n data-widget-size={size || 'small'}\r\n data-theme={theme}\r\n data-testid=\"notification-widget\"\r\n >\r\n <ComponentErrorBoundary componentName=\"BellComponent\">\r\n <BellComponent\r\n unreadCount={0}\r\n onClick={() => { }}\r\n size={size}\r\n disabled={true}\r\n />\r\n </ComponentErrorBoundary>\r\n </div>\r\n );\r\n }\r\n\r\n if (sdkError) {\r\n return (\r\n <div\r\n className={`relative inline-block ${className}`}\r\n data-widget-size={size || 'small'}\r\n data-theme={theme}\r\n data-testid=\"notification-widget\"\r\n >\r\n <ComponentErrorBoundary\r\n componentName=\"BellComponent\"\r\n fallback={\r\n <SDKConnectionFallback\r\n error={sdkError.message}\r\n onRetry={() => window.location.reload()}\r\n />\r\n }\r\n >\r\n <BellComponent\r\n unreadCount={0}\r\n onClick={() => { }}\r\n size={size}\r\n disabled={true}\r\n />\r\n </ComponentErrorBoundary>\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <div\r\n className={`relative inline-block ${className}`}\r\n data-widget-size={size || 'small'}\r\n data-theme={theme}\r\n data-testid=\"notification-widget\"\r\n >\r\n <ComponentErrorBoundary componentName=\"BellComponent\">\r\n <BellComponent\r\n unreadCount={state.unreadCount}\r\n onClick={handleBellClick}\r\n size={size}\r\n disabled={state.ui.isLoading}\r\n />\r\n </ComponentErrorBoundary>\r\n\r\n <ComponentErrorBoundary\r\n componentName=\"InboxPopover\"\r\n fallback={<LoadingFallback message=\"Unable to load notifications\" />}\r\n >\r\n <InboxPopover\r\n isOpen={state.ui.isOpen}\r\n onClose={handlePopoverClose}\r\n position={position}\r\n currentView={state.ui.currentView}\r\n onViewChange={handleViewChange}\r\n notifications={state.notifications}\r\n onNotificationAction={handleNotificationAction}\r\n preferences={state.preferences}\r\n onPreferenceChange={updatePreference}\r\n isPreferencesLoading={isSaving}\r\n />\r\n </ComponentErrorBoundary>\r\n </div>\r\n );\r\n};\r\n\r\nexport const NotificationWidget: React.FC<NotificationWidgetProps> = ({\r\n sdkConfig,\r\n ...props\r\n}) => {\r\n return (\r\n <NotificationWidgetErrorBoundary onError={props.onError}>\r\n <SDKProvider config={sdkConfig}>\r\n <NotificationWidgetInternal {...props} />\r\n </SDKProvider>\r\n </NotificationWidgetErrorBoundary>\r\n );\r\n};","export { NotificationWidget } from './components/NotificationWidget';\r\n\r\nexport { BellComponent } from './components/BellComponent';\r\nexport { InboxPopover } from './components/InboxPopover';\r\nexport { NotificationItem } from './components/NotificationItem';\r\nexport { PreferencesView } from './components/PreferencesView';\r\n\r\nexport { NotificationWidgetErrorBoundary } from './components/ErrorBoundary';\r\n\r\nexport type * from './types/core';\r\n\r\nexport type { Notification as SDKNotification, NotificationFilters } from '@edusight/notification-sdk';\r\n\r\nimport './styles/index.css';\r\n\r\nexport const VERSION = '3.0.0';\r\nexport const WIDGET_NAME = '@edusight/notification-widget';"],"names":["ErrorFallback","error","onRetry","jsxs","jsx","MdError","MdRefresh","NotificationWidgetErrorBoundary","Component","props","errorInfo","useNotificationsClient","usePreferencesSync","onPreferencesLoaded","onError","notificationClient","isLoading","setIsLoading","useState","setError","preferences","setPreferences","loadPreferences","useCallback","config","subscriberId","tenantId","environmentId","servicePreferences","mappedPreferences","workflowId","categoryPrefs","err","defaultPreferences","useEffect","useWorkflows","workflows","setWorkflows","loadWorkflows","mappedWorkflows","wf","SDKContext","createContext","useSDK","context","useContext","initialState","SDKProvider","children","sdkState","setSdkState","React","isMounted","existingSDK","client","NotificationClient","widgetReducer","state","action","n","newNotifications","updatedNotifications","filteredNotifications","NotificationWidgetInternal","position","size","theme","className","dispatch","useReducer","isInitialized","sdkError","websocketRef","useRef","handlePreferencesChange","handleWidgetError","preferencesLoadError","isWorkflowsLoading","updatePreference","isSaving","preferencesError","useLivePreferences","updatedSubscriptions","s","handleWebSocketEvent","event","notificationMapper","createNotificationMapper","wsPayload","mappedNotification","connectWebSocket","sdkConfig","fullUrl","socket","ioClient","payload","reason","attempt","disconnectWebSocket","handleBellClick","handlePopoverClose","handleViewChange","view","handleNotificationAction","id","coreNotifications","item","pollInterval","handleStorageChange","syncData","ComponentErrorBoundary","BellComponent","SDKConnectionFallback","LoadingFallback","InboxPopover","NotificationWidget","VERSION","WIDGET_NAME"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs.js","sources":["../src/components/ErrorBoundary.tsx","../src/hooks/usePreferencesSync.ts","../src/hooks/useWorkflows.ts","../src/components/NotificationWidget.tsx","../src/index.ts"],"sourcesContent":["import React, { Component, ErrorInfo, ReactNode } from 'react';\r\nimport { MdError, MdRefresh } from 'react-icons/md';\r\nimport { ErrorBoundaryState } from '../types/core';\r\n\r\ninterface ErrorBoundaryProps {\r\n children: ReactNode;\r\n onError?: (error: Error, errorInfo: ErrorInfo) => void;\r\n}\r\n\r\nconst ErrorFallback: React.FC<{\r\n error: Error | null;\r\n onRetry: () => void;\r\n}> = ({ error, onRetry }) => (\r\n <div\r\n className=\"p-4 bg-[var(--widget-error)]/10 border border-[var(--widget-error)]/20 rounded-lg\"\r\n role=\"alert\"\r\n data-testid=\"error-boundary-fallback\"\r\n >\r\n <div className=\"flex items-center mb-2\">\r\n <MdError\r\n className=\"w-6 h-6 text-[var(--widget-error)] mr-2\"\r\n aria-hidden=\"true\"\r\n />\r\n <h3\r\n className=\"text-sm font-medium text-[var(--widget-error)]\"\r\n >\r\n Something went wrong\r\n </h3>\r\n </div>\r\n\r\n <p\r\n className=\"text-sm mb-3 text-[var(--widget-error)]/80\"\r\n >\r\n The notification widget encountered an error and couldn't load properly.\r\n </p>\r\n\r\n {process.env.NODE_ENV === 'development' && error && (\r\n <details className=\"mb-3\">\r\n <summary\r\n className=\"text-xs cursor-pointer text-[var(--widget-error)] hover:text-[var(--widget-error)]/80 transition-colors\"\r\n >\r\n Error details (development only)\r\n </summary>\r\n <pre\r\n className=\"mt-2 text-xs bg-[var(--widget-error)]/5 p-2 rounded overflow-auto max-h-32 text-[var(--widget-error)]\"\r\n >\r\n {error.message}\r\n {error.stack && `\\n\\n${error.stack}`}\r\n </pre>\r\n </details>\r\n )}\r\n\r\n <button\r\n type=\"button\"\r\n className=\"inline-flex items-center px-3 py-2 border border-transparent text-sm leading-4 font-medium rounded-md text-[var(--widget-error)] bg-[var(--widget-error)]/10 hover:bg-[var(--widget-error)]/20 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-[var(--widget-error)] transition-colors\"\r\n onClick={onRetry}\r\n data-testid=\"error-retry-button\"\r\n >\r\n <MdRefresh\r\n className=\"mr-1 w-4 h-4\"\r\n aria-hidden=\"true\"\r\n />\r\n Try again\r\n </button>\r\n </div>\r\n);\r\n\r\nexport class NotificationWidgetErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {\r\n constructor(props: ErrorBoundaryProps) {\r\n super(props);\r\n this.state = {\r\n hasError: false,\r\n error: null,\r\n errorInfo: null,\r\n };\r\n }\r\n\r\n static getDerivedStateFromError(error: Error): Partial<ErrorBoundaryState> {\r\n return {\r\n hasError: true,\r\n error,\r\n };\r\n }\r\n\r\n componentDidCatch(error: Error, errorInfo: ErrorInfo) {\r\n this.setState({\r\n errorInfo,\r\n });\r\n\r\n console.error('NotificationWidget Error Boundary caught an error:', {\r\n message: error.message,\r\n stack: error.stack,\r\n componentStack: errorInfo.componentStack,\r\n timestamp: new Date().toISOString(),\r\n });\r\n\r\n if (this.props.onError) {\r\n this.props.onError(error, errorInfo);\r\n }\r\n }\r\n\r\n handleRetry = () => {\r\n this.setState({\r\n hasError: false,\r\n error: null,\r\n errorInfo: null,\r\n });\r\n };\r\n\r\n render() {\r\n if (this.state.hasError) {\r\n return (\r\n <ErrorFallback\r\n error={this.state.error}\r\n onRetry={this.handleRetry}\r\n />\r\n );\r\n }\r\n\r\n return this.props.children;\r\n }\r\n}\r\n\r\nexport const useErrorHandler = () => {\r\n return (error: Error, errorInfo?: ErrorInfo) => {\r\n console.error('Widget error:', {\r\n message: error.message,\r\n stack: error.stack,\r\n errorInfo,\r\n timestamp: new Date().toISOString(),\r\n });\r\n };\r\n};","import { useEffect, useState, useCallback } from 'react';\r\nimport { NotificationPreferences } from '../types/core';\r\n\r\nconst useNotificationsClient = () => {\r\n return (window as any).__notificationSDK?.client;\r\n};\r\n\r\nexport interface UsePreferencesSyncProps {\r\n onPreferencesLoaded: (preferences: NotificationPreferences) => void;\r\n onError?: (error: Error) => void;\r\n}\r\n\r\nexport interface UsePreferencesSyncResult {\r\n isLoading: boolean;\r\n error: Error | null;\r\n preferences: NotificationPreferences | null;\r\n}\r\n\r\nexport const usePreferencesSync = ({\r\n onPreferencesLoaded,\r\n onError,\r\n}: UsePreferencesSyncProps): UsePreferencesSyncResult => {\r\n const notificationClient = useNotificationsClient();\r\n const [isLoading, setIsLoading] = useState(true);\r\n const [error, setError] = useState<Error | null>(null);\r\n const [preferences, setPreferences] = useState<NotificationPreferences | null>(null);\r\n\r\n const loadPreferences = useCallback(async () => {\r\n try {\r\n setIsLoading(true);\r\n setError(null);\r\n\r\n if (!notificationClient) {\r\n throw new Error('Notification client not available');\r\n }\r\n\r\n const config = (window as any).__notificationSDK?.config;\r\n\r\n if (!config) {\r\n throw new Error('SDK configuration not available');\r\n }\r\n\r\n const { subscriberId, tenantId, environmentId } = config;\r\n\r\n if (!subscriberId || !tenantId || !environmentId) {\r\n throw new Error('SubscriberId, TenantId or EnvironmentId not available in config');\r\n }\r\n\r\n const servicePreferences = await notificationClient.preferences.get(\r\n tenantId,\r\n subscriberId,\r\n environmentId,\r\n );\r\n\r\n const mappedPreferences: NotificationPreferences = {\r\n channels: {\r\n email: servicePreferences.emailEnabled ?? true,\r\n push: servicePreferences.pushEnabled ?? true,\r\n sms: servicePreferences.smsEnabled ?? false,\r\n inApp: servicePreferences.inAppEnabled ?? true,\r\n },\r\n subscriptions: [],\r\n deliverySchedule: {\r\n timezone: 'UTC',\r\n quietHours: {\r\n start: servicePreferences.quietHoursStart ?? '22:00',\r\n end: servicePreferences.quietHoursEnd ?? '08:00',\r\n },\r\n weekdays: [true, true, true, true, true, false, false],\r\n },\r\n };\r\n\r\n if (servicePreferences.categories) {\r\n Object.entries(servicePreferences.categories).forEach(([workflowId, categoryPrefs]) => {\r\n mappedPreferences.subscriptions.push({\r\n workflowId,\r\n name: workflowId,\r\n enabled: true,\r\n channels: {\r\n email: (categoryPrefs as any).emailEnabled ?? true,\r\n push: (categoryPrefs as any).pushEnabled ?? true,\r\n sms: (categoryPrefs as any).smsEnabled ?? false,\r\n inApp: (categoryPrefs as any).inAppEnabled ?? true,\r\n },\r\n });\r\n });\r\n }\r\n\r\n setPreferences(mappedPreferences);\r\n onPreferencesLoaded(mappedPreferences);\r\n } catch (err: any) {\r\n const error = err instanceof Error ? err : new Error('Failed to load preferences');\r\n\r\n // If 404, it means preferences don't exist yet for this user. \r\n // We'll use defaults and suppress the error callback.\r\n const isNotFound = (err as any)?.response?.status === 404 || (err as any)?.status === 404;\r\n\r\n if (!isNotFound) {\r\n setError(error);\r\n onError?.(error);\r\n } else {\r\n console.warn('Preferences not found for user (404), using defaults.');\r\n }\r\n\r\n const defaultPreferences: NotificationPreferences = {\r\n channels: {\r\n email: true,\r\n push: true,\r\n sms: false,\r\n inApp: true,\r\n },\r\n subscriptions: [],\r\n deliverySchedule: {\r\n timezone: 'UTC',\r\n quietHours: {\r\n start: '22:00',\r\n end: '08:00',\r\n },\r\n weekdays: [true, true, true, true, true, false, false],\r\n },\r\n };\r\n setPreferences(defaultPreferences);\r\n onPreferencesLoaded(defaultPreferences);\r\n } finally {\r\n setIsLoading(false);\r\n }\r\n }, [notificationClient, onPreferencesLoaded, onError]);\r\n\r\n useEffect(() => {\r\n if (notificationClient) {\r\n loadPreferences();\r\n }\r\n }, [notificationClient, loadPreferences]);\r\n\r\n return {\r\n isLoading,\r\n error,\r\n preferences,\r\n };\r\n};\r\n","import { useEffect, useState, useCallback } from 'react';\r\n\r\nconst useNotificationsClient = () => {\r\n return (window as any).__notificationSDK?.client;\r\n};\r\n\r\nexport interface Workflow {\r\n workflowId: string;\r\n name: string;\r\n description?: string;\r\n}\r\n\r\nexport interface UseWorkflowsResult {\r\n workflows: Workflow[];\r\n isLoading: boolean;\r\n error: Error | null;\r\n refetch: () => void;\r\n}\r\n\r\nexport const useWorkflows = (): UseWorkflowsResult => {\r\n const notificationClient = useNotificationsClient();\r\n const [workflows, setWorkflows] = useState<Workflow[]>([]);\r\n const [isLoading, setIsLoading] = useState(true);\r\n const [error, setError] = useState<Error | null>(null);\r\n\r\n const loadWorkflows = useCallback(async () => {\r\n try {\r\n setIsLoading(true);\r\n setError(null);\r\n\r\n if (!notificationClient) {\r\n throw new Error('[useWorkflows] Notification client not available');\r\n }\r\n\r\n const config = (window as any).__notificationSDK?.config;\r\n\r\n if (!config) {\r\n throw new Error('[useWorkflows] SDK configuration not available');\r\n }\r\n\r\n const { tenantId, environmentId } = config;\r\n\r\n if (!tenantId || !environmentId) {\r\n throw new Error('[useWorkflows] TenantId or EnvironmentId not available in config');\r\n }\r\n\r\n const response = await notificationClient.workflows.list(\r\n { status: 'active' },\r\n tenantId,\r\n environmentId\r\n );\r\n\r\n const mappedWorkflows: Workflow[] = (response?.workflows || []).map((wf: any) => ({\r\n workflowId: wf.workflowId,\r\n name: wf.name || wf.workflowId,\r\n description: wf.description,\r\n }));\r\n\r\n setWorkflows(mappedWorkflows);\r\n } catch (err: any) {\r\n const error = err instanceof Error ? err : new Error('Failed to load workflows');\r\n\r\n console.warn('[useWorkflows] Failed to load workflows:', error);\r\n setError(error);\r\n setWorkflows([]);\r\n } finally {\r\n setIsLoading(false);\r\n }\r\n }, [notificationClient]);\r\n\r\n useEffect(() => {\r\n if (notificationClient) {\r\n loadWorkflows();\r\n }\r\n }, [notificationClient, loadWorkflows]);\r\n\r\n return {\r\n workflows,\r\n isLoading,\r\n error,\r\n refetch: loadWorkflows,\r\n };\r\n};\r\n","\r\nimport React, { useReducer, useEffect, useCallback, createContext, useContext, useRef } from 'react';\r\nimport { io as ioClient } from 'socket.io-client';\r\nimport { NotificationClient } from '@edusight/notification-sdk';\r\nimport { NotificationWidgetProps, WidgetState, WidgetAction, SDKConfiguration } from '../types/core';\r\nimport { BellComponent } from './BellComponent';\r\nimport { InboxPopover } from './InboxPopover';\r\nimport { NotificationWidgetErrorBoundary } from './ErrorBoundary';\r\nimport { ComponentErrorBoundary } from './ComponentErrorBoundary';\r\nimport { SDKConnectionFallback, LoadingFallback } from './FallbackComponents';\r\nimport { useLivePreferences } from '../hooks/useLivePreferences';\r\nimport { usePreferencesSync } from '../hooks/usePreferencesSync';\r\nimport { useWorkflows } from '../hooks/useWorkflows';\r\nimport { createNotificationMapper } from '../utils/notification-mapper';\r\n\r\ninterface SDKContextType {\r\n client: any;\r\n isInitialized: boolean;\r\n error: Error | null;\r\n}\r\n\r\nconst SDKContext = createContext<SDKContextType | null>(null);\r\n\r\nexport const useSDK = () => {\r\n const context = useContext(SDKContext);\r\n if (!context) {\r\n throw new Error('useSDK must be used within a NotificationWidget');\r\n }\r\n return context;\r\n};\r\n\r\nconst initialState: WidgetState = {\r\n notifications: [],\r\n unreadCount: 0,\r\n preferences: {\r\n channels: {\r\n email: true,\r\n push: true,\r\n sms: false,\r\n inApp: true,\r\n },\r\n subscriptions: [],\r\n deliverySchedule: {\r\n timezone: 'UTC',\r\n quietHours: {\r\n start: '22:00',\r\n end: '08:00',\r\n },\r\n weekdays: [true, true, true, true, true, false, false],\r\n },\r\n },\r\n ui: {\r\n isOpen: false,\r\n currentView: 'notifications',\r\n selectedNotifications: [],\r\n isLoading: false,\r\n error: null,\r\n },\r\n websocket: {\r\n connected: false,\r\n reconnecting: false,\r\n },\r\n};\r\n\r\nconst SDKProvider: React.FC<{ config: SDKConfiguration; children: React.ReactNode }> = ({\r\n config,\r\n children,\r\n}) => {\r\n const [sdkState, setSdkState] = React.useState<SDKContextType>({\r\n client: null,\r\n isInitialized: false,\r\n error: null,\r\n });\r\n\r\n useEffect(() => {\r\n let isMounted = true;\r\n\r\n const initializeSDK = async () => {\r\n try {\r\n const existingSDK = (window as any).__notificationSDK;\r\n\r\n // Check if we can reuse the existing SDK instance\r\n if (existingSDK?.client) {\r\n // Compare new config with existing config to determine if we need to re-initialize\r\n // We use simple JSON stringify as configs are simple objects with strings/numbers\r\n const isConfigMatch = JSON.stringify(existingSDK.config) === JSON.stringify(config);\r\n\r\n if (isConfigMatch) {\r\n if (isMounted) {\r\n setSdkState({\r\n client: existingSDK.client,\r\n isInitialized: true,\r\n error: null,\r\n });\r\n }\r\n return;\r\n } else {\r\n console.log('[NotificationWidget] Config changed, re-initializing SDK', { old: existingSDK.config, new: config });\r\n }\r\n }\r\n\r\n const client = new NotificationClient({\r\n apiUrl: config.baseUrl,\r\n apiKey: config.apiKey,\r\n tenantId: config.tenantId,\r\n environmentId: config.environmentId,\r\n });\r\n\r\n (window as any).__notificationSDK = { client, config };\r\n\r\n if (isMounted) {\r\n setSdkState({\r\n client,\r\n isInitialized: true,\r\n error: null,\r\n });\r\n }\r\n } catch (error) {\r\n console.error('Failed to initialize SDK:', error);\r\n if (isMounted) {\r\n setSdkState({\r\n client: null,\r\n isInitialized: false,\r\n error: error as Error,\r\n });\r\n }\r\n }\r\n };\r\n\r\n initializeSDK();\r\n\r\n return () => {\r\n isMounted = false;\r\n };\r\n }, [config]);\r\n\r\n return (\r\n <SDKContext.Provider value={sdkState}>\r\n {children}\r\n </SDKContext.Provider>\r\n );\r\n};\r\n\r\nconst widgetReducer = (state: WidgetState, action: WidgetAction): WidgetState => {\r\n switch (action.type) {\r\n case 'SET_NOTIFICATIONS':\r\n return {\r\n ...state,\r\n notifications: action.payload,\r\n unreadCount: action.payload.filter(n => !n.isRead).length,\r\n };\r\n\r\n case 'ADD_NOTIFICATION':\r\n const newNotifications = [action.payload, ...state.notifications];\r\n return {\r\n ...state,\r\n notifications: newNotifications,\r\n unreadCount: newNotifications.filter(n => !n.isRead).length,\r\n };\r\n\r\n case 'UPDATE_NOTIFICATION':\r\n const updatedNotifications = state.notifications.map(n =>\r\n n.id === action.payload.id ? { ...n, ...action.payload.updates } : n\r\n );\r\n return {\r\n ...state,\r\n notifications: updatedNotifications,\r\n unreadCount: updatedNotifications.filter(n => !n.isRead).length,\r\n };\r\n\r\n case 'DELETE_NOTIFICATION':\r\n const filteredNotifications = state.notifications.filter(n => n.id !== action.payload);\r\n return {\r\n ...state,\r\n notifications: filteredNotifications,\r\n unreadCount: filteredNotifications.filter(n => !n.isRead).length,\r\n };\r\n\r\n case 'SET_PREFERENCES':\r\n return {\r\n ...state,\r\n preferences: action.payload,\r\n };\r\n\r\n case 'SET_UI_STATE':\r\n return {\r\n ...state,\r\n ui: { ...state.ui, ...action.payload },\r\n };\r\n\r\n case 'SET_WEBSOCKET_STATE':\r\n return {\r\n ...state,\r\n websocket: { ...state.websocket, ...action.payload },\r\n };\r\n\r\n default:\r\n return state;\r\n }\r\n};\r\n\r\nconst NotificationWidgetInternal: React.FC<Omit<NotificationWidgetProps, 'sdkConfig'>> = ({\r\n position = 'right',\r\n size = 'medium',\r\n theme = 'light',\r\n className = '',\r\n onError,\r\n}) => {\r\n const [state, dispatch] = useReducer(widgetReducer, initialState);\r\n const { client, isInitialized, error: sdkError } = useSDK();\r\n const websocketRef = useRef<any>(null);\r\n\r\n const handlePreferencesChange = useCallback((preferences: any) => {\r\n dispatch({\r\n type: 'SET_PREFERENCES',\r\n payload: preferences,\r\n });\r\n }, []);\r\n\r\n const handleWidgetError = useCallback((error: Error) => {\r\n console.error('Widget error:', error);\r\n if (onError) {\r\n onError(error);\r\n }\r\n }, [onError]);\r\n\r\n const { isLoading: isPreferencesLoading, error: preferencesLoadError } = usePreferencesSync({\r\n onPreferencesLoaded: handlePreferencesChange,\r\n onError: handleWidgetError,\r\n });\r\n\r\n // Load available workflows to populate subscription preferences\r\n const { workflows, isLoading: isWorkflowsLoading } = useWorkflows();\r\n\r\n const { updatePreference, isSaving, error: preferencesError } = useLivePreferences({\r\n preferences: state.preferences,\r\n onPreferencesChange: handlePreferencesChange,\r\n onError: handleWidgetError,\r\n });\r\n\r\n // Merge workflows into preferences subscriptions when they load\r\n useEffect(() => {\r\n if (!isWorkflowsLoading && workflows.length > 0) {\r\n const updatedSubscriptions = workflows.map(wf => {\r\n // Find existing preference for this workflow\r\n const existing = state.preferences.subscriptions.find(s => s.workflowId === wf.workflowId);\r\n\r\n return existing || {\r\n workflowId: wf.workflowId,\r\n name: wf.name,\r\n enabled: true, // Default to enabled\r\n channels: {\r\n email: true,\r\n push: true,\r\n sms: false,\r\n inApp: true,\r\n },\r\n };\r\n });\r\n\r\n // Only update if different to avoid infinite loops\r\n if (JSON.stringify(updatedSubscriptions) !== JSON.stringify(state.preferences.subscriptions)) {\r\n dispatch({\r\n type: 'SET_PREFERENCES',\r\n payload: {\r\n ...state.preferences,\r\n subscriptions: updatedSubscriptions,\r\n },\r\n });\r\n }\r\n }\r\n }, [workflows, isWorkflowsLoading, state.preferences]);\r\n\r\n const handleWebSocketEvent = useCallback((event: any) => {\r\n try {\r\n const notificationMapper = createNotificationMapper();\r\n\r\n switch (event.type) {\r\n case 'notification_received': {\r\n const wsPayload = event.data;\r\n\r\n if (!notificationMapper.validateWebSocketPayload(wsPayload)) {\r\n console.error('Invalid WebSocket notification payload, skipping', wsPayload);\r\n break;\r\n }\r\n\r\n const mappedNotification = notificationMapper.toWidgetNotificationFromWebSocket(wsPayload);\r\n dispatch({\r\n type: 'ADD_NOTIFICATION',\r\n payload: mappedNotification,\r\n });\r\n break;\r\n }\r\n\r\n case 'notification_updated':\r\n dispatch({\r\n type: 'UPDATE_NOTIFICATION',\r\n payload: {\r\n id: event.data.id || event.data.notificationId,\r\n updates: event.data,\r\n },\r\n });\r\n break;\r\n\r\n case 'notification_deleted':\r\n dispatch({\r\n type: 'DELETE_NOTIFICATION',\r\n payload: event.data.id || event.data.notificationId,\r\n });\r\n break;\r\n\r\n case 'preferences_updated':\r\n dispatch({\r\n type: 'SET_PREFERENCES',\r\n payload: event.data,\r\n });\r\n break;\r\n\r\n default:\r\n console.log('Unknown WebSocket event type:', event.type);\r\n }\r\n } catch (error) {\r\n console.error('Error handling WebSocket event:', error);\r\n }\r\n }, []);\r\n\r\n const connectWebSocket = useCallback(async () => {\r\n if (!client || !isInitialized || websocketRef.current) return;\r\n\r\n try {\r\n dispatch({\r\n type: 'SET_WEBSOCKET_STATE',\r\n payload: { reconnecting: true },\r\n });\r\n\r\n const sdkConfig = (window as any).__notificationSDK?.config;\r\n if (!sdkConfig) {\r\n throw new Error('SDK configuration not available for WebSocket connection');\r\n }\r\n\r\n const baseUrl = client.getApiHost();\r\n const namespace = '/v1/notifications';\r\n const fullUrl = `${baseUrl}${namespace}`;\r\n\r\n console.log('Connecting to Socket.IO at:', fullUrl);\r\n\r\n const socket = ioClient(fullUrl, {\r\n query: {\r\n tenantId: sdkConfig.tenantId,\r\n subscriberId: sdkConfig.subscriberId,\r\n environmentId: sdkConfig.environmentId,\r\n },\r\n transports: ['websocket'],\r\n autoConnect: false,\r\n reconnection: true,\r\n reconnectionAttempts: 10,\r\n reconnectionDelay: 1000,\r\n reconnectionDelayMax: 5000,\r\n });\r\n\r\n websocketRef.current = socket;\r\n\r\n socket.on('notification', (payload: any) => {\r\n console.log('Received notification:', payload);\r\n handleWebSocketEvent({\r\n type: 'notification_received',\r\n data: payload,\r\n });\r\n });\r\n\r\n socket.on('connect', () => {\r\n console.log('Socket.IO connected successfully');\r\n dispatch({\r\n type: 'SET_WEBSOCKET_STATE',\r\n payload: { connected: true, reconnecting: false },\r\n });\r\n });\r\n\r\n socket.on('disconnect', (reason: any) => {\r\n console.log('Socket.IO disconnected:', reason);\r\n dispatch({\r\n type: 'SET_WEBSOCKET_STATE',\r\n payload: { connected: false, reconnecting: false },\r\n });\r\n });\r\n\r\n socket.on('reconnect_attempt', (attempt: any) => {\r\n console.log('Socket.IO reconnection attempt:', attempt);\r\n dispatch({\r\n type: 'SET_WEBSOCKET_STATE',\r\n payload: { connected: false, reconnecting: true },\r\n });\r\n });\r\n\r\n socket.on('connect_error', (error: any) => {\r\n console.error('Socket.IO connection error:', error);\r\n dispatch({\r\n type: 'SET_WEBSOCKET_STATE',\r\n payload: { connected: false, reconnecting: false },\r\n });\r\n if (onError) {\r\n onError(error);\r\n }\r\n });\r\n\r\n socket.connect();\r\n\r\n } catch (error) {\r\n console.error('Failed to connect WebSocket:', error);\r\n dispatch({\r\n type: 'SET_WEBSOCKET_STATE',\r\n payload: { connected: false, reconnecting: false },\r\n });\r\n if (onError) {\r\n onError(error as Error);\r\n }\r\n }\r\n }, [client, isInitialized, handleWebSocketEvent, onError]);\r\n\r\n const disconnectWebSocket = useCallback(() => {\r\n if (websocketRef.current) {\r\n try {\r\n if (websocketRef.current.disconnect) {\r\n websocketRef.current.disconnect();\r\n }\r\n websocketRef.current = null;\r\n dispatch({\r\n type: 'SET_WEBSOCKET_STATE',\r\n payload: { connected: false, reconnecting: false },\r\n });\r\n } catch (error) {\r\n console.error('Error disconnecting WebSocket:', error);\r\n }\r\n }\r\n }, []);\r\n\r\n const handleBellClick = useCallback(() => {\r\n dispatch({\r\n type: 'SET_UI_STATE',\r\n payload: { isOpen: !state.ui.isOpen },\r\n });\r\n }, [state.ui.isOpen]);\r\n\r\n const handlePopoverClose = useCallback(() => {\r\n dispatch({\r\n type: 'SET_UI_STATE',\r\n payload: { isOpen: false },\r\n });\r\n }, []);\r\n\r\n const handleViewChange = useCallback((view: 'notifications' | 'preferences') => {\r\n dispatch({\r\n type: 'SET_UI_STATE',\r\n payload: { currentView: view },\r\n });\r\n }, []);\r\n\r\n const handleNotificationAction = useCallback(async (id: string, action: any) => {\r\n if (!client || !isInitialized) {\r\n console.error('SDK not initialized');\r\n return;\r\n }\r\n\r\n const sdkConfig = (window as any).__notificationSDK?.config;\r\n if (!sdkConfig) {\r\n console.error('SDK configuration not available');\r\n return;\r\n }\r\n\r\n if (!id) {\r\n console.error('notificationId is required');\r\n throw new Error('notificationId is required');\r\n }\r\n\r\n try {\r\n switch (action.type) {\r\n case 'mark_read':\r\n await client.inbox.markAsRead(id, sdkConfig.tenantId, sdkConfig.environmentId, sdkConfig.subscriberId);\r\n break;\r\n case 'mark_unread':\r\n await client.inbox.markAsUnread(id, sdkConfig.tenantId, sdkConfig.environmentId, sdkConfig.subscriberId);\r\n break;\r\n case 'archive':\r\n await client.inbox.archive(id, sdkConfig.tenantId, sdkConfig.environmentId, sdkConfig.subscriberId);\r\n break;\r\n case 'delete':\r\n await client.inbox.delete(id, sdkConfig.tenantId, sdkConfig.environmentId, sdkConfig.subscriberId);\r\n break;\r\n default:\r\n if (action.handler) {\r\n await action.handler(id);\r\n }\r\n break;\r\n }\r\n\r\n switch (action.type) {\r\n case 'mark_read':\r\n dispatch({\r\n type: 'UPDATE_NOTIFICATION',\r\n payload: { id, updates: { isRead: true } },\r\n });\r\n break;\r\n case 'mark_unread':\r\n dispatch({\r\n type: 'UPDATE_NOTIFICATION',\r\n payload: { id, updates: { isRead: false } },\r\n });\r\n break;\r\n case 'archive':\r\n dispatch({\r\n type: 'UPDATE_NOTIFICATION',\r\n payload: { id, updates: { isArchived: true } },\r\n });\r\n break;\r\n case 'delete':\r\n dispatch({\r\n type: 'DELETE_NOTIFICATION',\r\n payload: id,\r\n });\r\n break;\r\n }\r\n } catch (error) {\r\n console.error('Error performing notification action:', error);\r\n if (onError) {\r\n onError(error as Error);\r\n }\r\n }\r\n }, [client]);\r\n\r\n useEffect(() => {\r\n if (!client || !isInitialized) return;\r\n\r\n const loadNotifications = async () => {\r\n try {\r\n dispatch({\r\n type: 'SET_UI_STATE',\r\n payload: { isLoading: true },\r\n });\r\n\r\n const sdkConfig = (window as any).__notificationSDK?.config;\r\n if (!sdkConfig) {\r\n throw new Error('SDK configuration not available');\r\n }\r\n\r\n const notificationMapper = createNotificationMapper();\r\n const response = await client.inbox.getRenderedNotifications(\r\n {\r\n channel: 'in_app',\r\n limit: 50,\r\n offset: 0,\r\n },\r\n sdkConfig.tenantId,\r\n sdkConfig.environmentId,\r\n sdkConfig.subscriberId,\r\n );\r\n\r\n const coreNotifications = (response?.items || []).map((item: any) =>\r\n notificationMapper.toWidgetNotification(item)\r\n );\r\n\r\n dispatch({\r\n type: 'SET_NOTIFICATIONS',\r\n payload: coreNotifications,\r\n });\r\n\r\n dispatch({\r\n type: 'SET_UI_STATE',\r\n payload: { isLoading: false, error: null },\r\n });\r\n } catch (error) {\r\n console.error('Failed to load notifications:', error);\r\n dispatch({\r\n type: 'SET_UI_STATE',\r\n payload: {\r\n isLoading: false,\r\n error: (error as Error)\r\n },\r\n });\r\n if (onError) {\r\n onError(error as Error);\r\n }\r\n }\r\n };\r\n\r\n loadNotifications();\r\n }, [client, isInitialized, onError]);\r\n\r\n useEffect(() => {\r\n if (client && isInitialized) {\r\n connectWebSocket();\r\n }\r\n\r\n return () => {\r\n disconnectWebSocket();\r\n };\r\n }, [client]);\r\n\r\n useEffect(() => {\r\n if (!client || !isInitialized) return;\r\n\r\n if (state.websocket.connected) return;\r\n\r\n const pollInterval = setInterval(async () => {\r\n try {\r\n const sdkConfig = (window as any).__notificationSDK?.config;\r\n if (!sdkConfig) {\r\n return;\r\n }\r\n\r\n const notificationMapper = createNotificationMapper();\r\n const response = await client.inbox.getRenderedNotifications(\r\n {\r\n channel: 'in_app',\r\n limit: 50,\r\n offset: 0,\r\n },\r\n sdkConfig.tenantId,\r\n sdkConfig.environmentId,\r\n sdkConfig.subscriberId,\r\n );\r\n\r\n const coreNotifications = (response?.items || []).map((item: any) =>\r\n notificationMapper.toWidgetNotification(item)\r\n );\r\n\r\n dispatch({\r\n type: 'SET_NOTIFICATIONS',\r\n payload: coreNotifications,\r\n });\r\n } catch (error) {\r\n console.error('Polling failed:', error);\r\n }\r\n }, 30000);\r\n\r\n return () => clearInterval(pollInterval);\r\n }, [client, state.websocket.connected]);\r\n\r\n useEffect(() => {\r\n const handleStorageChange = (event: StorageEvent) => {\r\n if (event.key === 'notification_widget_sync' && event.newValue) {\r\n try {\r\n const syncData = JSON.parse(event.newValue);\r\n handleWebSocketEvent(syncData);\r\n } catch (error) {\r\n console.error('Error parsing sync data:', error);\r\n }\r\n }\r\n };\r\n\r\n window.addEventListener('storage', handleStorageChange);\r\n return () => window.removeEventListener('storage', handleStorageChange);\r\n }, [handleWebSocketEvent]);\r\n\r\n useEffect(() => {\r\n dispatch({\r\n type: 'SET_UI_STATE',\r\n payload: { isLoading: isSaving },\r\n });\r\n }, [isSaving]);\r\n\r\n useEffect(() => {\r\n const error = sdkError || preferencesError || preferencesLoadError;\r\n if (error) {\r\n dispatch({\r\n type: 'SET_UI_STATE',\r\n payload: { error: error },\r\n });\r\n }\r\n }, [sdkError, preferencesError, preferencesLoadError]);\r\n\r\n if (!isInitialized && !sdkError) {\r\n return (\r\n <div\r\n className={`mx-widget-root relative inline-block ${className}`}\r\n data-mx-widget=\"root\"\r\n data-widget-size={size || 'small'}\r\n data-theme={theme}\r\n data-testid=\"notification-widget\"\r\n >\r\n <ComponentErrorBoundary componentName=\"BellComponent\">\r\n <BellComponent\r\n unreadCount={0}\r\n onClick={() => { }}\r\n size={size}\r\n disabled={true}\r\n />\r\n </ComponentErrorBoundary>\r\n </div>\r\n );\r\n }\r\n\r\n if (sdkError) {\r\n return (\r\n <div\r\n className={`mx-widget-root relative inline-block ${className}`}\r\n data-mx-widget=\"root\"\r\n data-widget-size={size || 'small'}\r\n data-theme={theme}\r\n data-testid=\"notification-widget\"\r\n >\r\n <ComponentErrorBoundary\r\n componentName=\"BellComponent\"\r\n fallback={\r\n <SDKConnectionFallback\r\n error={sdkError.message}\r\n onRetry={() => window.location.reload()}\r\n />\r\n }\r\n >\r\n <BellComponent\r\n unreadCount={0}\r\n onClick={() => { }}\r\n size={size}\r\n disabled={true}\r\n />\r\n </ComponentErrorBoundary>\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <div\r\n className={`mx-widget-root relative inline-block ${className}`}\r\n data-mx-widget=\"root\"\r\n data-widget-size={size || 'small'}\r\n data-theme={theme}\r\n data-testid=\"notification-widget\"\r\n >\r\n <ComponentErrorBoundary componentName=\"BellComponent\">\r\n <BellComponent\r\n unreadCount={state.unreadCount}\r\n onClick={handleBellClick}\r\n size={size}\r\n disabled={state.ui.isLoading}\r\n />\r\n </ComponentErrorBoundary>\r\n\r\n <ComponentErrorBoundary\r\n componentName=\"InboxPopover\"\r\n fallback={<LoadingFallback message=\"Unable to load notifications\" />}\r\n >\r\n <InboxPopover\r\n isOpen={state.ui.isOpen}\r\n onClose={handlePopoverClose}\r\n position={position}\r\n currentView={state.ui.currentView}\r\n onViewChange={handleViewChange}\r\n notifications={state.notifications}\r\n onNotificationAction={handleNotificationAction}\r\n preferences={state.preferences}\r\n onPreferenceChange={updatePreference}\r\n isPreferencesLoading={isSaving}\r\n />\r\n </ComponentErrorBoundary>\r\n </div>\r\n );\r\n};\r\n\r\nexport const NotificationWidget: React.FC<NotificationWidgetProps> = ({\r\n sdkConfig,\r\n ...props\r\n}) => {\r\n return (\r\n <NotificationWidgetErrorBoundary onError={props.onError}>\r\n <SDKProvider config={sdkConfig}>\r\n <NotificationWidgetInternal {...props} />\r\n </SDKProvider>\r\n </NotificationWidgetErrorBoundary>\r\n );\r\n};","export { NotificationWidget } from './components/NotificationWidget';\r\n\r\nexport { BellComponent } from './components/BellComponent';\r\nexport { InboxPopover } from './components/InboxPopover';\r\nexport { NotificationItem } from './components/NotificationItem';\r\nexport { PreferencesView } from './components/PreferencesView';\r\n\r\nexport { NotificationWidgetErrorBoundary } from './components/ErrorBoundary';\r\n\r\nexport type * from './types/core';\r\n\r\nexport type { Notification as SDKNotification, NotificationFilters } from '@edusight/notification-sdk';\r\n\r\nimport '../src/styles/index.css';\r\n\r\nexport const VERSION = '3.0.0';\r\nexport const WIDGET_NAME = '@edusight/notification-widget';"],"names":["ErrorFallback","error","onRetry","jsxs","jsx","MdError","MdRefresh","NotificationWidgetErrorBoundary","Component","props","errorInfo","useNotificationsClient","usePreferencesSync","onPreferencesLoaded","onError","notificationClient","isLoading","setIsLoading","useState","setError","preferences","setPreferences","loadPreferences","useCallback","config","subscriberId","tenantId","environmentId","servicePreferences","mappedPreferences","workflowId","categoryPrefs","err","defaultPreferences","useEffect","useWorkflows","workflows","setWorkflows","loadWorkflows","mappedWorkflows","wf","SDKContext","createContext","useSDK","context","useContext","initialState","SDKProvider","children","sdkState","setSdkState","React","isMounted","existingSDK","client","NotificationClient","widgetReducer","state","action","n","newNotifications","updatedNotifications","filteredNotifications","NotificationWidgetInternal","position","size","theme","className","dispatch","useReducer","isInitialized","sdkError","websocketRef","useRef","handlePreferencesChange","handleWidgetError","preferencesLoadError","isWorkflowsLoading","updatePreference","isSaving","preferencesError","useLivePreferences","updatedSubscriptions","s","handleWebSocketEvent","event","notificationMapper","createNotificationMapper","wsPayload","mappedNotification","connectWebSocket","sdkConfig","fullUrl","socket","ioClient","payload","reason","attempt","disconnectWebSocket","handleBellClick","handlePopoverClose","handleViewChange","view","handleNotificationAction","id","coreNotifications","item","pollInterval","handleStorageChange","syncData","ComponentErrorBoundary","BellComponent","SDKConnectionFallback","LoadingFallback","InboxPopover","NotificationWidget","VERSION","WIDGET_NAME"],"mappings":"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"}
|
package/dist/index.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
*,:before,:after{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}:before,:after{--tw-content: ""}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:var(--widget-font-family, -apple-system),BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}:root{--widget-primary: #6366f1;--widget-primary-hover: #4f46e5;--widget-primary-light: #eef2ff;--widget-background: #ffffff;--widget-bg: var(--widget-background);--widget-bg-secondary: #f9fafb;--widget-bg-hover: #f3f4f6;--widget-hover: var(--widget-bg-hover);--widget-text: #111827;--widget-text-secondary: #6b7280;--widget-text-tertiary: #9ca3af;--widget-border: #e5e7eb;--widget-border-light: #f3f4f6;--widget-unread-bg: #eff6ff;--widget-unread-dot: #3b82f6;--widget-unread-badge-bg: #ef4444;--widget-success: #10b981;--widget-warning: #f59e0b;--widget-error: #ef4444;--widget-font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;--widget-popover-width: 480px;--widget-popover-max-height: 600px;--widget-shadow-sm: 0 1px 2px 0 rgb(0 0 0 / .05);--widget-shadow: 0 4px 6px -1px rgb(0 0 0 / .1), 0 2px 4px -2px rgb(0 0 0 / .1);--widget-shadow-lg: 0 10px 15px -3px rgb(0 0 0 / .1), 0 4px 6px -4px rgb(0 0 0 / .1);--widget-shadow-xl: 0 20px 25px -5px rgb(0 0 0 / .1), 0 8px 10px -6px rgb(0 0 0 / .1)}[data-theme=dark]{--widget-background: #1f2937;--widget-bg: var(--widget-background);--widget-bg-secondary: #111827;--widget-bg-hover: #374151;--widget-hover: var(--widget-bg-hover);--widget-text: #f9fafb;--widget-text-secondary: #d1d5db;--widget-text-tertiary: #9ca3af;--widget-border: #374151;--widget-border-light: #1f2937;--widget-primary: #818cf8;--widget-primary-hover: #a5b4fc;--widget-primary-light: rgba(99, 102, 241, .1);--widget-unread-bg: rgba(59, 130, 246, .1);--widget-unread-dot: #60a5fa;--widget-shadow-sm: 0 1px 2px 0 rgb(0 0 0 / .3);--widget-shadow: 0 4px 6px -1px rgb(0 0 0 / .3), 0 2px 4px -2px rgb(0 0 0 / .3);--widget-shadow-lg: 0 10px 15px -3px rgb(0 0 0 / .4), 0 4px 6px -4px rgb(0 0 0 / .4);--widget-shadow-xl: 0 20px 25px -5px rgb(0 0 0 / .5), 0 8px 10px -6px rgb(0 0 0 / .5)}.notification-item{height:var(--widget-item-height, 80px);display:flex;align-items:flex-start;transition:background-color .2s ease-in-out;cursor:pointer}.notification-item:hover{background-color:var(--widget-hover, #f9fafb)}.notification-item.unread{background-color:var(--widget-unread-bg, #f0f4ff)}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.pointer-events-none{pointer-events:none}.static{position:static}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.inset-0{inset:0}.inset-y-0{top:0;bottom:0}.-right-2{right:-16px}.-top-2{top:-16px}.left-0{left:0}.right-0{right:0}.top-full{top:100%}.z-10{z-index:10}.z-40{z-index:40}.z-50{z-index:50}.col-span-2{grid-column:span 2 / span 2}.mx-auto{margin-left:auto;margin-right:auto}.mb-0\.5{margin-bottom:4px}.mb-2{margin-bottom:16px}.mb-3{margin-bottom:24px}.mb-4{margin-bottom:32px}.ml-1{margin-left:8px}.mr-1{margin-right:8px}.mr-2{margin-right:16px}.mt-1\.5{margin-top:12px}.mt-2{margin-top:16px}.line-clamp-2{overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2}.inline-block{display:inline-block}.flex{display:flex}.inline-flex{display:inline-flex}.grid{display:grid}.hidden{display:none}.h-10{height:80px}.h-12{height:96px}.h-2{height:16px}.h-3{height:24px}.h-4{height:32px}.h-5{height:40px}.h-6{height:48px}.h-7{height:1.75rem}.h-8{height:64px}.h-\[16px\]{height:16px}.h-full{height:100%}.max-h-32{max-height:8rem}.max-h-\[calc\(var\(--widget-popover-max-height\)-200px\)\]{max-height:calc(var(--widget-popover-max-height) - 200px)}.max-h-\[var\(--widget-popover-max-height\,580px\)\]{max-height:var(--widget-popover-max-height,580px)}.min-h-\[20px\]{min-height:20px}.w-10{width:80px}.w-12{width:96px}.w-16{width:128px}.w-2{width:16px}.w-3\/4{width:75%}.w-4{width:32px}.w-5{width:40px}.w-5\/6{width:83.333333%}.w-6{width:48px}.w-7{width:1.75rem}.w-8{width:64px}.w-9{width:2.25rem}.w-\[16px\]{width:16px}.w-\[88px\]{width:88px}.w-\[var\(--widget-popover-width\,400px\)\]{width:var(--widget-popover-width,400px)}.w-full{width:100%}.min-w-0{min-width:0px}.min-w-\[20rem\]{min-width:20rem}.flex-1{flex:1 1 0%}.flex-shrink-0{flex-shrink:0}.origin-top-left{transform-origin:top left}.origin-top-right{transform-origin:top right}.-translate-x-1\/2{--tw-translate-x: -50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.-translate-x-full{--tw-translate-x: -100%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.-translate-y-1\/2{--tw-translate-y: -50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.-translate-y-full{--tw-translate-y: -100%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-x-0{--tw-translate-x: 0px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-x-4{--tw-translate-x: 32px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-y-0{--tw-translate-y: 0px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.rotate-180{--tw-rotate: 180deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}@keyframes pulse{50%{opacity:.5}}.animate-pulse{animation:pulse 2s cubic-bezier(.4,0,.6,1) infinite}@keyframes spin{to{transform:rotate(360deg)}}.animate-spin{animation:spin 1s linear infinite}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.grid-cols-\[auto_1fr_auto_auto\]{grid-template-columns:auto 1fr auto auto}.flex-col{flex-direction:column}.items-start{align-items:flex-start}.items-center{align-items:center}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-1{gap:8px}.gap-2{gap:16px}.gap-3{gap:24px}.gap-x-4{-moz-column-gap:32px;column-gap:32px}.gap-y-3{row-gap:24px}.space-x-2>:not([hidden])~:not([hidden]){--tw-space-x-reverse: 0;margin-right:calc(16px * var(--tw-space-x-reverse));margin-left:calc(16px * calc(1 - var(--tw-space-x-reverse)))}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(8px * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(8px * var(--tw-space-y-reverse))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(16px * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(16px * var(--tw-space-y-reverse))}.divide-y>:not([hidden])~:not([hidden]){--tw-divide-y-reverse: 0;border-top-width:calc(1px * calc(1 - var(--tw-divide-y-reverse)));border-bottom-width:calc(1px * var(--tw-divide-y-reverse))}.divide-border-light>:not([hidden])~:not([hidden]){--tw-divide-opacity: 1;border-color:rgb(243 244 246 / var(--tw-divide-opacity, 1))}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.whitespace-nowrap{white-space:nowrap}.rounded{border-radius:var(--widget-radius-card, 8px)}.rounded-2xl{border-radius:16px}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:8px}.rounded-md{border-radius:.375rem}.border{border-width:1px}.border-0{border-width:0px}.border-2{border-width:2px}.border-b{border-bottom-width:1px}.border-b-2{border-bottom-width:2px}.border-t{border-top-width:1px}.border-\[var\(--widget-border\)\]{border-color:var(--widget-border)}.border-\[var\(--widget-primary\)\]{border-color:var(--widget-primary)}.border-blue-300{--tw-border-opacity: 1;border-color:rgb(147 197 253 / var(--tw-border-opacity, 1))}.border-border{border-color:var(--widget-border, #e5e7eb)}.border-border-light{--tw-border-opacity: 1;border-color:rgb(243 244 246 / var(--tw-border-opacity, 1))}.border-gray-200{--tw-border-opacity: 1;border-color:rgb(229 231 235 / var(--tw-border-opacity, 1))}.border-gray-300{--tw-border-opacity: 1;border-color:rgb(209 213 219 / var(--tw-border-opacity, 1))}.border-transparent{border-color:transparent}.border-white{--tw-border-opacity: 1;border-color:rgb(255 255 255 / var(--tw-border-opacity, 1))}.border-t-blue-500{--tw-border-opacity: 1;border-top-color:rgb(59 130 246 / var(--tw-border-opacity, 1))}.border-t-transparent{border-top-color:transparent}.bg-\[var\(--widget-background\)\]{background-color:var(--widget-background)}.bg-\[var\(--widget-bg-hover\)\]{background-color:var(--widget-bg-hover)}.bg-\[var\(--widget-bg-secondary\)\]{background-color:var(--widget-bg-secondary)}.bg-\[var\(--widget-primary\)\]{background-color:var(--widget-primary)}.bg-\[var\(--widget-text\)\]{background-color:var(--widget-text)}.bg-\[var\(--widget-warning\)\]{background-color:var(--widget-warning)}.bg-black\/20{background-color:#0003}.bg-gray-300{--tw-bg-opacity: 1;background-color:rgb(209 213 219 / var(--tw-bg-opacity, 1))}.bg-gray-50{--tw-bg-opacity: 1;background-color:rgb(249 250 251 / var(--tw-bg-opacity, 1))}.bg-red-500{--tw-bg-opacity: 1;background-color:rgb(239 68 68 / var(--tw-bg-opacity, 1))}.bg-transparent{background-color:transparent}.bg-unread-indicator{background-color:var(--widget-unread-indicator, #2563eb)}.bg-white{--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1))}.bg-widget-background{background-color:var(--widget-background, #ffffff)}.bg-widget-hover{background-color:var(--widget-hover, #f9fafb)}.bg-widget-primary{background-color:var(--widget-primary, #2563eb)}.bg-gradient-to-br{background-image:linear-gradient(to bottom right,var(--tw-gradient-stops))}.from-widget-primary{--tw-gradient-from: var(--widget-primary, #2563eb) var(--tw-gradient-from-position);--tw-gradient-to: rgb(255 255 255 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.object-cover{-o-object-fit:cover;object-fit:cover}.p-1{padding:8px}.p-2{padding:16px}.p-3{padding:24px}.p-4{padding:32px}.px-1{padding-left:8px;padding-right:8px}.px-2{padding-left:16px;padding-right:16px}.px-3{padding-left:24px;padding-right:24px}.px-4{padding-left:32px;padding-right:32px}.py-1{padding-top:8px;padding-bottom:8px}.py-1\.5{padding-top:12px;padding-bottom:12px}.py-12{padding-top:96px;padding-bottom:96px}.py-2{padding-top:16px;padding-bottom:16px}.py-2\.5{padding-top:.625rem;padding-bottom:.625rem}.py-3{padding-top:24px;padding-bottom:24px}.py-8{padding-top:64px;padding-bottom:64px}.pb-1\.5{padding-bottom:12px}.pl-1{padding-left:8px}.pl-10{padding-left:80px}.pl-3{padding-left:24px}.pr-3{padding-right:24px}.pt-0\.5{padding-top:4px}.text-center{text-align:center}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.text-\[10px\]{font-size:10px}.text-base{font-size:var(--widget-font-size-subject, 14px);line-height:20px}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:var(--widget-font-size-body, 13px);line-height:18px}.text-xs{font-size:var(--widget-font-size-timestamp, 12px);line-height:16px}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-semibold{font-weight:600}.leading-4{line-height:1rem}.leading-5{line-height:1.25rem}.leading-none{line-height:1}.leading-relaxed{line-height:1.625}.text-\[var\(--widget-error\)\]{color:var(--widget-error)}.text-\[var\(--widget-primary\)\]{color:var(--widget-primary)}.text-\[var\(--widget-success\)\]{color:var(--widget-success)}.text-\[var\(--widget-text\)\]{color:var(--widget-text)}.text-\[var\(--widget-text-secondary\)\]{color:var(--widget-text-secondary)}.text-\[var\(--widget-text-tertiary\)\]{color:var(--widget-text-tertiary)}.text-\[var\(--widget-warning\)\]{color:var(--widget-warning)}.text-blue-700{--tw-text-opacity: 1;color:rgb(29 78 216 / var(--tw-text-opacity, 1))}.text-gray-300{--tw-text-opacity: 1;color:rgb(209 213 219 / var(--tw-text-opacity, 1))}.text-gray-500{--tw-text-opacity: 1;color:rgb(107 114 128 / var(--tw-text-opacity, 1))}.text-gray-600{--tw-text-opacity: 1;color:rgb(75 85 99 / var(--tw-text-opacity, 1))}.text-text-primary{color:var(--widget-text, #1f2937)}.text-text-secondary{--tw-text-opacity: 1;color:rgb(107 114 128 / var(--tw-text-opacity, 1))}.text-text-tertiary{--tw-text-opacity: 1;color:rgb(156 163 175 / var(--tw-text-opacity, 1))}.text-widget-primary{color:var(--widget-primary, #2563eb)}.opacity-0{opacity:0}.opacity-100{opacity:1}.opacity-50{opacity:.5}.opacity-80{opacity:.8}.shadow-lg{--tw-shadow: 0 10px 15px -3px rgb(0 0 0 / .1), 0 4px 6px -4px rgb(0 0 0 / .1);--tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-md{--tw-shadow: 0 4px 6px -1px rgb(0 0 0 / .1), 0 2px 4px -2px rgb(0 0 0 / .1);--tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-sm{--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / .05);--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-\[var\(--widget-shadow-xl\)\]{--tw-shadow-color: var(--widget-shadow-xl);--tw-shadow: var(--tw-shadow-colored)}.outline-none{outline:2px solid transparent;outline-offset:2px}.ring-0{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(0px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.backdrop-blur-sm{--tw-backdrop-blur: blur(4px);-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-timing-function:ease-in-out;transition-duration:.2s}.transition-all{transition-property:all;transition-timing-function:ease-in-out;transition-duration:.2s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:ease-in-out;transition-duration:.2s}.transition-opacity{transition-property:opacity;transition-timing-function:ease-in-out;transition-duration:.2s}.transition-transform{transition-property:transform;transition-timing-function:ease-in-out;transition-duration:.2s}.duration-200{transition-duration:.2s}.duration-300{transition-duration:.3s}.ease-in-out{transition-timing-function:cubic-bezier(.4,0,.2,1)}.widget-scrollbar{scrollbar-width:thin;scrollbar-color:var(--widget-border) transparent}.widget-scrollbar::-webkit-scrollbar{width:6px}.widget-scrollbar::-webkit-scrollbar-track{background:transparent}.widget-scrollbar::-webkit-scrollbar-thumb{background-color:var(--widget-border);border-radius:20px}.widget-scrollbar::-webkit-scrollbar-thumb:hover{background-color:var(--widget-text-tertiary)}.tab-inactive:hover{background-color:var(--widget-bg-hover);color:var(--widget-text)}.placeholder\:text-\[var\(--widget-text-tertiary\)\]::-moz-placeholder{color:var(--widget-text-tertiary)}.placeholder\:text-\[var\(--widget-text-tertiary\)\]::placeholder{color:var(--widget-text-tertiary)}.hover\:bg-\[var\(--widget-bg-hover\)\]:hover{background-color:var(--widget-bg-hover)}.hover\:bg-\[var\(--widget-primary-hover\)\]:hover{background-color:var(--widget-primary-hover)}.hover\:bg-\[var\(--widget-primary-light\)\]:hover{background-color:var(--widget-primary-light)}.hover\:bg-blue-50:hover{--tw-bg-opacity: 1;background-color:rgb(239 246 255 / var(--tw-bg-opacity, 1))}.hover\:bg-gray-100:hover{--tw-bg-opacity: 1;background-color:rgb(243 244 246 / var(--tw-bg-opacity, 1))}.hover\:bg-widget-hover:hover{background-color:var(--widget-hover, #f9fafb)}.hover\:text-\[var\(--widget-primary-hover\)\]:hover{color:var(--widget-primary-hover)}.hover\:text-\[var\(--widget-text\)\]:hover{color:var(--widget-text)}.hover\:text-text-primary:hover{color:var(--widget-text, #1f2937)}.focus\:border-transparent:focus{border-color:transparent}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus\:ring-1:focus{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.focus\:ring-2:focus{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.focus\:ring-\[var\(--widget-error\)\]:focus{--tw-ring-color: var(--widget-error)}.focus\:ring-\[var\(--widget-primary\)\]:focus{--tw-ring-color: var(--widget-primary)}.focus\:ring-blue-500:focus{--tw-ring-opacity: 1;--tw-ring-color: rgb(59 130 246 / var(--tw-ring-opacity, 1))}.focus\:ring-text-secondary:focus{--tw-ring-opacity: 1;--tw-ring-color: rgb(107 114 128 / var(--tw-ring-opacity, 1))}.focus\:ring-widget-primary:focus{--tw-ring-color: var(--widget-primary, #2563eb)}.focus\:ring-offset-0:focus{--tw-ring-offset-width: 0px}.focus\:ring-offset-1:focus{--tw-ring-offset-width: 1px}.focus\:ring-offset-2:focus{--tw-ring-offset-width: 2px}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:bg-widget-hover:disabled{background-color:var(--widget-hover, #f9fafb)}.disabled\:opacity-50:disabled{opacity:.5}.disabled\:opacity-70:disabled{opacity:.7}.dark\:border-gray-600:is([data-theme=dark] *){--tw-border-opacity: 1;border-color:rgb(75 85 99 / var(--tw-border-opacity, 1))}.dark\:border-gray-900:is([data-theme=dark] *){--tw-border-opacity: 1;border-color:rgb(17 24 39 / var(--tw-border-opacity, 1))}.dark\:border-t-blue-400:is([data-theme=dark] *){--tw-border-opacity: 1;border-top-color:rgb(96 165 250 / var(--tw-border-opacity, 1))}.dark\:bg-gray-600:is([data-theme=dark] *){--tw-bg-opacity: 1;background-color:rgb(75 85 99 / var(--tw-bg-opacity, 1))}.dark\:text-gray-400:is([data-theme=dark] *){--tw-text-opacity: 1;color:rgb(156 163 175 / var(--tw-text-opacity, 1))}.dark\:hover\:bg-gray-800:hover:is([data-theme=dark] *){--tw-bg-opacity: 1;background-color:rgb(31 41 55 / var(--tw-bg-opacity, 1))}@media not all and (min-width:640px){.max-sm\:fixed{position:fixed}.max-sm\:inset-x-4{left:32px;right:32px}.max-sm\:bottom-4{bottom:32px}.max-sm\:top-16{top:128px}.max-sm\:max-h-\[calc\(100vh-120px\)\]{max-height:calc(100vh - 120px)}.max-sm\:w-auto{width:auto}.max-sm\:max-w-none{max-width:none}}@media(min-width:768px){.md\:hidden{display:none}}
|
|
1
|
+
*,:before,:after{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}:before,:after{--tw-content: ""}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:var(--widget-font-family, -apple-system),BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}:root{--widget-primary: #cecece;--widget-primary-hover: rgb(212, 212, 212);--widget-primary-light: #eef2ff;--widget-background: #ffffff;--widget-bg: var(--widget-background);--widget-bg-secondary: #f9fafb;--widget-bg-hover: #f3f4f6;--widget-hover: var(--widget-bg-hover);--widget-text: #111827;--widget-text-secondary: #6b7280;--widget-text-tertiary: #9ca3af;--widget-border: #e5e7eb;--widget-border-light: #f3f4f6;--widget-unread-bg: #af50d4;--widget-unread-dot: #c26dbb;--widget-unread-badge-bg: #ef4444;--widget-success: #10b981;--widget-warning: #f59e0b;--widget-error: #ef4444;--widget-font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;--widget-popover-width: 480px;--widget-popover-max-height: 600px;--widget-shadow-sm: 0 1px 2px 0 rgb(0 0 0 / .05);--widget-shadow: 0 4px 6px -1px rgb(0 0 0 / .1), 0 2px 4px -2px rgb(0 0 0 / .1);--widget-shadow-lg: 0 10px 15px -3px rgb(0 0 0 / .1), 0 4px 6px -4px rgb(0 0 0 / .1);--widget-shadow-xl: 0 20px 25px -5px rgb(0 0 0 / .1), 0 8px 10px -6px rgb(0 0 0 / .1)}[data-theme=dark]{--widget-background: #1f2937;--widget-bg: var(--widget-background);--widget-bg-secondary: #111827;--widget-bg-hover: #374151;--widget-hover: var(--widget-bg-hover);--widget-text: #f9fafb;--widget-text-secondary: #d1d5db;--widget-text-tertiary: #9ca3af;--widget-border: #374151;--widget-border-light: #1f2937;--widget-primary: #dbdbdb;--widget-primary-hover: #a5b4fc;--widget-primary-light: rgba(99, 102, 241, .1);--widget-unread-bg: rgba(59, 130, 246, .1);--widget-unread-dot: #bdc3c9;--widget-shadow-sm: 0 1px 2px 0 rgb(0 0 0 / .3);--widget-shadow: 0 4px 6px -1px rgb(0 0 0 / .3), 0 2px 4px -2px rgb(0 0 0 / .3);--widget-shadow-lg: 0 10px 15px -3px rgb(0 0 0 / .4), 0 4px 6px -4px rgb(0 0 0 / .4);--widget-shadow-xl: 0 20px 25px -5px rgb(0 0 0 / .5), 0 8px 10px -6px rgb(0 0 0 / .5)}.notification-item{height:var(--widget-item-height, 80px);display:flex;align-items:flex-start;transition:background-color .2s ease-in-out;cursor:pointer}.notification-item:hover{background-color:var(--widget-hover, #f9fafb)}.notification-item.unread{background-color:var(--widget-unread-bg, #f0f4ff)}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.pointer-events-none{pointer-events:none}.static{position:static}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.inset-0{inset:0}.inset-y-0{top:0;bottom:0}.-right-2{right:-16px}.-top-2{top:-16px}.left-0{left:0}.right-0{right:0}.top-full{top:100%}.z-10{z-index:10}.z-40{z-index:40}.z-50{z-index:50}.col-span-2{grid-column:span 2 / span 2}.mx-auto{margin-left:auto;margin-right:auto}.mb-0\.5{margin-bottom:4px}.mb-2{margin-bottom:16px}.mb-3{margin-bottom:24px}.mb-4{margin-bottom:32px}.ml-1{margin-left:8px}.mr-1{margin-right:8px}.mr-2{margin-right:16px}.mt-1\.5{margin-top:12px}.mt-2{margin-top:16px}.line-clamp-2{overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2}.inline-block{display:inline-block}.flex{display:flex}.inline-flex{display:inline-flex}.grid{display:grid}.hidden{display:none}.h-10{height:80px}.h-12{height:96px}.h-2{height:16px}.h-3{height:24px}.h-4{height:32px}.h-5{height:40px}.h-6{height:48px}.h-7{height:1.75rem}.h-8{height:64px}.h-\[16px\]{height:16px}.h-full{height:100%}.max-h-32{max-height:8rem}.max-h-\[calc\(var\(--widget-popover-max-height\)-200px\)\]{max-height:calc(var(--widget-popover-max-height) - 200px)}.max-h-\[var\(--widget-popover-max-height\,580px\)\]{max-height:var(--widget-popover-max-height,580px)}.min-h-\[20px\]{min-height:20px}.w-10{width:80px}.w-12{width:96px}.w-16{width:128px}.w-2{width:16px}.w-3\/4{width:75%}.w-4{width:32px}.w-5{width:40px}.w-5\/6{width:83.333333%}.w-6{width:48px}.w-7{width:1.75rem}.w-8{width:64px}.w-9{width:2.25rem}.w-\[16px\]{width:16px}.w-\[88px\]{width:88px}.w-\[var\(--widget-popover-width\,400px\)\]{width:var(--widget-popover-width,400px)}.w-full{width:100%}.min-w-0{min-width:0px}.min-w-\[20rem\]{min-width:20rem}.flex-1{flex:1 1 0%}.flex-shrink-0{flex-shrink:0}.origin-top-left{transform-origin:top left}.origin-top-right{transform-origin:top right}.-translate-x-1\/2{--tw-translate-x: -50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.-translate-x-full{--tw-translate-x: -100%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.-translate-y-1\/2{--tw-translate-y: -50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.-translate-y-full{--tw-translate-y: -100%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-x-0{--tw-translate-x: 0px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-x-4{--tw-translate-x: 32px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-y-0{--tw-translate-y: 0px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.rotate-180{--tw-rotate: 180deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}@keyframes pulse{50%{opacity:.5}}.animate-pulse{animation:pulse 2s cubic-bezier(.4,0,.6,1) infinite}@keyframes spin{to{transform:rotate(360deg)}}.animate-spin{animation:spin 1s linear infinite}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.grid-cols-\[auto_1fr_auto_auto\]{grid-template-columns:auto 1fr auto auto}.flex-col{flex-direction:column}.items-start{align-items:flex-start}.items-center{align-items:center}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-1{gap:8px}.gap-2{gap:16px}.gap-3{gap:24px}.gap-x-4{-moz-column-gap:32px;column-gap:32px}.gap-y-3{row-gap:24px}.space-x-2>:not([hidden])~:not([hidden]){--tw-space-x-reverse: 0;margin-right:calc(16px * var(--tw-space-x-reverse));margin-left:calc(16px * calc(1 - var(--tw-space-x-reverse)))}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(8px * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(8px * var(--tw-space-y-reverse))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(16px * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(16px * var(--tw-space-y-reverse))}.divide-y>:not([hidden])~:not([hidden]){--tw-divide-y-reverse: 0;border-top-width:calc(1px * calc(1 - var(--tw-divide-y-reverse)));border-bottom-width:calc(1px * var(--tw-divide-y-reverse))}.divide-border-light>:not([hidden])~:not([hidden]){--tw-divide-opacity: 1;border-color:rgb(243 244 246 / var(--tw-divide-opacity, 1))}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.whitespace-nowrap{white-space:nowrap}.rounded{border-radius:var(--widget-radius-card, 8px)}.rounded-2xl{border-radius:16px}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:8px}.rounded-md{border-radius:.375rem}.border{border-width:1px}.border-0{border-width:0px}.border-2{border-width:2px}.border-b{border-bottom-width:1px}.border-b-2{border-bottom-width:2px}.border-t{border-top-width:1px}.border-\[var\(--widget-border\)\]{border-color:var(--widget-border)}.border-\[var\(--widget-primary\)\]{border-color:var(--widget-primary)}.border-blue-300{--tw-border-opacity: 1;border-color:rgb(147 197 253 / var(--tw-border-opacity, 1))}.border-border{border-color:var(--widget-border, #e5e7eb)}.border-border-light{--tw-border-opacity: 1;border-color:rgb(243 244 246 / var(--tw-border-opacity, 1))}.border-gray-200{--tw-border-opacity: 1;border-color:rgb(229 231 235 / var(--tw-border-opacity, 1))}.border-gray-300{--tw-border-opacity: 1;border-color:rgb(209 213 219 / var(--tw-border-opacity, 1))}.border-transparent{border-color:transparent}.border-white{--tw-border-opacity: 1;border-color:rgb(255 255 255 / var(--tw-border-opacity, 1))}.border-t-blue-500{--tw-border-opacity: 1;border-top-color:rgb(59 130 246 / var(--tw-border-opacity, 1))}.border-t-transparent{border-top-color:transparent}.bg-\[var\(--widget-background\)\]{background-color:var(--widget-background)}.bg-\[var\(--widget-bg-hover\)\]{background-color:var(--widget-bg-hover)}.bg-\[var\(--widget-bg-secondary\)\]{background-color:var(--widget-bg-secondary)}.bg-\[var\(--widget-primary\)\]{background-color:var(--widget-primary)}.bg-\[var\(--widget-text\)\]{background-color:var(--widget-text)}.bg-\[var\(--widget-warning\)\]{background-color:var(--widget-warning)}.bg-black\/20{background-color:#0003}.bg-gray-300{--tw-bg-opacity: 1;background-color:rgb(209 213 219 / var(--tw-bg-opacity, 1))}.bg-gray-50{--tw-bg-opacity: 1;background-color:rgb(249 250 251 / var(--tw-bg-opacity, 1))}.bg-red-500{--tw-bg-opacity: 1;background-color:rgb(239 68 68 / var(--tw-bg-opacity, 1))}.bg-transparent{background-color:transparent}.bg-unread-indicator{background-color:var(--widget-unread-indicator, #2563eb)}.bg-white{--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1))}.bg-widget-background{background-color:var(--widget-background, #ffffff)}.bg-widget-hover{background-color:var(--widget-hover, #f9fafb)}.bg-widget-primary{background-color:var(--widget-primary, #2563eb)}.bg-gradient-to-br{background-image:linear-gradient(to bottom right,var(--tw-gradient-stops))}.from-widget-primary{--tw-gradient-from: var(--widget-primary, #2563eb) var(--tw-gradient-from-position);--tw-gradient-to: rgb(255 255 255 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.object-cover{-o-object-fit:cover;object-fit:cover}.p-1{padding:8px}.p-2{padding:16px}.p-3{padding:24px}.p-4{padding:32px}.px-1{padding-left:8px;padding-right:8px}.px-2{padding-left:16px;padding-right:16px}.px-3{padding-left:24px;padding-right:24px}.px-4{padding-left:32px;padding-right:32px}.py-1{padding-top:8px;padding-bottom:8px}.py-1\.5{padding-top:12px;padding-bottom:12px}.py-12{padding-top:96px;padding-bottom:96px}.py-2{padding-top:16px;padding-bottom:16px}.py-2\.5{padding-top:.625rem;padding-bottom:.625rem}.py-3{padding-top:24px;padding-bottom:24px}.py-8{padding-top:64px;padding-bottom:64px}.pb-1\.5{padding-bottom:12px}.pl-1{padding-left:8px}.pl-10{padding-left:80px}.pl-3{padding-left:24px}.pr-3{padding-right:24px}.pt-0\.5{padding-top:4px}.text-center{text-align:center}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.text-\[10px\]{font-size:10px}.text-base{font-size:var(--widget-font-size-subject, 14px);line-height:20px}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:var(--widget-font-size-body, 13px);line-height:18px}.text-xs{font-size:var(--widget-font-size-timestamp, 12px);line-height:16px}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-semibold{font-weight:600}.leading-4{line-height:1rem}.leading-5{line-height:1.25rem}.leading-none{line-height:1}.leading-relaxed{line-height:1.625}.text-\[var\(--widget-error\)\]{color:var(--widget-error)}.text-\[var\(--widget-primary\)\]{color:var(--widget-primary)}.text-\[var\(--widget-success\)\]{color:var(--widget-success)}.text-\[var\(--widget-text\)\]{color:var(--widget-text)}.text-\[var\(--widget-text-secondary\)\]{color:var(--widget-text-secondary)}.text-\[var\(--widget-text-tertiary\)\]{color:var(--widget-text-tertiary)}.text-\[var\(--widget-warning\)\]{color:var(--widget-warning)}.text-blue-700{--tw-text-opacity: 1;color:rgb(29 78 216 / var(--tw-text-opacity, 1))}.text-gray-300{--tw-text-opacity: 1;color:rgb(209 213 219 / var(--tw-text-opacity, 1))}.text-gray-500{--tw-text-opacity: 1;color:rgb(107 114 128 / var(--tw-text-opacity, 1))}.text-gray-600{--tw-text-opacity: 1;color:rgb(75 85 99 / var(--tw-text-opacity, 1))}.text-text-primary{color:var(--widget-text, #1f2937)}.text-text-secondary{--tw-text-opacity: 1;color:rgb(107 114 128 / var(--tw-text-opacity, 1))}.text-text-tertiary{--tw-text-opacity: 1;color:rgb(156 163 175 / var(--tw-text-opacity, 1))}.text-widget-primary{color:var(--widget-primary, #2563eb)}.opacity-0{opacity:0}.opacity-100{opacity:1}.opacity-50{opacity:.5}.opacity-80{opacity:.8}.shadow-lg{--tw-shadow: 0 10px 15px -3px rgb(0 0 0 / .1), 0 4px 6px -4px rgb(0 0 0 / .1);--tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-md{--tw-shadow: 0 4px 6px -1px rgb(0 0 0 / .1), 0 2px 4px -2px rgb(0 0 0 / .1);--tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-sm{--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / .05);--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-\[var\(--widget-shadow-xl\)\]{--tw-shadow-color: var(--widget-shadow-xl);--tw-shadow: var(--tw-shadow-colored)}.outline-none{outline:2px solid transparent;outline-offset:2px}.ring-0{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(0px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.backdrop-blur-sm{--tw-backdrop-blur: blur(4px);-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-timing-function:ease-in-out;transition-duration:.2s}.transition-all{transition-property:all;transition-timing-function:ease-in-out;transition-duration:.2s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:ease-in-out;transition-duration:.2s}.transition-opacity{transition-property:opacity;transition-timing-function:ease-in-out;transition-duration:.2s}.transition-transform{transition-property:transform;transition-timing-function:ease-in-out;transition-duration:.2s}.duration-200{transition-duration:.2s}.duration-300{transition-duration:.3s}.ease-in-out{transition-timing-function:cubic-bezier(.4,0,.2,1)}.placeholder\:text-\[var\(--widget-text-tertiary\)\]::-moz-placeholder{color:var(--widget-text-tertiary)}.placeholder\:text-\[var\(--widget-text-tertiary\)\]::placeholder{color:var(--widget-text-tertiary)}.hover\:bg-\[var\(--widget-bg-hover\)\]:hover{background-color:var(--widget-bg-hover)}.hover\:bg-\[var\(--widget-primary-hover\)\]:hover{background-color:var(--widget-primary-hover)}.hover\:bg-\[var\(--widget-primary-light\)\]:hover{background-color:var(--widget-primary-light)}.hover\:bg-blue-50:hover{--tw-bg-opacity: 1;background-color:rgb(239 246 255 / var(--tw-bg-opacity, 1))}.hover\:bg-gray-100:hover{--tw-bg-opacity: 1;background-color:rgb(243 244 246 / var(--tw-bg-opacity, 1))}.hover\:bg-widget-hover:hover{background-color:var(--widget-hover, #f9fafb)}.hover\:text-\[var\(--widget-primary-hover\)\]:hover{color:var(--widget-primary-hover)}.hover\:text-\[var\(--widget-text\)\]:hover{color:var(--widget-text)}.hover\:text-text-primary:hover{color:var(--widget-text, #1f2937)}.focus\:border-transparent:focus{border-color:transparent}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus\:ring-1:focus{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.focus\:ring-2:focus{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.focus\:ring-\[var\(--widget-error\)\]:focus{--tw-ring-color: var(--widget-error)}.focus\:ring-\[var\(--widget-primary\)\]:focus{--tw-ring-color: var(--widget-primary)}.focus\:ring-blue-500:focus{--tw-ring-opacity: 1;--tw-ring-color: rgb(59 130 246 / var(--tw-ring-opacity, 1))}.focus\:ring-text-secondary:focus{--tw-ring-opacity: 1;--tw-ring-color: rgb(107 114 128 / var(--tw-ring-opacity, 1))}.focus\:ring-widget-primary:focus{--tw-ring-color: var(--widget-primary, #2563eb)}.focus\:ring-offset-0:focus{--tw-ring-offset-width: 0px}.focus\:ring-offset-1:focus{--tw-ring-offset-width: 1px}.focus\:ring-offset-2:focus{--tw-ring-offset-width: 2px}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:bg-widget-hover:disabled{background-color:var(--widget-hover, #f9fafb)}.disabled\:opacity-50:disabled{opacity:.5}.disabled\:opacity-70:disabled{opacity:.7}.dark\:border-gray-600:is([data-theme=dark] *){--tw-border-opacity: 1;border-color:rgb(75 85 99 / var(--tw-border-opacity, 1))}.dark\:border-gray-900:is([data-theme=dark] *){--tw-border-opacity: 1;border-color:rgb(17 24 39 / var(--tw-border-opacity, 1))}.dark\:border-t-blue-400:is([data-theme=dark] *){--tw-border-opacity: 1;border-top-color:rgb(96 165 250 / var(--tw-border-opacity, 1))}.dark\:bg-gray-600:is([data-theme=dark] *){--tw-bg-opacity: 1;background-color:rgb(75 85 99 / var(--tw-bg-opacity, 1))}.dark\:text-gray-400:is([data-theme=dark] *){--tw-text-opacity: 1;color:rgb(156 163 175 / var(--tw-text-opacity, 1))}.dark\:hover\:bg-gray-800:hover:is([data-theme=dark] *){--tw-bg-opacity: 1;background-color:rgb(31 41 55 / var(--tw-bg-opacity, 1))}@media not all and (min-width:640px){.max-sm\:fixed{position:fixed}.max-sm\:inset-x-4{left:32px;right:32px}.max-sm\:bottom-4{bottom:32px}.max-sm\:top-16{top:128px}.max-sm\:max-h-\[calc\(100vh-120px\)\]{max-height:calc(100vh - 120px)}.max-sm\:w-auto{width:auto}.max-sm\:max-w-none{max-width:none}}@media(min-width:768px){.md\:hidden{display:none}}
|