@edusight/notification-widget 1.0.43 → 1.0.44

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/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"),B=require("@edusight/notification-sdk"),i=require("react"),q=require("socket.io-client"),v=require("./hooks-C6Z38jT_.cjs"),m=require("./components-CJcM_JjP.cjs"),V=()=>window.__notificationSDK?.client,z=({onPreferencesLoaded:t,onError:n})=>{const p=V(),[w,c]=i.useState(!0),[f,l]=i.useState(null),[r,u]=i.useState(null),y=i.useCallback(async()=>{try{if(c(!0),l(null),!p)throw new Error("Notification client not available");const h=window.__notificationSDK?.config;if(!h)throw new Error("SDK configuration not available");const{subscriberId:g,tenantId:k,environmentId:T}=h;if(!g||!k||!T)throw new Error("SubscriberId, TenantId or EnvironmentId not available in config");const E=await p.preferences.get(k,g,T);let d=null;try{d=await p.preferences.getSchedule(k,g,T)}catch{}const _={channels:{email:E.emailEnabled??!0,push:E.pushEnabled??!0,sms:E.smsEnabled??!1,inApp:E.inAppEnabled??!0},subscriptions:[],deliverySchedule:{enabled:d?.isEnabled||!1,timezone:"UTC",quietHours:{start:E.quietHoursStart??"22:00",end:E.quietHoursEnd??"08:00"},weekdays:d?.weeklySchedule?[!!d.weeklySchedule.monday,!!d.weeklySchedule.tuesday,!!d.weeklySchedule.wednesday,!!d.weeklySchedule.thursday,!!d.weeklySchedule.friday,!!d.weeklySchedule.saturday,!!d.weeklySchedule.sunday]:[!0,!0,!0,!0,!0,!1,!1],weeklySchedule:d?.weeklySchedule||void 0}};E.categories&&Object.entries(E.categories).forEach(([N,C])=>{_.subscriptions.push({workflowId:N,name:N,enabled:!0,channels:{email:C.emailEnabled??!0,push:C.pushEnabled??!0,sms:C.smsEnabled??!1,inApp:C.inAppEnabled??!0}})}),u(_),t(_)}catch(h){const g=h instanceof Error?h:new Error("Failed to load preferences");h?.response?.status===404||h?.status===404||(l(g),n?.(g));const T={channels:{email:!0,push:!0,sms:!1,inApp:!0},subscriptions:[],deliverySchedule:{enabled:!1,timezone:"UTC",quietHours:{start:"22:00",end:"08:00"},weekdays:[!0,!0,!0,!0,!0,!1,!1]}};u(T),t(T)}finally{c(!1)}},[p,t,n]);return i.useEffect(()=>{p&&y()},[p,y]),{isLoading:w,error:f,preferences:r}},H=()=>window.__notificationSDK?.client,$=()=>{const t=H(),[n,p]=i.useState([]),[w,c]=i.useState(!1),[f,l]=i.useState(!0),[r,u]=i.useState(0),y=5,h=i.useCallback(async()=>{if(!(!t||w||!f))try{c(!0);const k=window.__notificationSDK?.config;if(!k)return;const T=await t.preferences.listSpecific(k.tenantId,k.subscriberId,{includeWorkflows:!0,includeTemplates:!1,activeOnly:!0,limit:y,offset:r}),E=(T.items||[]).map(d=>({workflowId:d.identifier,name:d.name,enabled:d.preference.enabled,channels:d.preference.channels}));p(d=>{const _=new Set(d.map(C=>C.workflowId)),N=E.filter(C=>!_.has(C.workflowId));return[...d,...N]}),u(d=>d+y),(E.length<y||T.total!==void 0&&n.length+E.length>=T.total)&&l(!1)}catch{}finally{c(!1)}},[t,r,f,w,n.length]);return i.useEffect(()=>{t&&r===0&&n.length===0&&h()},[t,h,r,n.length]),{specificPreferences:n,isLoading:w,hasMore:f,loadMore:h,refetch:async()=>{p([]),u(0),l(!0)}}},J=({error:t,onRetry:n})=>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(m.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&&`
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const s=require("react/jsx-runtime"),H=require("@edusight/notification-sdk"),i=require("react"),z=require("socket.io-client"),A=require("./hooks-C6Z38jT_.cjs"),E=require("./components-CJcM_JjP.cjs"),$=()=>window.__notificationSDK?.client,J=({onPreferencesLoaded:t,onError:n})=>{const p=$(),[w,c]=i.useState(!0),[f,l]=i.useState(null),[r,u]=i.useState(null),b=i.useCallback(async()=>{try{if(c(!0),l(null),!p)throw new Error("Notification client not available");const h=window.__notificationSDK?.config;if(!h)throw new Error("SDK configuration not available");const{subscriberId:g,tenantId:k,environmentId:T}=h;if(!g||!k||!T)throw new Error("SubscriberId, TenantId or EnvironmentId not available in config");const S=await p.preferences.get(k,g,T);let d=null;try{d=await p.preferences.getSchedule(k,g,T)}catch{}const _={channels:{email:S.emailEnabled??!0,push:S.pushEnabled??!0,sms:S.smsEnabled??!1,inApp:S.inAppEnabled??!0},subscriptions:[],deliverySchedule:{enabled:d?.isEnabled||!1,timezone:"UTC",quietHours:{start:S.quietHoursStart??"22:00",end:S.quietHoursEnd??"08:00"},weekdays:d?.weeklySchedule?[!!d.weeklySchedule.monday,!!d.weeklySchedule.tuesday,!!d.weeklySchedule.wednesday,!!d.weeklySchedule.thursday,!!d.weeklySchedule.friday,!!d.weeklySchedule.saturday,!!d.weeklySchedule.sunday]:[!0,!0,!0,!0,!0,!1,!1],weeklySchedule:d?.weeklySchedule||void 0}};S.categories&&Object.entries(S.categories).forEach(([N,C])=>{_.subscriptions.push({workflowId:N,name:N,enabled:!0,channels:{email:C.emailEnabled??!0,push:C.pushEnabled??!0,sms:C.smsEnabled??!1,inApp:C.inAppEnabled??!0}})}),u(_),t(_)}catch(h){const g=h instanceof Error?h:new Error("Failed to load preferences");h?.response?.status===404||h?.status===404||(l(g),n?.(g));const T={channels:{email:!0,push:!0,sms:!1,inApp:!0},subscriptions:[],deliverySchedule:{enabled:!1,timezone:"UTC",quietHours:{start:"22:00",end:"08:00"},weekdays:[!0,!0,!0,!0,!0,!1,!1]}};u(T),t(T)}finally{c(!1)}},[p,t,n]);return i.useEffect(()=>{p&&b()},[p,b]),{isLoading:w,error:f,preferences:r}},G=()=>window.__notificationSDK?.client,Q=()=>{const t=G(),[n,p]=i.useState([]),[w,c]=i.useState(!1),[f,l]=i.useState(!0),[r,u]=i.useState(0),b=5,h=i.useCallback(async()=>{if(!(!t||w||!f))try{c(!0);const k=window.__notificationSDK?.config;if(!k)return;const T=await t.preferences.listSpecific(k.tenantId,k.subscriberId,{includeWorkflows:!0,includeTemplates:!1,activeOnly:!0,limit:b,offset:r}),S=(T.items||[]).map(d=>({workflowId:d.identifier,name:d.name,enabled:d.preference.enabled,channels:d.preference.channels}));p(d=>{const _=new Set(d.map(C=>C.workflowId)),N=S.filter(C=>!_.has(C.workflowId));return[...d,...N]}),u(d=>d+b),(S.length<b||T.total!==void 0&&n.length+S.length>=T.total)&&l(!1)}catch{}finally{c(!1)}},[t,r,f,w,n.length]);return i.useEffect(()=>{t&&r===0&&n.length===0&&h()},[t,h,r,n.length]),{specificPreferences:n,isLoading:w,hasMore:f,loadMore:h,refetch:async()=>{p([]),u(0),l(!0)}}},X=({error:t,onRetry:n})=>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:n,"data-testid":"error-retry-button",children:[s.jsx(m.MdRefresh,{className:"mr-1 w-4 h-4","aria-hidden":"true"}),"Try again"]})]});class D extends i.Component{constructor(n){super(n),this.handleRetry=()=>{this.setState({hasError:!1,error:null,errorInfo:null})},this.state={hasError:!1,error:null,errorInfo:null}}static getDerivedStateFromError(n){return{hasError:!0,error:n}}componentDidCatch(n,p){this.setState({errorInfo:p}),this.props.onError&&this.props.onError(n,p)}render(){return this.state.hasError?s.jsx(J,{error:this.state.error,onRetry:this.handleRetry}):this.props.children}}const P=i.createContext(null),G=()=>{const t=i.useContext(P);if(!t)throw new Error("useSDK must be used within a NotificationWidget");return t},Q={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}},X=({config:t,children:n})=>{const[p,w]=i.useState({client:null,isInitialized:!1,error:null});return i.useEffect(()=>{let c=!0;return(async()=>{try{const l=window.__notificationSDK;if(l?.client&&JSON.stringify(l.config)===JSON.stringify(t)){c&&w({client:l.client,isInitialized:!0,error:null});return}const r=new B.NotificationClient({apiUrl:t.baseUrl,apiKey:t.apiKey,tenantId:t.tenantId,environmentId:t.environmentId});window.__notificationSDK={client:r,config:t},c&&w({client:r,isInitialized:!0,error:null})}catch(l){c&&w({client:null,isInitialized:!1,error:l})}})(),()=>{c=!1}},[t]),s.jsx(P.Provider,{value:p,children:n})},Y=(t,n)=>{switch(n.type){case"SET_NOTIFICATIONS":return{...t,notifications:n.payload,unreadCount:n.payload.filter(f=>!f.isRead).length};case"ADD_NOTIFICATION":const p=[n.payload,...t.notifications];return{...t,notifications:p,unreadCount:p.filter(f=>!f.isRead).length};case"UPDATE_NOTIFICATION":const w=t.notifications.map(f=>f.id===n.payload.id?{...f,...n.payload.updates}:f);return{...t,notifications:w,unreadCount:w.filter(f=>!f.isRead).length};case"DELETE_NOTIFICATION":const c=t.notifications.filter(f=>f.id!==n.payload);return{...t,notifications:c,unreadCount:c.filter(f=>!f.isRead).length};case"SET_PREFERENCES":return{...t,preferences:n.payload};case"SET_UI_STATE":return{...t,ui:{...t.ui,...n.payload}};case"SET_WEBSOCKET_STATE":return{...t,websocket:{...t.websocket,...n.payload}};default:return t}},Z=({position:t="right",size:n="medium",theme:p="light",className:w="",onError:c,onMorePreferencesClick:f})=>{const[l,r]=i.useReducer(Y,Q),{client:u,isInitialized:y,error:h}=G(),g=i.useRef(null),k=i.useCallback(e=>{r({type:"SET_PREFERENCES",payload:e})},[]),T=i.useCallback(e=>{c&&c(e)},[c]),{error:E}=z({onPreferencesLoaded:k,onError:T}),{specificPreferences:d,isLoading:_,hasMore:N,loadMore:C}=$(),{updatePreference:j,isSaving:A,error:O}=v.useLivePreferences({preferences:l.preferences,onPreferencesChange:k,onError:T});i.useEffect(()=>{if(d.length>0){const o=[...l.preferences.subscriptions];let a=!1;d.forEach(I=>{const S=o.findIndex(b=>b.workflowId===I.workflowId);if(S===-1)o.push(I),a=!0;else{const b=o[S];b.name===b.workflowId&&I.name&&I.name!==I.workflowId&&(o[S]={...b,name:I.name},a=!0)}}),a&&r({type:"SET_PREFERENCES",payload:{...l.preferences,subscriptions:o}})}},[d]);const K=i.useMemo(()=>d.map(e=>l.preferences.subscriptions.find(a=>a.workflowId===e.workflowId)||e),[d,l.preferences.subscriptions]),x=i.useCallback(e=>{try{const o=v.createNotificationMapper();switch(e.type){case"notification_received":{const a=e.data;if(!o.validateWebSocketPayload(a))break;const I=o.toWidgetNotificationFromWebSocket(a);r({type:"ADD_NOTIFICATION",payload:I});break}case"notification_updated":r({type:"UPDATE_NOTIFICATION",payload:{id:e.data.id||e.data.notificationId,updates:e.data}});break;case"notification_deleted":r({type:"DELETE_NOTIFICATION",payload:e.data.id||e.data.notificationId});break;case"preferences_updated":r({type:"SET_PREFERENCES",payload:e.data});break;default:}}catch{}},[]),R=i.useCallback(async()=>{if(!(!u||!y||g.current))try{r({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 I=`${u.getApiHost()}/v1/notifications`,S=q.io(I,{query:{tenantId:e.tenantId,subscriberId:e.subscriberId,environmentId:e.environmentId},transports:["websocket"],autoConnect:!1,reconnection:!0,reconnectionAttempts:10,reconnectionDelay:1e3,reconnectionDelayMax:5e3});g.current=S,S.on("notification",b=>{x({type:"notification_received",data:b})}),S.on("connect",()=>{r({type:"SET_WEBSOCKET_STATE",payload:{connected:!0,reconnecting:!1}})}),S.on("disconnect",b=>{r({type:"SET_WEBSOCKET_STATE",payload:{connected:!1,reconnecting:!1}})}),S.on("reconnect_attempt",b=>{r({type:"SET_WEBSOCKET_STATE",payload:{connected:!1,reconnecting:!0}})}),S.on("connect_error",b=>{r({type:"SET_WEBSOCKET_STATE",payload:{connected:!1,reconnecting:!1}}),c&&c(b)}),S.connect()}catch(e){r({type:"SET_WEBSOCKET_STATE",payload:{connected:!1,reconnecting:!1}}),c&&c(e)}},[u,y,x,c]),W=i.useCallback(()=>{if(g.current)try{g.current.disconnect&&g.current.disconnect(),g.current=null,r({type:"SET_WEBSOCKET_STATE",payload:{connected:!1,reconnecting:!1}})}catch{}},[]),F=i.useCallback(()=>{r({type:"SET_UI_STATE",payload:{isOpen:!l.ui.isOpen}})},[l.ui.isOpen]),M=i.useCallback(()=>{r({type:"SET_UI_STATE",payload:{isOpen:!1}})},[]),L=i.useCallback(e=>{r({type:"SET_UI_STATE",payload:{currentView:e}})},[]),U=i.useCallback(async(e,o)=>{if(!u||!y)return;const a=window.__notificationSDK?.config;if(a){if(!e)throw new Error("notificationId is required");try{switch(o.type){case"mark_read":await u.inbox.markAsRead(e,a.tenantId,a.environmentId,a.subscriberId);break;case"mark_unread":await u.inbox.markAsUnread(e,a.tenantId,a.environmentId,a.subscriberId);break;case"archive":await u.inbox.archive(e,a.tenantId,a.environmentId,a.subscriberId);break;case"delete":await u.inbox.delete(e,a.tenantId,a.environmentId,a.subscriberId);break;default:o.handler&&await o.handler(e);break}switch(o.type){case"mark_read":r({type:"UPDATE_NOTIFICATION",payload:{id:e,updates:{isRead:!0}}});break;case"mark_unread":r({type:"UPDATE_NOTIFICATION",payload:{id:e,updates:{isRead:!1}}});break;case"archive":r({type:"UPDATE_NOTIFICATION",payload:{id:e,updates:{isArchived:!0}}});break;case"delete":r({type:"DELETE_NOTIFICATION",payload:e});break}}catch(I){c&&c(I)}}},[u]);return i.useEffect(()=>{if(!u||!y)return;(async()=>{try{r({type:"SET_UI_STATE",payload:{isLoading:!0}});const o=window.__notificationSDK?.config;if(!o)throw new Error("SDK configuration not available");const a=v.createNotificationMapper(),S=((await u.inbox.getRenderedNotifications({channel:"in_app",limit:50,offset:0},o.tenantId,o.environmentId,o.subscriberId))?.items||[]).map(b=>a.toWidgetNotification(b));r({type:"SET_NOTIFICATIONS",payload:S}),r({type:"SET_UI_STATE",payload:{isLoading:!1,error:null}})}catch(o){r({type:"SET_UI_STATE",payload:{isLoading:!1,error:o}}),c&&c(o)}})()},[u,y,c]),i.useEffect(()=>(u&&y&&R(),()=>{W()}),[u]),i.useEffect(()=>{if(!u||!y||l.websocket.connected)return;const e=setInterval(async()=>{try{const o=window.__notificationSDK?.config;if(!o)return;const a=v.createNotificationMapper(),S=((await u.inbox.getRenderedNotifications({channel:"in_app",limit:50,offset:0},o.tenantId,o.environmentId,o.subscriberId))?.items||[]).map(b=>a.toWidgetNotification(b));r({type:"SET_NOTIFICATIONS",payload:S})}catch{}},3e4);return()=>clearInterval(e)},[u,l.websocket.connected]),i.useEffect(()=>{const e=o=>{if(o.key==="notification_widget_sync"&&o.newValue)try{const a=JSON.parse(o.newValue);x(a)}catch{}};return window.addEventListener("storage",e),()=>window.removeEventListener("storage",e)},[x]),i.useEffect(()=>{r({type:"SET_UI_STATE",payload:{isLoading:A}})},[A]),i.useEffect(()=>{const e=h||O||E;e&&r({type:"SET_UI_STATE",payload:{error:e}})},[h,O,E]),!y&&!h?s.jsx("div",{className:`mx-widget-root relative inline-block ${w}`,"data-mx-widget":"root","data-widget-size":n||"small","data-theme":p,"data-testid":"notification-widget",children:s.jsx(m.ComponentErrorBoundary,{componentName:"BellComponent",children:s.jsx(m.BellComponent,{unreadCount:0,onClick:()=>{},size:n,disabled:!0})})}):h?s.jsx("div",{className:`mx-widget-root relative inline-block ${w}`,"data-mx-widget":"root","data-widget-size":n||"small","data-theme":p,"data-testid":"notification-widget",children:s.jsx(m.ComponentErrorBoundary,{componentName:"BellComponent",fallback:s.jsx(m.SDKConnectionFallback,{error:h.message,onRetry:()=>window.location.reload()}),children:s.jsx(m.BellComponent,{unreadCount:0,onClick:()=>{},size:n,disabled:!0})})}):s.jsxs("div",{className:`mx-widget-root min-w-[20rem] relative inline-block ${w}`,"data-mx-widget":"root","data-widget-size":n||"small","data-theme":p,"data-testid":"notification-widget",children:[s.jsx(m.ComponentErrorBoundary,{componentName:"BellComponent",children:s.jsx(m.BellComponent,{unreadCount:l.unreadCount,onClick:F,size:n,disabled:l.ui.isLoading})}),s.jsx(m.ComponentErrorBoundary,{componentName:"InboxPopover",fallback:s.jsx(m.LoadingFallback,{message:"Unable to load notifications"}),children:s.jsx(m.InboxPopover,{isOpen:l.ui.isOpen,onClose:M,position:t,currentView:l.ui.currentView,onViewChange:L,notifications:l.notifications,onNotificationAction:U,preferences:l.preferences,onPreferenceChange:j,isPreferencesLoading:A,specificPreferences:K,onLoadMoreSpecific:C,hasMoreSpecific:N,isListLoading:_,onMorePreferencesClick:f})})]})},ee=({sdkConfig:t,...n})=>s.jsx(D,{onError:n.onError,children:s.jsx(X,{config:t,children:s.jsx(Z,{...n})})}),te="3.0.0",ne="@edusight/notification-widget";exports.BellComponent=m.BellComponent;exports.InboxPopover=m.InboxPopover;exports.NotificationItem=m.NotificationItem;exports.PreferencesView=m.PreferencesView;exports.NotificationWidget=ee;exports.NotificationWidgetErrorBoundary=D;exports.VERSION=te;exports.WIDGET_NAME=ne;
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:n,"data-testid":"error-retry-button",children:[s.jsx(E.MdRefresh,{className:"mr-1 w-4 h-4","aria-hidden":"true"}),"Try again"]})]});class P extends i.Component{constructor(n){super(n),this.handleRetry=()=>{this.setState({hasError:!1,error:null,errorInfo:null})},this.state={hasError:!1,error:null,errorInfo:null}}static getDerivedStateFromError(n){return{hasError:!0,error:n}}componentDidCatch(n,p){this.setState({errorInfo:p}),this.props.onError&&this.props.onError(n,p)}render(){return this.state.hasError?s.jsx(X,{error:this.state.error,onRetry:this.handleRetry}):this.props.children}}const j=i.createContext(null),Y=()=>{const t=i.useContext(j);if(!t)throw new Error("useSDK must be used within a NotificationWidget");return t},Z={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}},ee=({config:t,children:n})=>{const[p,w]=i.useState({client:null,isInitialized:!1,error:null});return i.useEffect(()=>{let c=!0;return(async()=>{try{const l=window.__notificationSDK;if(l?.client&&JSON.stringify(l.config)===JSON.stringify(t)){c&&w({client:l.client,isInitialized:!0,error:null});return}const r=new H.NotificationClient({apiUrl:t.baseUrl,apiKey:t.apiKey,tenantId:t.tenantId,environmentId:t.environmentId});window.__notificationSDK={client:r,config:t},c&&w({client:r,isInitialized:!0,error:null})}catch(l){c&&w({client:null,isInitialized:!1,error:l})}})(),()=>{c=!1}},[t]),s.jsx(j.Provider,{value:p,children:n})},te=(t,n)=>{switch(n.type){case"SET_NOTIFICATIONS":return{...t,notifications:n.payload,unreadCount:n.payload.filter(f=>!f.isRead).length};case"ADD_NOTIFICATION":const p=[n.payload,...t.notifications];return{...t,notifications:p,unreadCount:p.filter(f=>!f.isRead).length};case"UPDATE_NOTIFICATION":const w=t.notifications.map(f=>f.id===n.payload.id?{...f,...n.payload.updates}:f);return{...t,notifications:w,unreadCount:w.filter(f=>!f.isRead).length};case"DELETE_NOTIFICATION":const c=t.notifications.filter(f=>f.id!==n.payload);return{...t,notifications:c,unreadCount:c.filter(f=>!f.isRead).length};case"SET_PREFERENCES":return{...t,preferences:n.payload};case"SET_UI_STATE":return{...t,ui:{...t.ui,...n.payload}};case"SET_WEBSOCKET_STATE":return{...t,websocket:{...t.websocket,...n.payload}};default:return t}},ne=({position:t="right",size:n="medium",theme:p="light",className:w="",onError:c,onMorePreferencesClick:f})=>{const[l,r]=i.useReducer(te,Z),{client:u,isInitialized:b,error:h}=Y(),g=i.useRef(null),k=i.useCallback(e=>{r({type:"SET_PREFERENCES",payload:e})},[]),T=i.useCallback(e=>{c&&c(e)},[c]),{error:S}=J({onPreferencesLoaded:k,onError:T}),{specificPreferences:d,isLoading:_,hasMore:N,loadMore:C}=Q(),{updatePreference:K,isSaving:O,error:D}=A.useLivePreferences({preferences:l.preferences,onPreferencesChange:k,onError:T});i.useEffect(()=>{if(d.length>0){const o=[...l.preferences.subscriptions];let a=!1;d.forEach(I=>{const m=o.findIndex(y=>y.workflowId===I.workflowId);if(m===-1)o.push(I),a=!0;else{const y=o[m];y.name===y.workflowId&&I.name&&I.name!==I.workflowId&&(o[m]={...y,name:I.name},a=!0)}}),a&&r({type:"SET_PREFERENCES",payload:{...l.preferences,subscriptions:o}})}},[d]);const R=i.useMemo(()=>d.map(e=>l.preferences.subscriptions.find(a=>a.workflowId===e.workflowId)||e),[d,l.preferences.subscriptions]),v=i.useCallback(e=>{try{const o=A.createNotificationMapper();switch(e.type){case"notification_received":{const a=e.data;if(!o.validateWebSocketPayload(a))break;const I=o.toWidgetNotificationFromWebSocket(a);r({type:"ADD_NOTIFICATION",payload:I});break}case"notification_updated":r({type:"UPDATE_NOTIFICATION",payload:{id:e.data.id||e.data.notificationId,updates:e.data}});break;case"notification_deleted":r({type:"DELETE_NOTIFICATION",payload:e.data.id||e.data.notificationId});break;case"preferences_updated":r({type:"SET_PREFERENCES",payload:e.data});break;default:}}catch{}},[]),W=i.useCallback(async()=>{if(!(!u||!b||g.current))try{r({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 I=`${u.getApiHost()}/v1/notifications`,m=z.io(I,{query:{tenantId:e.tenantId,subscriberId:e.subscriberId,environmentId:e.environmentId},transports:["websocket","polling"],autoConnect:!1,reconnection:!0,reconnectionAttempts:10,reconnectionDelay:1e3,reconnectionDelayMax:5e3});g.current=m;let y=null;const q=()=>{y&&clearInterval(y),y=setInterval(()=>{m.connected&&m.emit("ping",{timestamp:Date.now()})},3e3)},V=()=>{y&&(clearInterval(y),y=null)};m.on("notification",x=>{v({type:"notification_received",data:x})}),m.on("connect",()=>{r({type:"SET_WEBSOCKET_STATE",payload:{connected:!0,reconnecting:!1}}),q()}),m.on("disconnect",x=>{r({type:"SET_WEBSOCKET_STATE",payload:{connected:!1,reconnecting:!1}}),V()}),m.on("reconnect_attempt",x=>{r({type:"SET_WEBSOCKET_STATE",payload:{connected:!1,reconnecting:!0}})}),m.on("connect_error",x=>{r({type:"SET_WEBSOCKET_STATE",payload:{connected:!1,reconnecting:!1}}),c&&c(x)}),m.connect()}catch(e){r({type:"SET_WEBSOCKET_STATE",payload:{connected:!1,reconnecting:!1}}),c&&c(e)}},[u,b,v,c]),F=i.useCallback(()=>{if(g.current)try{g.current.disconnect&&g.current.disconnect(),g.current=null,r({type:"SET_WEBSOCKET_STATE",payload:{connected:!1,reconnecting:!1}})}catch{}},[]),M=i.useCallback(()=>{r({type:"SET_UI_STATE",payload:{isOpen:!l.ui.isOpen}})},[l.ui.isOpen]),L=i.useCallback(()=>{r({type:"SET_UI_STATE",payload:{isOpen:!1}})},[]),U=i.useCallback(e=>{r({type:"SET_UI_STATE",payload:{currentView:e}})},[]),B=i.useCallback(async(e,o)=>{if(!u||!b)return;const a=window.__notificationSDK?.config;if(a){if(!e)throw new Error("notificationId is required");try{switch(o.type){case"mark_read":await u.inbox.markAsRead(e,a.tenantId,a.environmentId,a.subscriberId);break;case"mark_unread":await u.inbox.markAsUnread(e,a.tenantId,a.environmentId,a.subscriberId);break;case"archive":await u.inbox.archive(e,a.tenantId,a.environmentId,a.subscriberId);break;case"delete":await u.inbox.delete(e,a.tenantId,a.environmentId,a.subscriberId);break;default:o.handler&&await o.handler(e);break}switch(o.type){case"mark_read":r({type:"UPDATE_NOTIFICATION",payload:{id:e,updates:{isRead:!0}}});break;case"mark_unread":r({type:"UPDATE_NOTIFICATION",payload:{id:e,updates:{isRead:!1}}});break;case"archive":r({type:"UPDATE_NOTIFICATION",payload:{id:e,updates:{isArchived:!0}}});break;case"delete":r({type:"DELETE_NOTIFICATION",payload:e});break}}catch(I){c&&c(I)}}},[u]);return i.useEffect(()=>{if(!u||!b)return;(async()=>{try{r({type:"SET_UI_STATE",payload:{isLoading:!0}});const o=window.__notificationSDK?.config;if(!o)throw new Error("SDK configuration not available");const a=A.createNotificationMapper(),m=((await u.inbox.getRenderedNotifications({channel:"in_app",limit:50,offset:0},o.tenantId,o.environmentId,o.subscriberId))?.items||[]).map(y=>a.toWidgetNotification(y));r({type:"SET_NOTIFICATIONS",payload:m}),r({type:"SET_UI_STATE",payload:{isLoading:!1,error:null}})}catch(o){r({type:"SET_UI_STATE",payload:{isLoading:!1,error:o}}),c&&c(o)}})()},[u,b,c]),i.useEffect(()=>(u&&b&&W(),()=>{F()}),[u]),i.useEffect(()=>{if(!u||!b||l.websocket.connected)return;const e=setInterval(async()=>{try{const o=window.__notificationSDK?.config;if(!o)return;const a=A.createNotificationMapper(),m=((await u.inbox.getRenderedNotifications({channel:"in_app",limit:50,offset:0},o.tenantId,o.environmentId,o.subscriberId))?.items||[]).map(y=>a.toWidgetNotification(y));r({type:"SET_NOTIFICATIONS",payload:m})}catch{}},3e4);return()=>clearInterval(e)},[u,l.websocket.connected]),i.useEffect(()=>{const e=o=>{if(o.key==="notification_widget_sync"&&o.newValue)try{const a=JSON.parse(o.newValue);v(a)}catch{}};return window.addEventListener("storage",e),()=>window.removeEventListener("storage",e)},[v]),i.useEffect(()=>{r({type:"SET_UI_STATE",payload:{isLoading:O}})},[O]),i.useEffect(()=>{const e=h||D||S;e&&r({type:"SET_UI_STATE",payload:{error:e}})},[h,D,S]),!b&&!h?s.jsx("div",{className:`mx-widget-root relative inline-block ${w}`,"data-mx-widget":"root","data-widget-size":n||"small","data-theme":p,"data-testid":"notification-widget",children:s.jsx(E.ComponentErrorBoundary,{componentName:"BellComponent",children:s.jsx(E.BellComponent,{unreadCount:0,onClick:()=>{},size:n,disabled:!0})})}):h?s.jsx("div",{className:`mx-widget-root relative inline-block ${w}`,"data-mx-widget":"root","data-widget-size":n||"small","data-theme":p,"data-testid":"notification-widget",children:s.jsx(E.ComponentErrorBoundary,{componentName:"BellComponent",fallback:s.jsx(E.SDKConnectionFallback,{error:h.message,onRetry:()=>window.location.reload()}),children:s.jsx(E.BellComponent,{unreadCount:0,onClick:()=>{},size:n,disabled:!0})})}):s.jsxs("div",{className:`mx-widget-root min-w-[20rem] relative inline-block ${w}`,"data-mx-widget":"root","data-widget-size":n||"small","data-theme":p,"data-testid":"notification-widget",children:[s.jsx(E.ComponentErrorBoundary,{componentName:"BellComponent",children:s.jsx(E.BellComponent,{unreadCount:l.unreadCount,onClick:M,size:n,disabled:l.ui.isLoading})}),s.jsx(E.ComponentErrorBoundary,{componentName:"InboxPopover",fallback:s.jsx(E.LoadingFallback,{message:"Unable to load notifications"}),children:s.jsx(E.InboxPopover,{isOpen:l.ui.isOpen,onClose:L,position:t,currentView:l.ui.currentView,onViewChange:U,notifications:l.notifications,onNotificationAction:B,preferences:l.preferences,onPreferenceChange:K,isPreferencesLoading:O,specificPreferences:R,onLoadMoreSpecific:C,hasMoreSpecific:N,isListLoading:_,onMorePreferencesClick:f})})]})},re=({sdkConfig:t,...n})=>s.jsx(P,{onError:n.onError,children:s.jsx(ee,{config:t,children:s.jsx(ne,{...n})})}),ie="3.0.0",oe="@edusight/notification-widget";exports.BellComponent=E.BellComponent;exports.InboxPopover=E.InboxPopover;exports.NotificationItem=E.NotificationItem;exports.PreferencesView=E.PreferencesView;exports.NotificationWidget=re;exports.NotificationWidgetErrorBoundary=P;exports.VERSION=ie;exports.WIDGET_NAME=oe;
4
4
  //# sourceMappingURL=index.cjs.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs.js","sources":["../src/hooks/usePreferencesSync.ts","../src/hooks/useSpecificPreferences.ts","../src/components/ErrorBoundary.tsx","../src/components/NotificationWidget.tsx","../src/index.ts"],"sourcesContent":["import { useEffect, useState, useCallback } from 'react';\n\nimport { NotificationPreferences } from '../types/core';\n\nconst useNotificationsClient = () => {\n return (window as any).__notificationSDK?.client;\n};\n\nexport interface UsePreferencesSyncProps {\n onPreferencesLoaded: (preferences: NotificationPreferences) => void;\n onError?: (error: Error) => void;\n}\n\nexport interface UsePreferencesSyncResult {\n isLoading: boolean;\n error: Error | null;\n preferences: NotificationPreferences | null;\n}\n\nexport const usePreferencesSync = ({\n onPreferencesLoaded,\n onError,\n}: UsePreferencesSyncProps): UsePreferencesSyncResult => {\n const notificationClient = useNotificationsClient();\n const [isLoading, setIsLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n const [preferences, setPreferences] = useState<NotificationPreferences | null>(null);\n\n const loadPreferences = useCallback(async () => {\n try {\n setIsLoading(true);\n setError(null);\n\n if (!notificationClient) {\n throw new Error('Notification client not available');\n }\n\n const config = (window as any).__notificationSDK?.config;\n\n if (!config) {\n throw new Error('SDK configuration not available');\n }\n\n const { subscriberId, tenantId, environmentId } = config;\n\n if (!subscriberId || !tenantId || !environmentId) {\n throw new Error('SubscriberId, TenantId or EnvironmentId not available in config');\n }\n\n const servicePreferences = await notificationClient.preferences.get(\n tenantId,\n subscriberId,\n environmentId,\n );\n\n // Fetch schedule separately\n let schedule = null;\n try {\n schedule = await notificationClient.preferences.getSchedule(\n tenantId,\n subscriberId,\n environmentId,\n );\n } catch (e) {\n console.warn('Failed to fetch schedule, using defaults:', e);\n }\n\n const mappedPreferences: NotificationPreferences = {\n channels: {\n email: servicePreferences.emailEnabled ?? true,\n push: servicePreferences.pushEnabled ?? true,\n sms: servicePreferences.smsEnabled ?? false,\n inApp: servicePreferences.inAppEnabled ?? true,\n },\n subscriptions: [],\n deliverySchedule: {\n enabled: schedule?.isEnabled || false,\n timezone: 'UTC',\n quietHours: {\n start: servicePreferences.quietHoursStart ?? '22:00',\n end: servicePreferences.quietHoursEnd ?? '08:00',\n },\n weekdays: schedule?.weeklySchedule\n ? [\n !!schedule.weeklySchedule.monday,\n !!schedule.weeklySchedule.tuesday,\n !!schedule.weeklySchedule.wednesday,\n !!schedule.weeklySchedule.thursday,\n !!schedule.weeklySchedule.friday,\n !!schedule.weeklySchedule.saturday,\n !!schedule.weeklySchedule.sunday,\n ]\n : [true, true, true, true, true, false, false],\n weeklySchedule: schedule?.weeklySchedule || undefined,\n },\n };\n\n if (servicePreferences.categories) {\n Object.entries(servicePreferences.categories).forEach(([workflowId, categoryPrefs]) => {\n mappedPreferences.subscriptions.push({\n workflowId,\n name: workflowId,\n enabled: true,\n channels: {\n email: (categoryPrefs as any).emailEnabled ?? true,\n push: (categoryPrefs as any).pushEnabled ?? true,\n sms: (categoryPrefs as any).smsEnabled ?? false,\n inApp: (categoryPrefs as any).inAppEnabled ?? true,\n },\n });\n });\n }\n\n setPreferences(mappedPreferences);\n onPreferencesLoaded(mappedPreferences);\n } catch (err: any) {\n const error = err instanceof Error ? err : new Error('Failed to load preferences');\n\n // If 404, it means preferences don't exist yet for this user.\n // We'll use defaults and suppress the error callback.\n const isNotFound = (err as any)?.response?.status === 404 || (err as any)?.status === 404;\n\n if (!isNotFound) {\n setError(error);\n onError?.(error);\n } else {\n console.warn('Preferences not found for user (404), using defaults.');\n }\n\n const defaultPreferences: NotificationPreferences = {\n channels: {\n email: true,\n push: true,\n sms: false,\n inApp: true,\n },\n subscriptions: [],\n deliverySchedule: {\n enabled: false,\n timezone: 'UTC',\n quietHours: {\n start: '22:00',\n end: '08:00',\n },\n weekdays: [true, true, true, true, true, false, false],\n },\n };\n setPreferences(defaultPreferences);\n onPreferencesLoaded(defaultPreferences);\n } finally {\n setIsLoading(false);\n }\n }, [notificationClient, onPreferencesLoaded, onError]);\n\n useEffect(() => {\n if (notificationClient) {\n loadPreferences();\n }\n }, [notificationClient, loadPreferences]);\n\n return {\n isLoading,\n error,\n preferences,\n };\n};\n","import { useState, useCallback, useEffect } from 'react';\n\nimport { WorkflowSubscription } from '../types/core';\n\nconst useNotificationsClient = () => {\n return (window as any).__notificationSDK?.client;\n};\n\nexport interface UseSpecificPreferencesResult {\n specificPreferences: WorkflowSubscription[];\n isLoading: boolean;\n hasMore: boolean;\n loadMore: () => Promise<void>;\n refetch: () => Promise<void>;\n}\n\nexport const useSpecificPreferences = (): UseSpecificPreferencesResult => {\n const client = useNotificationsClient();\n const [items, setItems] = useState<WorkflowSubscription[]>([]);\n const [isLoading, setIsLoading] = useState(false);\n const [hasMore, setHasMore] = useState(true);\n const [offset, setOffset] = useState(0);\n const LIMIT = 5;\n\n const loadMore = useCallback(async () => {\n if (!client || isLoading || !hasMore) return;\n\n try {\n setIsLoading(true);\n const sdkConfig = (window as any).__notificationSDK?.config;\n if (!sdkConfig) return;\n\n const response = await client.preferences.listSpecific(\n sdkConfig.tenantId,\n sdkConfig.subscriberId,\n {\n includeWorkflows: true,\n includeTemplates: false,\n activeOnly: true,\n limit: LIMIT,\n offset: offset,\n },\n );\n\n const newItems = (response.items || []).map((item: any) => ({\n workflowId: item.identifier,\n name: item.name,\n enabled: item.preference.enabled,\n channels: item.preference.channels,\n }));\n\n setItems((prev) => {\n // Determine uniqueness by workflowId to avoid duplicates if offset logic overlaps or double fetch\n const existingIds = new Set(prev.map((i) => i.workflowId));\n const uniqueNewItems = newItems.filter((i: any) => !existingIds.has(i.workflowId));\n return [...prev, ...uniqueNewItems];\n });\n\n setOffset((prev) => prev + LIMIT);\n\n // Check if we reached the end\n if (\n newItems.length < LIMIT ||\n (response.total !== undefined && items.length + newItems.length >= response.total)\n ) {\n setHasMore(false);\n }\n } catch (error) {\n console.error('Failed to load specific preferences:', error);\n // Don't disable hasMore on error, user can retry by scrolling\n } finally {\n setIsLoading(false);\n }\n }, [client, offset, hasMore, isLoading, items.length]);\n\n // Initial load\n useEffect(() => {\n if (client && offset === 0 && items.length === 0) {\n loadMore();\n }\n }, [client, loadMore, offset, items.length]);\n\n const refetch = async () => {\n setItems([]);\n setOffset(0);\n setHasMore(true);\n // Note: The effect will trigger loadMore because offset becomes 0 and items becomes empty\n };\n\n return {\n specificPreferences: items,\n isLoading,\n hasMore,\n loadMore,\n refetch,\n };\n};\n","import React, { Component, ErrorInfo, ReactNode } from 'react';\nimport { MdError, MdRefresh } from 'react-icons/md';\n\nimport { ErrorBoundaryState } from '../types/core';\n\ninterface ErrorBoundaryProps {\n children: ReactNode;\n onError?: (error: Error, errorInfo: ErrorInfo) => void;\n}\n\nconst ErrorFallback: React.FC<{\n error: Error | null;\n onRetry: () => void;\n}> = ({ error, onRetry }) => (\n <div\n className=\"p-4 bg-[var(--widget-error)]/10 border border-[var(--widget-error)]/20 rounded-lg\"\n role=\"alert\"\n data-testid=\"error-boundary-fallback\"\n >\n <div className=\"flex items-center mb-2\">\n <MdError className=\"w-6 h-6 text-[var(--widget-error)] mr-2\" aria-hidden=\"true\" />\n <h3 className=\"text-sm font-medium text-[var(--widget-error)]\">Something went wrong</h3>\n </div>\n\n <p className=\"text-sm mb-3 text-[var(--widget-error)]/80\">\n The notification widget encountered an error and couldn&apos;t load properly.\n </p>\n\n {process.env.NODE_ENV === 'development' && error && (\n <details className=\"mb-3\">\n <summary className=\"text-xs cursor-pointer text-[var(--widget-error)] hover:text-[var(--widget-error)]/80 transition-colors\">\n Error details (development only)\n </summary>\n <pre className=\"mt-2 text-xs bg-[var(--widget-error)]/5 p-2 rounded overflow-auto max-h-32 text-[var(--widget-error)]\">\n {error.message}\n {error.stack && `\\n\\n${error.stack}`}\n </pre>\n </details>\n )}\n\n <button\n type=\"button\"\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\"\n onClick={onRetry}\n data-testid=\"error-retry-button\"\n >\n <MdRefresh className=\"mr-1 w-4 h-4\" aria-hidden=\"true\" />\n Try again\n </button>\n </div>\n);\n\nexport class NotificationWidgetErrorBoundary extends Component<\n ErrorBoundaryProps,\n ErrorBoundaryState\n> {\n constructor(props: ErrorBoundaryProps) {\n super(props);\n this.state = {\n hasError: false,\n error: null,\n errorInfo: null,\n };\n }\n\n static getDerivedStateFromError(error: Error): Partial<ErrorBoundaryState> {\n return {\n hasError: true,\n error,\n };\n }\n\n componentDidCatch(error: Error, errorInfo: ErrorInfo) {\n this.setState({\n errorInfo,\n });\n\n console.error('NotificationWidget Error Boundary caught an error:', {\n message: error.message,\n stack: error.stack,\n componentStack: errorInfo.componentStack,\n timestamp: new Date().toISOString(),\n });\n\n if (this.props.onError) {\n this.props.onError(error, errorInfo);\n }\n }\n\n handleRetry = () => {\n this.setState({\n hasError: false,\n error: null,\n errorInfo: null,\n });\n };\n\n render() {\n if (this.state.hasError) {\n return <ErrorFallback error={this.state.error} onRetry={this.handleRetry} />;\n }\n\n return this.props.children;\n }\n}\n\nexport const useErrorHandler = () => {\n return (error: Error, errorInfo?: ErrorInfo) => {\n console.error('Widget error:', {\n message: error.message,\n stack: error.stack,\n errorInfo,\n timestamp: new Date().toISOString(),\n });\n };\n};\n","import { NotificationClient } from '@edusight/notification-sdk';\nimport React, {\n useReducer,\n useEffect,\n useCallback,\n createContext,\n useContext,\n useRef,\n} from 'react';\nimport { io as ioClient } from 'socket.io-client';\n\nimport { useLivePreferences } from '../hooks/useLivePreferences';\nimport { usePreferencesSync } from '../hooks/usePreferencesSync';\nimport { useSpecificPreferences } from '../hooks/useSpecificPreferences';\nimport {\n NotificationWidgetProps,\n WidgetState,\n WidgetAction,\n SDKConfiguration,\n} from '../types/core';\nimport { createNotificationMapper } from '../utils/notification-mapper';\n\nimport { BellComponent } from './BellComponent';\nimport { ComponentErrorBoundary } from './ComponentErrorBoundary';\nimport { NotificationWidgetErrorBoundary } from './ErrorBoundary';\nimport { SDKConnectionFallback, LoadingFallback } from './FallbackComponents';\nimport { InboxPopover } from './InboxPopover';\n\ninterface SDKContextType {\n client: any;\n isInitialized: boolean;\n error: Error | null;\n}\n\nconst SDKContext = createContext<SDKContextType | null>(null);\n\nexport const useSDK = () => {\n const context = useContext(SDKContext);\n if (!context) {\n throw new Error('useSDK must be used within a NotificationWidget');\n }\n return context;\n};\n\nconst initialState: WidgetState = {\n notifications: [],\n unreadCount: 0,\n preferences: {\n channels: {\n email: true,\n push: true,\n sms: false,\n inApp: true,\n },\n subscriptions: [],\n deliverySchedule: {\n timezone: 'UTC',\n quietHours: {\n start: '22:00',\n end: '08:00',\n },\n weekdays: [true, true, true, true, true, false, false],\n },\n },\n ui: {\n isOpen: false,\n currentView: 'notifications',\n selectedNotifications: [],\n isLoading: false,\n error: null,\n },\n websocket: {\n connected: false,\n reconnecting: false,\n },\n};\n\nconst SDKProvider: React.FC<{ config: SDKConfiguration; children: React.ReactNode }> = ({\n config,\n children,\n}) => {\n const [sdkState, setSdkState] = React.useState<SDKContextType>({\n client: null,\n isInitialized: false,\n error: null,\n });\n\n useEffect(() => {\n let isMounted = true;\n\n const initializeSDK = async () => {\n try {\n const existingSDK = (window as any).__notificationSDK;\n\n // Check if we can reuse the existing SDK instance\n if (existingSDK?.client) {\n // Compare new config with existing config to determine if we need to re-initialize\n // We use simple JSON stringify as configs are simple objects with strings/numbers\n const isConfigMatch = JSON.stringify(existingSDK.config) === JSON.stringify(config);\n\n if (isConfigMatch) {\n if (isMounted) {\n setSdkState({\n client: existingSDK.client,\n isInitialized: true,\n error: null,\n });\n }\n return;\n } else {\n console.log('[NotificationWidget] Config changed, re-initializing SDK', {\n old: existingSDK.config,\n new: config,\n });\n }\n }\n\n const client = new NotificationClient({\n apiUrl: config.baseUrl,\n apiKey: config.apiKey,\n tenantId: config.tenantId,\n environmentId: config.environmentId,\n });\n\n (window as any).__notificationSDK = { client, config };\n\n if (isMounted) {\n setSdkState({\n client,\n isInitialized: true,\n error: null,\n });\n }\n } catch (error) {\n console.error('Failed to initialize SDK:', error);\n if (isMounted) {\n setSdkState({\n client: null,\n isInitialized: false,\n error: error as Error,\n });\n }\n }\n };\n\n initializeSDK();\n\n return () => {\n isMounted = false;\n };\n }, [config]);\n\n return <SDKContext.Provider value={sdkState}>{children}</SDKContext.Provider>;\n};\n\nconst widgetReducer = (state: WidgetState, action: WidgetAction): WidgetState => {\n switch (action.type) {\n case 'SET_NOTIFICATIONS':\n return {\n ...state,\n notifications: action.payload,\n unreadCount: action.payload.filter((n) => !n.isRead).length,\n };\n\n case 'ADD_NOTIFICATION':\n const newNotifications = [action.payload, ...state.notifications];\n return {\n ...state,\n notifications: newNotifications,\n unreadCount: newNotifications.filter((n) => !n.isRead).length,\n };\n\n case 'UPDATE_NOTIFICATION':\n const updatedNotifications = state.notifications.map((n) =>\n n.id === action.payload.id ? { ...n, ...action.payload.updates } : n,\n );\n return {\n ...state,\n notifications: updatedNotifications,\n unreadCount: updatedNotifications.filter((n) => !n.isRead).length,\n };\n\n case 'DELETE_NOTIFICATION':\n const filteredNotifications = state.notifications.filter((n) => n.id !== action.payload);\n return {\n ...state,\n notifications: filteredNotifications,\n unreadCount: filteredNotifications.filter((n) => !n.isRead).length,\n };\n\n case 'SET_PREFERENCES':\n return {\n ...state,\n preferences: action.payload,\n };\n\n case 'SET_UI_STATE':\n return {\n ...state,\n ui: { ...state.ui, ...action.payload },\n };\n\n case 'SET_WEBSOCKET_STATE':\n return {\n ...state,\n websocket: { ...state.websocket, ...action.payload },\n };\n\n default:\n return state;\n }\n};\n\nconst NotificationWidgetInternal: React.FC<Omit<NotificationWidgetProps, 'sdkConfig'>> = ({\n position = 'right',\n size = 'medium',\n theme = 'light',\n className = '',\n\n onError,\n onMorePreferencesClick,\n}) => {\n const [state, dispatch] = useReducer(widgetReducer, initialState);\n const { client, isInitialized, error: sdkError } = useSDK();\n const websocketRef = useRef<any>(null);\n\n const handlePreferencesChange = useCallback((preferences: any) => {\n dispatch({\n type: 'SET_PREFERENCES',\n payload: preferences,\n });\n }, []);\n\n const handleWidgetError = useCallback(\n (error: Error) => {\n console.error('Widget error:', error);\n if (onError) {\n onError(error);\n }\n },\n [onError],\n );\n\n const { error: preferencesLoadError } = usePreferencesSync({\n onPreferencesLoaded: handlePreferencesChange,\n onError: handleWidgetError,\n });\n\n const {\n specificPreferences,\n isLoading: isSpecificLoading,\n hasMore: hasMoreSpecific,\n loadMore: loadMoreSpecific,\n } = useSpecificPreferences();\n\n const {\n updatePreference,\n isSaving,\n error: preferencesError,\n } = useLivePreferences({\n preferences: state.preferences,\n onPreferencesChange: handlePreferencesChange,\n onError: handleWidgetError,\n });\n\n // Merge specific preferences into state when they load\n useEffect(() => {\n if (specificPreferences.length > 0) {\n const currentSubs = state.preferences.subscriptions;\n const newSubs = [...currentSubs];\n let changed = false;\n\n specificPreferences.forEach((sp) => {\n const existingIdx = newSubs.findIndex((s) => s.workflowId === sp.workflowId);\n\n // If not in state, add it\n if (existingIdx === -1) {\n newSubs.push(sp);\n changed = true;\n } else {\n // If existing name is just the ID (default), update with real name from specific prefs\n const existing = newSubs[existingIdx];\n if (existing.name === existing.workflowId && sp.name && sp.name !== sp.workflowId) {\n newSubs[existingIdx] = { ...existing, name: sp.name };\n changed = true;\n }\n }\n });\n\n if (changed) {\n dispatch({\n type: 'SET_PREFERENCES',\n payload: {\n ...state.preferences,\n subscriptions: newSubs,\n },\n });\n }\n }\n }, [specificPreferences]); // Depend on specificPreferences list changes (load more)\n\n // Create display list that respects order from hook but values from state\n const displaySpecificPreferences = React.useMemo(() => {\n return specificPreferences.map((sp) => {\n const found = state.preferences.subscriptions.find((s) => s.workflowId === sp.workflowId);\n return found || sp;\n });\n }, [specificPreferences, state.preferences.subscriptions]);\n\n const handleWebSocketEvent = useCallback((event: any) => {\n try {\n const notificationMapper = createNotificationMapper();\n\n switch (event.type) {\n case 'notification_received': {\n const wsPayload = event.data;\n\n if (!notificationMapper.validateWebSocketPayload(wsPayload)) {\n console.error('Invalid WebSocket notification payload, skipping', wsPayload);\n break;\n }\n\n const mappedNotification =\n notificationMapper.toWidgetNotificationFromWebSocket(wsPayload);\n dispatch({\n type: 'ADD_NOTIFICATION',\n payload: mappedNotification,\n });\n break;\n }\n\n case 'notification_updated':\n dispatch({\n type: 'UPDATE_NOTIFICATION',\n payload: {\n id: event.data.id || event.data.notificationId,\n updates: event.data,\n },\n });\n break;\n\n case 'notification_deleted':\n dispatch({\n type: 'DELETE_NOTIFICATION',\n payload: event.data.id || event.data.notificationId,\n });\n break;\n\n case 'preferences_updated':\n dispatch({\n type: 'SET_PREFERENCES',\n payload: event.data,\n });\n break;\n\n default:\n console.log('Unknown WebSocket event type:', event.type);\n }\n } catch (error) {\n console.error('Error handling WebSocket event:', error);\n }\n }, []);\n\n const connectWebSocket = useCallback(async () => {\n if (!client || !isInitialized || websocketRef.current) return;\n\n try {\n dispatch({\n type: 'SET_WEBSOCKET_STATE',\n payload: { reconnecting: true },\n });\n\n const sdkConfig = (window as any).__notificationSDK?.config;\n if (!sdkConfig) {\n throw new Error('SDK configuration not available for WebSocket connection');\n }\n\n const baseUrl = client.getApiHost();\n const namespace = '/v1/notifications';\n const fullUrl = `${baseUrl}${namespace}`;\n\n console.log('Connecting to Socket.IO at:', fullUrl);\n\n const socket = ioClient(fullUrl, {\n query: {\n tenantId: sdkConfig.tenantId,\n subscriberId: sdkConfig.subscriberId,\n environmentId: sdkConfig.environmentId,\n },\n transports: ['websocket'],\n autoConnect: false,\n reconnection: true,\n reconnectionAttempts: 10,\n reconnectionDelay: 1000,\n reconnectionDelayMax: 5000,\n });\n\n websocketRef.current = socket;\n\n socket.on('notification', (payload: any) => {\n console.log('Received notification:', payload);\n handleWebSocketEvent({\n type: 'notification_received',\n data: payload,\n });\n });\n\n socket.on('connect', () => {\n console.log('Socket.IO connected successfully');\n dispatch({\n type: 'SET_WEBSOCKET_STATE',\n payload: { connected: true, reconnecting: false },\n });\n });\n\n socket.on('disconnect', (reason: any) => {\n console.log('Socket.IO disconnected:', reason);\n dispatch({\n type: 'SET_WEBSOCKET_STATE',\n payload: { connected: false, reconnecting: false },\n });\n });\n\n socket.on('reconnect_attempt', (attempt: any) => {\n console.log('Socket.IO reconnection attempt:', attempt);\n dispatch({\n type: 'SET_WEBSOCKET_STATE',\n payload: { connected: false, reconnecting: true },\n });\n });\n\n socket.on('connect_error', (error: any) => {\n console.error('Socket.IO connection error:', error);\n dispatch({\n type: 'SET_WEBSOCKET_STATE',\n payload: { connected: false, reconnecting: false },\n });\n if (onError) {\n onError(error);\n }\n });\n\n socket.connect();\n } catch (error) {\n console.error('Failed to connect WebSocket:', error);\n dispatch({\n type: 'SET_WEBSOCKET_STATE',\n payload: { connected: false, reconnecting: false },\n });\n if (onError) {\n onError(error as Error);\n }\n }\n }, [client, isInitialized, handleWebSocketEvent, onError]);\n\n const disconnectWebSocket = useCallback(() => {\n if (websocketRef.current) {\n try {\n if (websocketRef.current.disconnect) {\n websocketRef.current.disconnect();\n }\n websocketRef.current = null;\n dispatch({\n type: 'SET_WEBSOCKET_STATE',\n payload: { connected: false, reconnecting: false },\n });\n } catch (error) {\n console.error('Error disconnecting WebSocket:', error);\n }\n }\n }, []);\n\n const handleBellClick = useCallback(() => {\n dispatch({\n type: 'SET_UI_STATE',\n payload: { isOpen: !state.ui.isOpen },\n });\n }, [state.ui.isOpen]);\n\n const handlePopoverClose = useCallback(() => {\n dispatch({\n type: 'SET_UI_STATE',\n payload: { isOpen: false },\n });\n }, []);\n\n const handleViewChange = useCallback((view: 'notifications' | 'preferences') => {\n dispatch({\n type: 'SET_UI_STATE',\n payload: { currentView: view },\n });\n }, []);\n\n const handleNotificationAction = useCallback(\n async (id: string, action: any) => {\n if (!client || !isInitialized) {\n console.error('SDK not initialized');\n return;\n }\n\n const sdkConfig = (window as any).__notificationSDK?.config;\n if (!sdkConfig) {\n console.error('SDK configuration not available');\n return;\n }\n\n if (!id) {\n console.error('notificationId is required');\n throw new Error('notificationId is required');\n }\n\n try {\n switch (action.type) {\n case 'mark_read':\n await client.inbox.markAsRead(\n id,\n sdkConfig.tenantId,\n sdkConfig.environmentId,\n sdkConfig.subscriberId,\n );\n break;\n case 'mark_unread':\n await client.inbox.markAsUnread(\n id,\n sdkConfig.tenantId,\n sdkConfig.environmentId,\n sdkConfig.subscriberId,\n );\n break;\n case 'archive':\n await client.inbox.archive(\n id,\n sdkConfig.tenantId,\n sdkConfig.environmentId,\n sdkConfig.subscriberId,\n );\n break;\n case 'delete':\n await client.inbox.delete(\n id,\n sdkConfig.tenantId,\n sdkConfig.environmentId,\n sdkConfig.subscriberId,\n );\n break;\n default:\n if (action.handler) {\n await action.handler(id);\n }\n break;\n }\n\n switch (action.type) {\n case 'mark_read':\n dispatch({\n type: 'UPDATE_NOTIFICATION',\n payload: { id, updates: { isRead: true } },\n });\n break;\n case 'mark_unread':\n dispatch({\n type: 'UPDATE_NOTIFICATION',\n payload: { id, updates: { isRead: false } },\n });\n break;\n case 'archive':\n dispatch({\n type: 'UPDATE_NOTIFICATION',\n payload: { id, updates: { isArchived: true } },\n });\n break;\n case 'delete':\n dispatch({\n type: 'DELETE_NOTIFICATION',\n payload: id,\n });\n break;\n }\n } catch (error) {\n console.error('Error performing notification action:', error);\n if (onError) {\n onError(error as Error);\n }\n }\n },\n [client],\n );\n\n useEffect(() => {\n if (!client || !isInitialized) return;\n\n const loadNotifications = async () => {\n try {\n dispatch({\n type: 'SET_UI_STATE',\n payload: { isLoading: true },\n });\n\n const sdkConfig = (window as any).__notificationSDK?.config;\n if (!sdkConfig) {\n throw new Error('SDK configuration not available');\n }\n\n const notificationMapper = createNotificationMapper();\n const response = await client.inbox.getRenderedNotifications(\n {\n channel: 'in_app',\n limit: 50,\n offset: 0,\n },\n sdkConfig.tenantId,\n sdkConfig.environmentId,\n sdkConfig.subscriberId,\n );\n\n const coreNotifications = (response?.items || []).map((item: any) =>\n notificationMapper.toWidgetNotification(item),\n );\n\n dispatch({\n type: 'SET_NOTIFICATIONS',\n payload: coreNotifications,\n });\n\n dispatch({\n type: 'SET_UI_STATE',\n payload: { isLoading: false, error: null },\n });\n } catch (error) {\n console.error('Failed to load notifications:', error);\n dispatch({\n type: 'SET_UI_STATE',\n payload: {\n isLoading: false,\n error: error as Error,\n },\n });\n if (onError) {\n onError(error as Error);\n }\n }\n };\n\n loadNotifications();\n }, [client, isInitialized, onError]);\n\n useEffect(() => {\n if (client && isInitialized) {\n connectWebSocket();\n }\n\n return () => {\n disconnectWebSocket();\n };\n }, [client]);\n\n useEffect(() => {\n if (!client || !isInitialized) return;\n\n if (state.websocket.connected) return;\n\n const pollInterval = setInterval(async () => {\n try {\n const sdkConfig = (window as any).__notificationSDK?.config;\n if (!sdkConfig) {\n return;\n }\n\n const notificationMapper = createNotificationMapper();\n const response = await client.inbox.getRenderedNotifications(\n {\n channel: 'in_app',\n limit: 50,\n offset: 0,\n },\n sdkConfig.tenantId,\n sdkConfig.environmentId,\n sdkConfig.subscriberId,\n );\n\n const coreNotifications = (response?.items || []).map((item: any) =>\n notificationMapper.toWidgetNotification(item),\n );\n\n dispatch({\n type: 'SET_NOTIFICATIONS',\n payload: coreNotifications,\n });\n } catch (error) {\n console.error('Polling failed:', error);\n }\n }, 30000);\n\n return () => clearInterval(pollInterval);\n }, [client, state.websocket.connected]);\n\n useEffect(() => {\n const handleStorageChange = (event: StorageEvent) => {\n if (event.key === 'notification_widget_sync' && event.newValue) {\n try {\n const syncData = JSON.parse(event.newValue);\n handleWebSocketEvent(syncData);\n } catch (error) {\n console.error('Error parsing sync data:', error);\n }\n }\n };\n\n window.addEventListener('storage', handleStorageChange);\n return () => window.removeEventListener('storage', handleStorageChange);\n }, [handleWebSocketEvent]);\n\n useEffect(() => {\n dispatch({\n type: 'SET_UI_STATE',\n payload: { isLoading: isSaving },\n });\n }, [isSaving]);\n\n useEffect(() => {\n const error = sdkError || preferencesError || preferencesLoadError;\n if (error) {\n dispatch({\n type: 'SET_UI_STATE',\n payload: { error: error },\n });\n }\n }, [sdkError, preferencesError, preferencesLoadError]);\n\n if (!isInitialized && !sdkError) {\n return (\n <div\n className={`mx-widget-root relative inline-block ${className}`}\n data-mx-widget=\"root\"\n data-widget-size={size || 'small'}\n data-theme={theme}\n data-testid=\"notification-widget\"\n >\n <ComponentErrorBoundary componentName=\"BellComponent\">\n <BellComponent unreadCount={0} onClick={() => { }} size={size} disabled={true} />\n </ComponentErrorBoundary>\n </div>\n );\n }\n\n if (sdkError) {\n return (\n <div\n className={`mx-widget-root relative inline-block ${className}`}\n data-mx-widget=\"root\"\n data-widget-size={size || 'small'}\n data-theme={theme}\n data-testid=\"notification-widget\"\n >\n <ComponentErrorBoundary\n componentName=\"BellComponent\"\n fallback={\n <SDKConnectionFallback\n error={sdkError.message}\n onRetry={() => window.location.reload()}\n />\n }\n >\n <BellComponent unreadCount={0} onClick={() => { }} size={size} disabled={true} />\n </ComponentErrorBoundary>\n </div>\n );\n }\n\n return (\n <div\n className={`mx-widget-root min-w-[20rem] relative inline-block ${className}`}\n data-mx-widget=\"root\"\n data-widget-size={size || 'small'}\n data-theme={theme}\n data-testid=\"notification-widget\"\n >\n <ComponentErrorBoundary componentName=\"BellComponent\">\n <BellComponent\n unreadCount={state.unreadCount}\n onClick={handleBellClick}\n size={size}\n disabled={state.ui.isLoading}\n />\n </ComponentErrorBoundary>\n\n <ComponentErrorBoundary\n componentName=\"InboxPopover\"\n fallback={<LoadingFallback message=\"Unable to load notifications\" />}\n >\n <InboxPopover\n isOpen={state.ui.isOpen}\n onClose={handlePopoverClose}\n position={position}\n currentView={state.ui.currentView}\n onViewChange={handleViewChange}\n notifications={state.notifications}\n onNotificationAction={handleNotificationAction}\n preferences={state.preferences}\n onPreferenceChange={updatePreference}\n isPreferencesLoading={isSaving}\n specificPreferences={displaySpecificPreferences}\n onLoadMoreSpecific={loadMoreSpecific}\n hasMoreSpecific={hasMoreSpecific}\n isListLoading={isSpecificLoading}\n onMorePreferencesClick={onMorePreferencesClick}\n />\n </ComponentErrorBoundary>\n </div>\n );\n};\n\nexport const NotificationWidget: React.FC<NotificationWidgetProps> = ({ sdkConfig, ...props }) => {\n return (\n <NotificationWidgetErrorBoundary onError={props.onError}>\n <SDKProvider config={sdkConfig}>\n <NotificationWidgetInternal {...props} />\n </SDKProvider>\n </NotificationWidgetErrorBoundary>\n );\n};\n","export { NotificationWidget } from './components/NotificationWidget';\n\nexport { BellComponent } from './components/BellComponent';\nexport { InboxPopover } from './components/InboxPopover';\nexport { NotificationItem } from './components/NotificationItem';\nexport { PreferencesView } from './components/PreferencesView';\n\nexport { NotificationWidgetErrorBoundary } from './components/ErrorBoundary';\n\nexport type * from './types/core';\n\nexport type {\n Notification as SDKNotification,\n NotificationFilters,\n} from '@edusight/notification-sdk';\n\nimport '../src/styles/index.css';\n\nexport const VERSION = '3.0.0';\nexport const WIDGET_NAME = '@edusight/notification-widget';\n"],"names":["useNotificationsClient","usePreferencesSync","onPreferencesLoaded","onError","notificationClient","isLoading","setIsLoading","useState","error","setError","preferences","setPreferences","loadPreferences","useCallback","config","subscriberId","tenantId","environmentId","servicePreferences","schedule","mappedPreferences","workflowId","categoryPrefs","err","defaultPreferences","useEffect","useSpecificPreferences","client","items","setItems","hasMore","setHasMore","offset","setOffset","LIMIT","loadMore","sdkConfig","response","newItems","item","prev","existingIds","i","uniqueNewItems","ErrorFallback","onRetry","jsxs","jsx","MdError","MdRefresh","NotificationWidgetErrorBoundary","Component","props","errorInfo","SDKContext","createContext","useSDK","context","useContext","initialState","SDKProvider","children","sdkState","setSdkState","React","isMounted","existingSDK","NotificationClient","widgetReducer","state","action","n","newNotifications","updatedNotifications","filteredNotifications","NotificationWidgetInternal","position","size","theme","className","onMorePreferencesClick","dispatch","useReducer","isInitialized","sdkError","websocketRef","useRef","handlePreferencesChange","handleWidgetError","preferencesLoadError","specificPreferences","isSpecificLoading","hasMoreSpecific","loadMoreSpecific","updatePreference","isSaving","preferencesError","useLivePreferences","newSubs","changed","sp","existingIdx","s","existing","displaySpecificPreferences","handleWebSocketEvent","event","notificationMapper","createNotificationMapper","wsPayload","mappedNotification","connectWebSocket","fullUrl","socket","ioClient","payload","reason","attempt","disconnectWebSocket","handleBellClick","handlePopoverClose","handleViewChange","view","handleNotificationAction","id","coreNotifications","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/hooks/usePreferencesSync.ts","../src/hooks/useSpecificPreferences.ts","../src/components/ErrorBoundary.tsx","../src/components/NotificationWidget.tsx","../src/index.ts"],"sourcesContent":["import { useEffect, useState, useCallback } from 'react';\n\nimport { NotificationPreferences } from '../types/core';\n\nconst useNotificationsClient = () => {\n return (window as any).__notificationSDK?.client;\n};\n\nexport interface UsePreferencesSyncProps {\n onPreferencesLoaded: (preferences: NotificationPreferences) => void;\n onError?: (error: Error) => void;\n}\n\nexport interface UsePreferencesSyncResult {\n isLoading: boolean;\n error: Error | null;\n preferences: NotificationPreferences | null;\n}\n\nexport const usePreferencesSync = ({\n onPreferencesLoaded,\n onError,\n}: UsePreferencesSyncProps): UsePreferencesSyncResult => {\n const notificationClient = useNotificationsClient();\n const [isLoading, setIsLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n const [preferences, setPreferences] = useState<NotificationPreferences | null>(null);\n\n const loadPreferences = useCallback(async () => {\n try {\n setIsLoading(true);\n setError(null);\n\n if (!notificationClient) {\n throw new Error('Notification client not available');\n }\n\n const config = (window as any).__notificationSDK?.config;\n\n if (!config) {\n throw new Error('SDK configuration not available');\n }\n\n const { subscriberId, tenantId, environmentId } = config;\n\n if (!subscriberId || !tenantId || !environmentId) {\n throw new Error('SubscriberId, TenantId or EnvironmentId not available in config');\n }\n\n const servicePreferences = await notificationClient.preferences.get(\n tenantId,\n subscriberId,\n environmentId,\n );\n\n // Fetch schedule separately\n let schedule = null;\n try {\n schedule = await notificationClient.preferences.getSchedule(\n tenantId,\n subscriberId,\n environmentId,\n );\n } catch (e) {\n console.warn('Failed to fetch schedule, using defaults:', e);\n }\n\n const mappedPreferences: NotificationPreferences = {\n channels: {\n email: servicePreferences.emailEnabled ?? true,\n push: servicePreferences.pushEnabled ?? true,\n sms: servicePreferences.smsEnabled ?? false,\n inApp: servicePreferences.inAppEnabled ?? true,\n },\n subscriptions: [],\n deliverySchedule: {\n enabled: schedule?.isEnabled || false,\n timezone: 'UTC',\n quietHours: {\n start: servicePreferences.quietHoursStart ?? '22:00',\n end: servicePreferences.quietHoursEnd ?? '08:00',\n },\n weekdays: schedule?.weeklySchedule\n ? [\n !!schedule.weeklySchedule.monday,\n !!schedule.weeklySchedule.tuesday,\n !!schedule.weeklySchedule.wednesday,\n !!schedule.weeklySchedule.thursday,\n !!schedule.weeklySchedule.friday,\n !!schedule.weeklySchedule.saturday,\n !!schedule.weeklySchedule.sunday,\n ]\n : [true, true, true, true, true, false, false],\n weeklySchedule: schedule?.weeklySchedule || undefined,\n },\n };\n\n if (servicePreferences.categories) {\n Object.entries(servicePreferences.categories).forEach(([workflowId, categoryPrefs]) => {\n mappedPreferences.subscriptions.push({\n workflowId,\n name: workflowId,\n enabled: true,\n channels: {\n email: (categoryPrefs as any).emailEnabled ?? true,\n push: (categoryPrefs as any).pushEnabled ?? true,\n sms: (categoryPrefs as any).smsEnabled ?? false,\n inApp: (categoryPrefs as any).inAppEnabled ?? true,\n },\n });\n });\n }\n\n setPreferences(mappedPreferences);\n onPreferencesLoaded(mappedPreferences);\n } catch (err: any) {\n const error = err instanceof Error ? err : new Error('Failed to load preferences');\n\n // If 404, it means preferences don't exist yet for this user.\n // We'll use defaults and suppress the error callback.\n const isNotFound = (err as any)?.response?.status === 404 || (err as any)?.status === 404;\n\n if (!isNotFound) {\n setError(error);\n onError?.(error);\n } else {\n console.warn('Preferences not found for user (404), using defaults.');\n }\n\n const defaultPreferences: NotificationPreferences = {\n channels: {\n email: true,\n push: true,\n sms: false,\n inApp: true,\n },\n subscriptions: [],\n deliverySchedule: {\n enabled: false,\n timezone: 'UTC',\n quietHours: {\n start: '22:00',\n end: '08:00',\n },\n weekdays: [true, true, true, true, true, false, false],\n },\n };\n setPreferences(defaultPreferences);\n onPreferencesLoaded(defaultPreferences);\n } finally {\n setIsLoading(false);\n }\n }, [notificationClient, onPreferencesLoaded, onError]);\n\n useEffect(() => {\n if (notificationClient) {\n loadPreferences();\n }\n }, [notificationClient, loadPreferences]);\n\n return {\n isLoading,\n error,\n preferences,\n };\n};\n","import { useState, useCallback, useEffect } from 'react';\n\nimport { WorkflowSubscription } from '../types/core';\n\nconst useNotificationsClient = () => {\n return (window as any).__notificationSDK?.client;\n};\n\nexport interface UseSpecificPreferencesResult {\n specificPreferences: WorkflowSubscription[];\n isLoading: boolean;\n hasMore: boolean;\n loadMore: () => Promise<void>;\n refetch: () => Promise<void>;\n}\n\nexport const useSpecificPreferences = (): UseSpecificPreferencesResult => {\n const client = useNotificationsClient();\n const [items, setItems] = useState<WorkflowSubscription[]>([]);\n const [isLoading, setIsLoading] = useState(false);\n const [hasMore, setHasMore] = useState(true);\n const [offset, setOffset] = useState(0);\n const LIMIT = 5;\n\n const loadMore = useCallback(async () => {\n if (!client || isLoading || !hasMore) return;\n\n try {\n setIsLoading(true);\n const sdkConfig = (window as any).__notificationSDK?.config;\n if (!sdkConfig) return;\n\n const response = await client.preferences.listSpecific(\n sdkConfig.tenantId,\n sdkConfig.subscriberId,\n {\n includeWorkflows: true,\n includeTemplates: false,\n activeOnly: true,\n limit: LIMIT,\n offset: offset,\n },\n );\n\n const newItems = (response.items || []).map((item: any) => ({\n workflowId: item.identifier,\n name: item.name,\n enabled: item.preference.enabled,\n channels: item.preference.channels,\n }));\n\n setItems((prev) => {\n // Determine uniqueness by workflowId to avoid duplicates if offset logic overlaps or double fetch\n const existingIds = new Set(prev.map((i) => i.workflowId));\n const uniqueNewItems = newItems.filter((i: any) => !existingIds.has(i.workflowId));\n return [...prev, ...uniqueNewItems];\n });\n\n setOffset((prev) => prev + LIMIT);\n\n // Check if we reached the end\n if (\n newItems.length < LIMIT ||\n (response.total !== undefined && items.length + newItems.length >= response.total)\n ) {\n setHasMore(false);\n }\n } catch (error) {\n console.error('Failed to load specific preferences:', error);\n // Don't disable hasMore on error, user can retry by scrolling\n } finally {\n setIsLoading(false);\n }\n }, [client, offset, hasMore, isLoading, items.length]);\n\n // Initial load\n useEffect(() => {\n if (client && offset === 0 && items.length === 0) {\n loadMore();\n }\n }, [client, loadMore, offset, items.length]);\n\n const refetch = async () => {\n setItems([]);\n setOffset(0);\n setHasMore(true);\n // Note: The effect will trigger loadMore because offset becomes 0 and items becomes empty\n };\n\n return {\n specificPreferences: items,\n isLoading,\n hasMore,\n loadMore,\n refetch,\n };\n};\n","import React, { Component, ErrorInfo, ReactNode } from 'react';\nimport { MdError, MdRefresh } from 'react-icons/md';\n\nimport { ErrorBoundaryState } from '../types/core';\n\ninterface ErrorBoundaryProps {\n children: ReactNode;\n onError?: (error: Error, errorInfo: ErrorInfo) => void;\n}\n\nconst ErrorFallback: React.FC<{\n error: Error | null;\n onRetry: () => void;\n}> = ({ error, onRetry }) => (\n <div\n className=\"p-4 bg-[var(--widget-error)]/10 border border-[var(--widget-error)]/20 rounded-lg\"\n role=\"alert\"\n data-testid=\"error-boundary-fallback\"\n >\n <div className=\"flex items-center mb-2\">\n <MdError className=\"w-6 h-6 text-[var(--widget-error)] mr-2\" aria-hidden=\"true\" />\n <h3 className=\"text-sm font-medium text-[var(--widget-error)]\">Something went wrong</h3>\n </div>\n\n <p className=\"text-sm mb-3 text-[var(--widget-error)]/80\">\n The notification widget encountered an error and couldn&apos;t load properly.\n </p>\n\n {process.env.NODE_ENV === 'development' && error && (\n <details className=\"mb-3\">\n <summary className=\"text-xs cursor-pointer text-[var(--widget-error)] hover:text-[var(--widget-error)]/80 transition-colors\">\n Error details (development only)\n </summary>\n <pre className=\"mt-2 text-xs bg-[var(--widget-error)]/5 p-2 rounded overflow-auto max-h-32 text-[var(--widget-error)]\">\n {error.message}\n {error.stack && `\\n\\n${error.stack}`}\n </pre>\n </details>\n )}\n\n <button\n type=\"button\"\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\"\n onClick={onRetry}\n data-testid=\"error-retry-button\"\n >\n <MdRefresh className=\"mr-1 w-4 h-4\" aria-hidden=\"true\" />\n Try again\n </button>\n </div>\n);\n\nexport class NotificationWidgetErrorBoundary extends Component<\n ErrorBoundaryProps,\n ErrorBoundaryState\n> {\n constructor(props: ErrorBoundaryProps) {\n super(props);\n this.state = {\n hasError: false,\n error: null,\n errorInfo: null,\n };\n }\n\n static getDerivedStateFromError(error: Error): Partial<ErrorBoundaryState> {\n return {\n hasError: true,\n error,\n };\n }\n\n componentDidCatch(error: Error, errorInfo: ErrorInfo) {\n this.setState({\n errorInfo,\n });\n\n console.error('NotificationWidget Error Boundary caught an error:', {\n message: error.message,\n stack: error.stack,\n componentStack: errorInfo.componentStack,\n timestamp: new Date().toISOString(),\n });\n\n if (this.props.onError) {\n this.props.onError(error, errorInfo);\n }\n }\n\n handleRetry = () => {\n this.setState({\n hasError: false,\n error: null,\n errorInfo: null,\n });\n };\n\n render() {\n if (this.state.hasError) {\n return <ErrorFallback error={this.state.error} onRetry={this.handleRetry} />;\n }\n\n return this.props.children;\n }\n}\n\nexport const useErrorHandler = () => {\n return (error: Error, errorInfo?: ErrorInfo) => {\n console.error('Widget error:', {\n message: error.message,\n stack: error.stack,\n errorInfo,\n timestamp: new Date().toISOString(),\n });\n };\n};\n","import { NotificationClient } from '@edusight/notification-sdk';\nimport React, {\n useReducer,\n useEffect,\n useCallback,\n createContext,\n useContext,\n useRef,\n} from 'react';\nimport { io as ioClient } from 'socket.io-client';\n\nimport { useLivePreferences } from '../hooks/useLivePreferences';\nimport { usePreferencesSync } from '../hooks/usePreferencesSync';\nimport { useSpecificPreferences } from '../hooks/useSpecificPreferences';\nimport {\n NotificationWidgetProps,\n WidgetState,\n WidgetAction,\n SDKConfiguration,\n} from '../types/core';\nimport { createNotificationMapper } from '../utils/notification-mapper';\n\nimport { BellComponent } from './BellComponent';\nimport { ComponentErrorBoundary } from './ComponentErrorBoundary';\nimport { NotificationWidgetErrorBoundary } from './ErrorBoundary';\nimport { SDKConnectionFallback, LoadingFallback } from './FallbackComponents';\nimport { InboxPopover } from './InboxPopover';\n\ninterface SDKContextType {\n client: any;\n isInitialized: boolean;\n error: Error | null;\n}\n\nconst SDKContext = createContext<SDKContextType | null>(null);\n\nexport const useSDK = () => {\n const context = useContext(SDKContext);\n if (!context) {\n throw new Error('useSDK must be used within a NotificationWidget');\n }\n return context;\n};\n\nconst initialState: WidgetState = {\n notifications: [],\n unreadCount: 0,\n preferences: {\n channels: {\n email: true,\n push: true,\n sms: false,\n inApp: true,\n },\n subscriptions: [],\n deliverySchedule: {\n timezone: 'UTC',\n quietHours: {\n start: '22:00',\n end: '08:00',\n },\n weekdays: [true, true, true, true, true, false, false],\n },\n },\n ui: {\n isOpen: false,\n currentView: 'notifications',\n selectedNotifications: [],\n isLoading: false,\n error: null,\n },\n websocket: {\n connected: false,\n reconnecting: false,\n },\n};\n\nconst SDKProvider: React.FC<{ config: SDKConfiguration; children: React.ReactNode }> = ({\n config,\n children,\n}) => {\n const [sdkState, setSdkState] = React.useState<SDKContextType>({\n client: null,\n isInitialized: false,\n error: null,\n });\n\n useEffect(() => {\n let isMounted = true;\n\n const initializeSDK = async () => {\n try {\n const existingSDK = (window as any).__notificationSDK;\n\n // Check if we can reuse the existing SDK instance\n if (existingSDK?.client) {\n // Compare new config with existing config to determine if we need to re-initialize\n // We use simple JSON stringify as configs are simple objects with strings/numbers\n const isConfigMatch = JSON.stringify(existingSDK.config) === JSON.stringify(config);\n\n if (isConfigMatch) {\n if (isMounted) {\n setSdkState({\n client: existingSDK.client,\n isInitialized: true,\n error: null,\n });\n }\n return;\n } else {\n console.log('[NotificationWidget] Config changed, re-initializing SDK', {\n old: existingSDK.config,\n new: config,\n });\n }\n }\n\n const client = new NotificationClient({\n apiUrl: config.baseUrl,\n apiKey: config.apiKey,\n tenantId: config.tenantId,\n environmentId: config.environmentId,\n });\n\n (window as any).__notificationSDK = { client, config };\n\n if (isMounted) {\n setSdkState({\n client,\n isInitialized: true,\n error: null,\n });\n }\n } catch (error) {\n console.error('Failed to initialize SDK:', error);\n if (isMounted) {\n setSdkState({\n client: null,\n isInitialized: false,\n error: error as Error,\n });\n }\n }\n };\n\n initializeSDK();\n\n return () => {\n isMounted = false;\n };\n }, [config]);\n\n return <SDKContext.Provider value={sdkState}>{children}</SDKContext.Provider>;\n};\n\nconst widgetReducer = (state: WidgetState, action: WidgetAction): WidgetState => {\n switch (action.type) {\n case 'SET_NOTIFICATIONS':\n return {\n ...state,\n notifications: action.payload,\n unreadCount: action.payload.filter((n) => !n.isRead).length,\n };\n\n case 'ADD_NOTIFICATION':\n const newNotifications = [action.payload, ...state.notifications];\n return {\n ...state,\n notifications: newNotifications,\n unreadCount: newNotifications.filter((n) => !n.isRead).length,\n };\n\n case 'UPDATE_NOTIFICATION':\n const updatedNotifications = state.notifications.map((n) =>\n n.id === action.payload.id ? { ...n, ...action.payload.updates } : n,\n );\n return {\n ...state,\n notifications: updatedNotifications,\n unreadCount: updatedNotifications.filter((n) => !n.isRead).length,\n };\n\n case 'DELETE_NOTIFICATION':\n const filteredNotifications = state.notifications.filter((n) => n.id !== action.payload);\n return {\n ...state,\n notifications: filteredNotifications,\n unreadCount: filteredNotifications.filter((n) => !n.isRead).length,\n };\n\n case 'SET_PREFERENCES':\n return {\n ...state,\n preferences: action.payload,\n };\n\n case 'SET_UI_STATE':\n return {\n ...state,\n ui: { ...state.ui, ...action.payload },\n };\n\n case 'SET_WEBSOCKET_STATE':\n return {\n ...state,\n websocket: { ...state.websocket, ...action.payload },\n };\n\n default:\n return state;\n }\n};\n\nconst NotificationWidgetInternal: React.FC<Omit<NotificationWidgetProps, 'sdkConfig'>> = ({\n position = 'right',\n size = 'medium',\n theme = 'light',\n className = '',\n\n onError,\n onMorePreferencesClick,\n}) => {\n const [state, dispatch] = useReducer(widgetReducer, initialState);\n const { client, isInitialized, error: sdkError } = useSDK();\n const websocketRef = useRef<any>(null);\n\n const handlePreferencesChange = useCallback((preferences: any) => {\n dispatch({\n type: 'SET_PREFERENCES',\n payload: preferences,\n });\n }, []);\n\n const handleWidgetError = useCallback(\n (error: Error) => {\n console.error('Widget error:', error);\n if (onError) {\n onError(error);\n }\n },\n [onError],\n );\n\n const { error: preferencesLoadError } = usePreferencesSync({\n onPreferencesLoaded: handlePreferencesChange,\n onError: handleWidgetError,\n });\n\n const {\n specificPreferences,\n isLoading: isSpecificLoading,\n hasMore: hasMoreSpecific,\n loadMore: loadMoreSpecific,\n } = useSpecificPreferences();\n\n const {\n updatePreference,\n isSaving,\n error: preferencesError,\n } = useLivePreferences({\n preferences: state.preferences,\n onPreferencesChange: handlePreferencesChange,\n onError: handleWidgetError,\n });\n\n // Merge specific preferences into state when they load\n useEffect(() => {\n if (specificPreferences.length > 0) {\n const currentSubs = state.preferences.subscriptions;\n const newSubs = [...currentSubs];\n let changed = false;\n\n specificPreferences.forEach((sp) => {\n const existingIdx = newSubs.findIndex((s) => s.workflowId === sp.workflowId);\n\n // If not in state, add it\n if (existingIdx === -1) {\n newSubs.push(sp);\n changed = true;\n } else {\n // If existing name is just the ID (default), update with real name from specific prefs\n const existing = newSubs[existingIdx];\n if (existing.name === existing.workflowId && sp.name && sp.name !== sp.workflowId) {\n newSubs[existingIdx] = { ...existing, name: sp.name };\n changed = true;\n }\n }\n });\n\n if (changed) {\n dispatch({\n type: 'SET_PREFERENCES',\n payload: {\n ...state.preferences,\n subscriptions: newSubs,\n },\n });\n }\n }\n }, [specificPreferences]); // Depend on specificPreferences list changes (load more)\n\n // Create display list that respects order from hook but values from state\n const displaySpecificPreferences = React.useMemo(() => {\n return specificPreferences.map((sp) => {\n const found = state.preferences.subscriptions.find((s) => s.workflowId === sp.workflowId);\n return found || sp;\n });\n }, [specificPreferences, state.preferences.subscriptions]);\n\n const handleWebSocketEvent = useCallback((event: any) => {\n try {\n const notificationMapper = createNotificationMapper();\n\n switch (event.type) {\n case 'notification_received': {\n const wsPayload = event.data;\n\n if (!notificationMapper.validateWebSocketPayload(wsPayload)) {\n console.error('Invalid WebSocket notification payload, skipping', wsPayload);\n break;\n }\n\n const mappedNotification =\n notificationMapper.toWidgetNotificationFromWebSocket(wsPayload);\n dispatch({\n type: 'ADD_NOTIFICATION',\n payload: mappedNotification,\n });\n break;\n }\n\n case 'notification_updated':\n dispatch({\n type: 'UPDATE_NOTIFICATION',\n payload: {\n id: event.data.id || event.data.notificationId,\n updates: event.data,\n },\n });\n break;\n\n case 'notification_deleted':\n dispatch({\n type: 'DELETE_NOTIFICATION',\n payload: event.data.id || event.data.notificationId,\n });\n break;\n\n case 'preferences_updated':\n dispatch({\n type: 'SET_PREFERENCES',\n payload: event.data,\n });\n break;\n\n default:\n console.log('Unknown WebSocket event type:', event.type);\n }\n } catch (error) {\n console.error('Error handling WebSocket event:', error);\n }\n }, []);\n\n const connectWebSocket = useCallback(async () => {\n if (!client || !isInitialized || websocketRef.current) return;\n\n try {\n dispatch({\n type: 'SET_WEBSOCKET_STATE',\n payload: { reconnecting: true },\n });\n\n const sdkConfig = (window as any).__notificationSDK?.config;\n if (!sdkConfig) {\n throw new Error('SDK configuration not available for WebSocket connection');\n }\n\n const baseUrl = client.getApiHost();\n const namespace = '/v1/notifications';\n const fullUrl = `${baseUrl}${namespace}`;\n\n console.log('Connecting to Socket.IO at:', fullUrl);\n\n const socket = ioClient(fullUrl, {\n query: {\n tenantId: sdkConfig.tenantId,\n subscriberId: sdkConfig.subscriberId,\n environmentId: sdkConfig.environmentId,\n },\n transports: ['websocket', 'polling'],\n autoConnect: false,\n reconnection: true,\n reconnectionAttempts: 10,\n reconnectionDelay: 1000,\n reconnectionDelayMax: 5000,\n });\n\n websocketRef.current = socket;\n let heartbeatInterval: any = null;\n\n const startHeartbeat = () => {\n if (heartbeatInterval) clearInterval(heartbeatInterval);\n heartbeatInterval = setInterval(() => {\n if (socket.connected) {\n socket.emit('ping', { timestamp: Date.now() });\n }\n }, 3000);\n };\n\n const stopHeartbeat = () => {\n if (heartbeatInterval) {\n clearInterval(heartbeatInterval);\n heartbeatInterval = null;\n }\n };\n\n socket.on('notification', (payload: any) => {\n console.log('Received notification:', payload);\n handleWebSocketEvent({\n type: 'notification_received',\n data: payload,\n });\n });\n\n socket.on('connect', () => {\n console.log('Socket.IO connected successfully');\n dispatch({\n type: 'SET_WEBSOCKET_STATE',\n payload: { connected: true, reconnecting: false },\n });\n startHeartbeat();\n });\n\n socket.on('disconnect', (reason: any) => {\n console.log('Socket.IO disconnected:', reason);\n dispatch({\n type: 'SET_WEBSOCKET_STATE',\n payload: { connected: false, reconnecting: false },\n });\n stopHeartbeat();\n });\n\n socket.on('reconnect_attempt', (attempt: any) => {\n console.log('Socket.IO reconnection attempt:', attempt);\n dispatch({\n type: 'SET_WEBSOCKET_STATE',\n payload: { connected: false, reconnecting: true },\n });\n });\n\n socket.on('connect_error', (error: any) => {\n console.error('Socket.IO connection error:', error);\n dispatch({\n type: 'SET_WEBSOCKET_STATE',\n payload: { connected: false, reconnecting: false },\n });\n if (onError) {\n onError(error);\n }\n });\n\n socket.connect();\n } catch (error) {\n console.error('Failed to connect WebSocket:', error);\n dispatch({\n type: 'SET_WEBSOCKET_STATE',\n payload: { connected: false, reconnecting: false },\n });\n if (onError) {\n onError(error as Error);\n }\n }\n }, [client, isInitialized, handleWebSocketEvent, onError]);\n\n const disconnectWebSocket = useCallback(() => {\n if (websocketRef.current) {\n try {\n if (websocketRef.current.disconnect) {\n websocketRef.current.disconnect();\n }\n websocketRef.current = null;\n dispatch({\n type: 'SET_WEBSOCKET_STATE',\n payload: { connected: false, reconnecting: false },\n });\n } catch (error) {\n console.error('Error disconnecting WebSocket:', error);\n }\n }\n }, []);\n\n const handleBellClick = useCallback(() => {\n dispatch({\n type: 'SET_UI_STATE',\n payload: { isOpen: !state.ui.isOpen },\n });\n }, [state.ui.isOpen]);\n\n const handlePopoverClose = useCallback(() => {\n dispatch({\n type: 'SET_UI_STATE',\n payload: { isOpen: false },\n });\n }, []);\n\n const handleViewChange = useCallback((view: 'notifications' | 'preferences') => {\n dispatch({\n type: 'SET_UI_STATE',\n payload: { currentView: view },\n });\n }, []);\n\n const handleNotificationAction = useCallback(\n async (id: string, action: any) => {\n if (!client || !isInitialized) {\n console.error('SDK not initialized');\n return;\n }\n\n const sdkConfig = (window as any).__notificationSDK?.config;\n if (!sdkConfig) {\n console.error('SDK configuration not available');\n return;\n }\n\n if (!id) {\n console.error('notificationId is required');\n throw new Error('notificationId is required');\n }\n\n try {\n switch (action.type) {\n case 'mark_read':\n await client.inbox.markAsRead(\n id,\n sdkConfig.tenantId,\n sdkConfig.environmentId,\n sdkConfig.subscriberId,\n );\n break;\n case 'mark_unread':\n await client.inbox.markAsUnread(\n id,\n sdkConfig.tenantId,\n sdkConfig.environmentId,\n sdkConfig.subscriberId,\n );\n break;\n case 'archive':\n await client.inbox.archive(\n id,\n sdkConfig.tenantId,\n sdkConfig.environmentId,\n sdkConfig.subscriberId,\n );\n break;\n case 'delete':\n await client.inbox.delete(\n id,\n sdkConfig.tenantId,\n sdkConfig.environmentId,\n sdkConfig.subscriberId,\n );\n break;\n default:\n if (action.handler) {\n await action.handler(id);\n }\n break;\n }\n\n switch (action.type) {\n case 'mark_read':\n dispatch({\n type: 'UPDATE_NOTIFICATION',\n payload: { id, updates: { isRead: true } },\n });\n break;\n case 'mark_unread':\n dispatch({\n type: 'UPDATE_NOTIFICATION',\n payload: { id, updates: { isRead: false } },\n });\n break;\n case 'archive':\n dispatch({\n type: 'UPDATE_NOTIFICATION',\n payload: { id, updates: { isArchived: true } },\n });\n break;\n case 'delete':\n dispatch({\n type: 'DELETE_NOTIFICATION',\n payload: id,\n });\n break;\n }\n } catch (error) {\n console.error('Error performing notification action:', error);\n if (onError) {\n onError(error as Error);\n }\n }\n },\n [client],\n );\n\n useEffect(() => {\n if (!client || !isInitialized) return;\n\n const loadNotifications = async () => {\n try {\n dispatch({\n type: 'SET_UI_STATE',\n payload: { isLoading: true },\n });\n\n const sdkConfig = (window as any).__notificationSDK?.config;\n if (!sdkConfig) {\n throw new Error('SDK configuration not available');\n }\n\n const notificationMapper = createNotificationMapper();\n const response = await client.inbox.getRenderedNotifications(\n {\n channel: 'in_app',\n limit: 50,\n offset: 0,\n },\n sdkConfig.tenantId,\n sdkConfig.environmentId,\n sdkConfig.subscriberId,\n );\n\n const coreNotifications = (response?.items || []).map((item: any) =>\n notificationMapper.toWidgetNotification(item),\n );\n\n dispatch({\n type: 'SET_NOTIFICATIONS',\n payload: coreNotifications,\n });\n\n dispatch({\n type: 'SET_UI_STATE',\n payload: { isLoading: false, error: null },\n });\n } catch (error) {\n console.error('Failed to load notifications:', error);\n dispatch({\n type: 'SET_UI_STATE',\n payload: {\n isLoading: false,\n error: error as Error,\n },\n });\n if (onError) {\n onError(error as Error);\n }\n }\n };\n\n loadNotifications();\n }, [client, isInitialized, onError]);\n\n useEffect(() => {\n if (client && isInitialized) {\n connectWebSocket();\n }\n\n return () => {\n disconnectWebSocket();\n };\n }, [client]);\n\n useEffect(() => {\n if (!client || !isInitialized) return;\n\n if (state.websocket.connected) return;\n\n const pollInterval = setInterval(async () => {\n try {\n const sdkConfig = (window as any).__notificationSDK?.config;\n if (!sdkConfig) {\n return;\n }\n\n const notificationMapper = createNotificationMapper();\n const response = await client.inbox.getRenderedNotifications(\n {\n channel: 'in_app',\n limit: 50,\n offset: 0,\n },\n sdkConfig.tenantId,\n sdkConfig.environmentId,\n sdkConfig.subscriberId,\n );\n\n const coreNotifications = (response?.items || []).map((item: any) =>\n notificationMapper.toWidgetNotification(item),\n );\n\n dispatch({\n type: 'SET_NOTIFICATIONS',\n payload: coreNotifications,\n });\n } catch (error) {\n console.error('Polling failed:', error);\n }\n }, 30000);\n\n return () => clearInterval(pollInterval);\n }, [client, state.websocket.connected]);\n\n useEffect(() => {\n const handleStorageChange = (event: StorageEvent) => {\n if (event.key === 'notification_widget_sync' && event.newValue) {\n try {\n const syncData = JSON.parse(event.newValue);\n handleWebSocketEvent(syncData);\n } catch (error) {\n console.error('Error parsing sync data:', error);\n }\n }\n };\n\n window.addEventListener('storage', handleStorageChange);\n return () => window.removeEventListener('storage', handleStorageChange);\n }, [handleWebSocketEvent]);\n\n useEffect(() => {\n dispatch({\n type: 'SET_UI_STATE',\n payload: { isLoading: isSaving },\n });\n }, [isSaving]);\n\n useEffect(() => {\n const error = sdkError || preferencesError || preferencesLoadError;\n if (error) {\n dispatch({\n type: 'SET_UI_STATE',\n payload: { error: error },\n });\n }\n }, [sdkError, preferencesError, preferencesLoadError]);\n\n if (!isInitialized && !sdkError) {\n return (\n <div\n className={`mx-widget-root relative inline-block ${className}`}\n data-mx-widget=\"root\"\n data-widget-size={size || 'small'}\n data-theme={theme}\n data-testid=\"notification-widget\"\n >\n <ComponentErrorBoundary componentName=\"BellComponent\">\n <BellComponent unreadCount={0} onClick={() => { }} size={size} disabled={true} />\n </ComponentErrorBoundary>\n </div>\n );\n }\n\n if (sdkError) {\n return (\n <div\n className={`mx-widget-root relative inline-block ${className}`}\n data-mx-widget=\"root\"\n data-widget-size={size || 'small'}\n data-theme={theme}\n data-testid=\"notification-widget\"\n >\n <ComponentErrorBoundary\n componentName=\"BellComponent\"\n fallback={\n <SDKConnectionFallback\n error={sdkError.message}\n onRetry={() => window.location.reload()}\n />\n }\n >\n <BellComponent unreadCount={0} onClick={() => { }} size={size} disabled={true} />\n </ComponentErrorBoundary>\n </div>\n );\n }\n\n return (\n <div\n className={`mx-widget-root min-w-[20rem] relative inline-block ${className}`}\n data-mx-widget=\"root\"\n data-widget-size={size || 'small'}\n data-theme={theme}\n data-testid=\"notification-widget\"\n >\n <ComponentErrorBoundary componentName=\"BellComponent\">\n <BellComponent\n unreadCount={state.unreadCount}\n onClick={handleBellClick}\n size={size}\n disabled={state.ui.isLoading}\n />\n </ComponentErrorBoundary>\n\n <ComponentErrorBoundary\n componentName=\"InboxPopover\"\n fallback={<LoadingFallback message=\"Unable to load notifications\" />}\n >\n <InboxPopover\n isOpen={state.ui.isOpen}\n onClose={handlePopoverClose}\n position={position}\n currentView={state.ui.currentView}\n onViewChange={handleViewChange}\n notifications={state.notifications}\n onNotificationAction={handleNotificationAction}\n preferences={state.preferences}\n onPreferenceChange={updatePreference}\n isPreferencesLoading={isSaving}\n specificPreferences={displaySpecificPreferences}\n onLoadMoreSpecific={loadMoreSpecific}\n hasMoreSpecific={hasMoreSpecific}\n isListLoading={isSpecificLoading}\n onMorePreferencesClick={onMorePreferencesClick}\n />\n </ComponentErrorBoundary>\n </div>\n );\n};\n\nexport const NotificationWidget: React.FC<NotificationWidgetProps> = ({ sdkConfig, ...props }) => {\n return (\n <NotificationWidgetErrorBoundary onError={props.onError}>\n <SDKProvider config={sdkConfig}>\n <NotificationWidgetInternal {...props} />\n </SDKProvider>\n </NotificationWidgetErrorBoundary>\n );\n};\n","export { NotificationWidget } from './components/NotificationWidget';\n\nexport { BellComponent } from './components/BellComponent';\nexport { InboxPopover } from './components/InboxPopover';\nexport { NotificationItem } from './components/NotificationItem';\nexport { PreferencesView } from './components/PreferencesView';\n\nexport { NotificationWidgetErrorBoundary } from './components/ErrorBoundary';\n\nexport type * from './types/core';\n\nexport type {\n Notification as SDKNotification,\n NotificationFilters,\n} from '@edusight/notification-sdk';\n\nimport '../src/styles/index.css';\n\nexport const VERSION = '3.0.0';\nexport const WIDGET_NAME = '@edusight/notification-widget';\n"],"names":["useNotificationsClient","usePreferencesSync","onPreferencesLoaded","onError","notificationClient","isLoading","setIsLoading","useState","error","setError","preferences","setPreferences","loadPreferences","useCallback","config","subscriberId","tenantId","environmentId","servicePreferences","schedule","mappedPreferences","workflowId","categoryPrefs","err","defaultPreferences","useEffect","useSpecificPreferences","client","items","setItems","hasMore","setHasMore","offset","setOffset","LIMIT","loadMore","sdkConfig","response","newItems","item","prev","existingIds","i","uniqueNewItems","ErrorFallback","onRetry","jsxs","jsx","MdError","MdRefresh","NotificationWidgetErrorBoundary","Component","props","errorInfo","SDKContext","createContext","useSDK","context","useContext","initialState","SDKProvider","children","sdkState","setSdkState","React","isMounted","existingSDK","NotificationClient","widgetReducer","state","action","n","newNotifications","updatedNotifications","filteredNotifications","NotificationWidgetInternal","position","size","theme","className","onMorePreferencesClick","dispatch","useReducer","isInitialized","sdkError","websocketRef","useRef","handlePreferencesChange","handleWidgetError","preferencesLoadError","specificPreferences","isSpecificLoading","hasMoreSpecific","loadMoreSpecific","updatePreference","isSaving","preferencesError","useLivePreferences","newSubs","changed","sp","existingIdx","s","existing","displaySpecificPreferences","handleWebSocketEvent","event","notificationMapper","createNotificationMapper","wsPayload","mappedNotification","connectWebSocket","fullUrl","socket","ioClient","heartbeatInterval","startHeartbeat","stopHeartbeat","payload","reason","attempt","disconnectWebSocket","handleBellClick","handlePopoverClose","handleViewChange","view","handleNotificationAction","id","coreNotifications","pollInterval","handleStorageChange","syncData","ComponentErrorBoundary","BellComponent","SDKConnectionFallback","LoadingFallback","InboxPopover","NotificationWidget","VERSION","WIDGET_NAME"],"mappings":"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"}