@knocklabs/react-core 0.2.16 → 0.2.17

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/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.2.17
4
+
5
+ ### Patch Changes
6
+
7
+ - f25b112: fix: ensure feed store reference re-renders after changes to user
8
+ - Updated dependencies [f25b112]
9
+ - @knocklabs/client@0.10.7
10
+
3
11
  ## 0.2.16
4
12
 
5
13
  ### Patch Changes
@@ -1,2 +1,2 @@
1
- "use strict";const d=require("@knocklabs/client"),h=require("react"),k=require("zustand/shallow"),f=t=>t&&typeof t=="object"&&"default"in t?t:{default:t},_=f(d),a=f(h),R=f(k);function s(t,c,r,n={}){t.authenticate(c,r,{onUserTokenExpiring:n==null?void 0:n.onUserTokenExpiring,timeBeforeExpirationInMs:n==null?void 0:n.timeBeforeExpirationInMs})}function m(t,c,r,n={}){const l=a.default.useRef(),i=a.default.useRef(),u=a.default.useMemo(()=>{const e=i.current||{};return R.default(n,e)?e:n},[n]);return a.default.useMemo(()=>{const e=l.current;if(e&&e.isAuthenticated()&&(e.userId!==c||e.userToken!==r))return s(e,c,r,u),e;e&&e.teardown();const o=new _.default(t,{host:u.host,logLevel:u.logLevel});return s(o,c,r,u),l.current=o,o},[t,c,r,u])}module.exports=m;
1
+ "use strict";const d=require("@knocklabs/client"),h=require("react"),k=require("zustand/shallow"),l=n=>n&&typeof n=="object"&&"default"in n?n:{default:n},_=l(d),a=l(h),R=l(k);function s(n,r,c,e={}){n.authenticate(r,c,{onUserTokenExpiring:e==null?void 0:e.onUserTokenExpiring,timeBeforeExpirationInMs:e==null?void 0:e.timeBeforeExpirationInMs})}function m(n,r,c,e={}){const o=a.default.useRef(),i=a.default.useRef(),u=a.default.useMemo(()=>{const t=i.current||{};return R.default(e,t)?t:(i.current=e,e)},[e]);return a.default.useMemo(()=>{const t=o.current;if(t&&t.isAuthenticated()&&(t.userId!==r||t.userToken!==c))return s(t,r,c,u),t;t&&t.teardown();const f=new _.default(n,{host:u.host,logLevel:u.logLevel});return s(f,r,c,u),o.current=f,f},[n,r,c,u])}module.exports=m;
2
2
  //# sourceMappingURL=useAuthenticatedKnockClient.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"useAuthenticatedKnockClient.js","sources":["../../../../../src/modules/core/hooks/useAuthenticatedKnockClient.ts"],"sourcesContent":["import Knock, { AuthenticateOptions, KnockOptions } from \"@knocklabs/client\";\nimport React from \"react\";\nimport shallow from \"zustand/shallow\";\n\nfunction authenticateWithOptions(\n knock: Knock,\n userId: string,\n userToken?: string,\n options: AuthenticateOptions = {},\n) {\n knock.authenticate(userId, userToken, {\n onUserTokenExpiring: options?.onUserTokenExpiring,\n timeBeforeExpirationInMs: options?.timeBeforeExpirationInMs,\n });\n}\n\nexport type AuthenticatedKnockClientOptions = KnockOptions &\n AuthenticateOptions;\n\nfunction useAuthenticatedKnockClient(\n apiKey: string,\n userId: string,\n userToken?: string,\n options: AuthenticatedKnockClientOptions = {},\n) {\n const knockRef = React.useRef<Knock | undefined>();\n const optionsRef = React.useRef<AuthenticatedKnockClientOptions>();\n\n // Shallow compare options so that we ensure that we have a stable\n // set of options between re-renders.\n const stableOptions = React.useMemo(() => {\n const currentOptions = optionsRef.current || {};\n return shallow(options, currentOptions) ? currentOptions : options;\n }, [options]);\n\n return React.useMemo(() => {\n const currentKnock = knockRef.current;\n\n // If the userId and the userToken changes then just reauth\n if (\n currentKnock &&\n currentKnock.isAuthenticated() &&\n (currentKnock.userId !== userId || currentKnock.userToken !== userToken)\n ) {\n authenticateWithOptions(currentKnock, userId, userToken, stableOptions);\n return currentKnock;\n }\n\n if (currentKnock) {\n currentKnock.teardown();\n }\n\n // Otherwise instantiate a new Knock client\n const knock = new Knock(apiKey, {\n host: stableOptions.host,\n logLevel: stableOptions.logLevel,\n });\n\n authenticateWithOptions(knock, userId, userToken, stableOptions);\n knockRef.current = knock;\n\n return knock;\n }, [apiKey, userId, userToken, stableOptions]);\n}\n\nexport default useAuthenticatedKnockClient;\n"],"names":["authenticateWithOptions","knock","userId","userToken","options","authenticate","onUserTokenExpiring","timeBeforeExpirationInMs","useAuthenticatedKnockClient","apiKey","knockRef","React","useRef","optionsRef","stableOptions","useMemo","currentOptions","current","shallow","currentKnock","isAuthenticated","teardown","Knock","host","logLevel"],"mappings":"+KAIA,SAASA,EACPC,EACAC,EACAC,EACAC,EAA+B,CAAA,EAC/B,CACMC,EAAAA,aAAaH,EAAQC,EAAW,CACpCG,oBAAqBF,GAAAA,YAAAA,EAASE,oBAC9BC,yBAA0BH,GAAAA,YAAAA,EAASG,wBAAAA,CACpC,CACH,CAKA,SAASC,EACPC,EACAP,EACAC,EACAC,EAA2C,CAAA,EAC3C,CACMM,MAAAA,EAAWC,UAAMC,SACjBC,EAAaF,UAAMC,SAInBE,EAAgBH,UAAMI,QAAQ,IAAM,CAClCC,MAAAA,EAAiBH,EAAWI,SAAW,GAC7C,OAAOC,EAAQd,QAAAA,EAASY,CAAc,EAAIA,EAAiBZ,CAAAA,EAC1D,CAACA,CAAO,CAAC,EAELO,OAAAA,EAAAA,QAAMI,QAAQ,IAAM,CACzB,MAAMI,EAAeT,EAASO,QAI5BE,GAAAA,GACAA,EAAaC,gBAAgB,IAC5BD,EAAajB,SAAWA,GAAUiB,EAAahB,YAAcA,GAEtCgB,OAAAA,EAAAA,EAAcjB,EAAQC,EAAWW,CAAa,EAC/DK,EAGLA,GACFA,EAAaE,SAAS,EAIlBpB,MAAAA,EAAQ,IAAIqB,EAAAA,QAAMb,EAAQ,CAC9Bc,KAAMT,EAAcS,KACpBC,SAAUV,EAAcU,QAAAA,CACzB,EAEuBvB,OAAAA,EAAAA,EAAOC,EAAQC,EAAWW,CAAa,EAC/DJ,EAASO,QAAUhB,EAEZA,GACN,CAACQ,EAAQP,EAAQC,EAAWW,CAAa,CAAC,CAC/C"}
1
+ {"version":3,"file":"useAuthenticatedKnockClient.js","sources":["../../../../../src/modules/core/hooks/useAuthenticatedKnockClient.ts"],"sourcesContent":["import Knock, { AuthenticateOptions, KnockOptions } from \"@knocklabs/client\";\nimport React from \"react\";\nimport shallow from \"zustand/shallow\";\n\nfunction authenticateWithOptions(\n knock: Knock,\n userId: string,\n userToken?: string,\n options: AuthenticateOptions = {},\n) {\n knock.authenticate(userId, userToken, {\n onUserTokenExpiring: options?.onUserTokenExpiring,\n timeBeforeExpirationInMs: options?.timeBeforeExpirationInMs,\n });\n}\n\nexport type AuthenticatedKnockClientOptions = KnockOptions &\n AuthenticateOptions;\n\nfunction useAuthenticatedKnockClient(\n apiKey: string,\n userId: string,\n userToken?: string,\n options: AuthenticatedKnockClientOptions = {},\n) {\n const knockRef = React.useRef<Knock | undefined>();\n const optionsRef = React.useRef<AuthenticatedKnockClientOptions>();\n\n // Shallow compare options so that we ensure that we have a stable\n // set of options between re-renders.\n const stableOptions = React.useMemo(() => {\n const currentOptions = optionsRef.current || {};\n\n if (shallow(options, currentOptions)) {\n return currentOptions;\n }\n\n optionsRef.current = options;\n return options;\n }, [options]);\n\n return React.useMemo(() => {\n const currentKnock = knockRef.current;\n\n // If the userId and the userToken changes then just reauth\n if (\n currentKnock &&\n currentKnock.isAuthenticated() &&\n (currentKnock.userId !== userId || currentKnock.userToken !== userToken)\n ) {\n authenticateWithOptions(currentKnock, userId, userToken, stableOptions);\n return currentKnock;\n }\n\n if (currentKnock) {\n currentKnock.teardown();\n }\n\n // Otherwise instantiate a new Knock client\n const knock = new Knock(apiKey, {\n host: stableOptions.host,\n logLevel: stableOptions.logLevel,\n });\n\n authenticateWithOptions(knock, userId, userToken, stableOptions);\n knockRef.current = knock;\n\n return knock;\n }, [apiKey, userId, userToken, stableOptions]);\n}\n\nexport default useAuthenticatedKnockClient;\n"],"names":["authenticateWithOptions","knock","userId","userToken","options","authenticate","onUserTokenExpiring","timeBeforeExpirationInMs","useAuthenticatedKnockClient","apiKey","knockRef","React","useRef","optionsRef","stableOptions","useMemo","currentOptions","current","shallow","currentKnock","isAuthenticated","teardown","Knock","host","logLevel"],"mappings":"+KAIA,SAASA,EACPC,EACAC,EACAC,EACAC,EAA+B,CAAA,EAC/B,CACMC,EAAAA,aAAaH,EAAQC,EAAW,CACpCG,oBAAqBF,GAAAA,YAAAA,EAASE,oBAC9BC,yBAA0BH,GAAAA,YAAAA,EAASG,wBAAAA,CACpC,CACH,CAKA,SAASC,EACPC,EACAP,EACAC,EACAC,EAA2C,CAAA,EAC3C,CACMM,MAAAA,EAAWC,UAAMC,SACjBC,EAAaF,UAAMC,SAInBE,EAAgBH,UAAMI,QAAQ,IAAM,CAClCC,MAAAA,EAAiBH,EAAWI,SAAW,GAEzCC,OAAAA,EAAAA,QAAQd,EAASY,CAAc,EAC1BA,GAGTH,EAAWI,QAAUb,EACdA,EAAAA,EACN,CAACA,CAAO,CAAC,EAELO,OAAAA,EAAAA,QAAMI,QAAQ,IAAM,CACzB,MAAMI,EAAeT,EAASO,QAI5BE,GAAAA,GACAA,EAAaC,gBAAgB,IAC5BD,EAAajB,SAAWA,GAAUiB,EAAahB,YAAcA,GAEtCgB,OAAAA,EAAAA,EAAcjB,EAAQC,EAAWW,CAAa,EAC/DK,EAGLA,GACFA,EAAaE,SAAS,EAIlBpB,MAAAA,EAAQ,IAAIqB,EAAAA,QAAMb,EAAQ,CAC9Bc,KAAMT,EAAcS,KACpBC,SAAUV,EAAcU,QAAAA,CACzB,EAEuBvB,OAAAA,EAAAA,EAAOC,EAAQC,EAAWW,CAAa,EAC/DJ,EAASO,QAAUhB,EAEZA,GACN,CAACQ,EAAQP,EAAQC,EAAWW,CAAa,CAAC,CAC/C"}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("date-fns");function c(e){return e>9?"9+":e}function i(e,r={}){try{const t=o.parseISO(e);return o.intlFormatDistance(t,new Date,{locale:r.locale})}catch{return e}}function d(e){return e.charAt(0).toUpperCase()+e.slice(1)}function l(e,r){return e!==void 0?e:r}function u(e,r={}){return[e,r.source,r.tenant,r.has_tenant,r.archived].filter(t=>t!=null).join("-")}function f({knockSlackChannelId:e,tenant:r,connectionStatus:t,errorLabel:n}){return[e,r,t,n].filter(a=>a!=null).join("-")}exports.feedProviderKey=u;exports.formatBadgeCount=c;exports.formatTimestamp=i;exports.renderNodeOrFallback=l;exports.slackProviderKey=f;exports.toSentenceCase=d;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("date-fns");function c(e){return e>9?"9+":e}function i(e,t={}){try{const r=o.parseISO(e);return o.intlFormatDistance(r,new Date,{locale:t.locale})}catch{return e}}function d(e){return e.charAt(0).toUpperCase()+e.slice(1)}function l(e,t){return e!==void 0?e:t}function u(e,t,r={}){return[e,t,r.source,r.tenant,r.has_tenant,r.archived].filter(n=>n!=null).join("-")}function f({knockSlackChannelId:e,tenant:t,connectionStatus:r,errorLabel:n}){return[e,t,r,n].filter(a=>a!=null).join("-")}exports.feedProviderKey=u;exports.formatBadgeCount=c;exports.formatTimestamp=i;exports.renderNodeOrFallback=l;exports.slackProviderKey=f;exports.toSentenceCase=d;
2
2
  //# sourceMappingURL=utils.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","sources":["../../../../src/modules/core/utils.ts"],"sourcesContent":["import { FeedClientOptions } from \"@knocklabs/client\";\nimport { intlFormatDistance, parseISO } from \"date-fns\";\nimport { ReactNode } from \"react\";\n\nexport function formatBadgeCount(count: number): string | number {\n return count > 9 ? \"9+\" : count;\n}\n\ntype FormatTimestampOptions = {\n locale?: string | string[];\n};\n\nexport function formatTimestamp(\n ts: string,\n options: FormatTimestampOptions = {},\n) {\n try {\n const parsedTs = parseISO(ts);\n const formatted = intlFormatDistance(parsedTs, new Date(), {\n locale: options.locale,\n });\n\n return formatted;\n } catch (e) {\n return ts;\n }\n}\n\nexport function toSentenceCase(string: string): string {\n return string.charAt(0).toUpperCase() + string.slice(1);\n}\n\nexport function renderNodeOrFallback(node: ReactNode, fallback: ReactNode) {\n return node !== undefined ? node : fallback;\n}\n\n/*\n Used to build a consistent key for the KnockFeedProvider so that React knows when\n to trigger a re-render of the context when a key property changes.\n*/\nexport function feedProviderKey(\n userFeedId: string,\n options: FeedClientOptions = {},\n) {\n return [\n userFeedId,\n options.source,\n options.tenant,\n options.has_tenant,\n options.archived,\n ]\n .filter((f) => f !== null && f !== undefined)\n .join(\"-\");\n}\n\n/*\n Used to build a consistent key for the KnockSlackProvider so that React knows when\n to trigger a re-render of the context when a key property changes.\n*/\nexport function slackProviderKey({\n knockSlackChannelId,\n tenant,\n connectionStatus,\n errorLabel,\n}: {\n knockSlackChannelId: string;\n tenant: string;\n connectionStatus: string;\n errorLabel: string | null;\n}) {\n return [knockSlackChannelId, tenant, connectionStatus, errorLabel]\n .filter((f) => f !== null && f !== undefined)\n .join(\"-\");\n}\n"],"names":["formatBadgeCount","count","formatTimestamp","ts","options","parsedTs","parseISO","formatted","intlFormatDistance","Date","locale","toSentenceCase","string","charAt","toUpperCase","slice","renderNodeOrFallback","node","fallback","undefined","feedProviderKey","userFeedId","source","tenant","has_tenant","archived","filter","f","join","slackProviderKey","knockSlackChannelId","connectionStatus","errorLabel"],"mappings":"4GAIO,SAASA,EAAiBC,EAAgC,CACxDA,OAAAA,EAAQ,EAAI,KAAOA,CAC5B,CAMO,SAASC,EACdC,EACAC,EAAkC,GAClC,CACI,GAAA,CACIC,MAAAA,EAAWC,WAASH,CAAE,EAKrBI,OAJWC,EAAAA,mBAAmBH,EAAU,IAAII,KAAQ,CACzDC,OAAQN,EAAQM,MAAAA,CACjB,OAGS,CACHP,OAAAA,CACT,CACF,CAEO,SAASQ,EAAeC,EAAwB,CAC9CA,OAAAA,EAAOC,OAAO,CAAC,EAAEC,cAAgBF,EAAOG,MAAM,CAAC,CACxD,CAEgBC,SAAAA,EAAqBC,EAAiBC,EAAqB,CAClED,OAAAA,IAASE,OAAYF,EAAOC,CACrC,CAMO,SAASE,EACdC,EACAjB,EAA6B,GAC7B,CACA,MAAO,CACLiB,EACAjB,EAAQkB,OACRlB,EAAQmB,OACRnB,EAAQoB,WACRpB,EAAQqB,QAAQ,EAEfC,UAAcC,GAAM,IAAuB,EAC3CC,KAAK,GAAG,CACb,CAMO,SAASC,EAAiB,CAC/BC,oBAAAA,EACAP,OAAAA,EACAQ,iBAAAA,EACAC,WAAAA,CAMF,EAAG,CACD,MAAO,CAACF,EAAqBP,EAAQQ,EAAkBC,CAAU,EAC9DN,OAAcC,GAAAA,GAAM,IAAuB,EAC3CC,KAAK,GAAG,CACb"}
1
+ {"version":3,"file":"utils.js","sources":["../../../../src/modules/core/utils.ts"],"sourcesContent":["import { FeedClientOptions } from \"@knocklabs/client\";\nimport { intlFormatDistance, parseISO } from \"date-fns\";\nimport { ReactNode } from \"react\";\n\nexport function formatBadgeCount(count: number): string | number {\n return count > 9 ? \"9+\" : count;\n}\n\ntype FormatTimestampOptions = {\n locale?: string | string[];\n};\n\nexport function formatTimestamp(\n ts: string,\n options: FormatTimestampOptions = {},\n) {\n try {\n const parsedTs = parseISO(ts);\n const formatted = intlFormatDistance(parsedTs, new Date(), {\n locale: options.locale,\n });\n\n return formatted;\n } catch (e) {\n return ts;\n }\n}\n\nexport function toSentenceCase(string: string): string {\n return string.charAt(0).toUpperCase() + string.slice(1);\n}\n\nexport function renderNodeOrFallback(node: ReactNode, fallback: ReactNode) {\n return node !== undefined ? node : fallback;\n}\n\n/*\n Used to build a consistent key for the KnockFeedProvider so that React knows when\n to trigger a re-render of the context when a key property changes.\n*/\nexport function feedProviderKey(\n userId: string | undefined,\n feedId: string,\n options: FeedClientOptions = {},\n) {\n return [\n userId,\n feedId,\n options.source,\n options.tenant,\n options.has_tenant,\n options.archived,\n ]\n .filter((f) => f !== null && f !== undefined)\n .join(\"-\");\n}\n\n/*\n Used to build a consistent key for the KnockSlackProvider so that React knows when\n to trigger a re-render of the context when a key property changes.\n*/\nexport function slackProviderKey({\n knockSlackChannelId,\n tenant,\n connectionStatus,\n errorLabel,\n}: {\n knockSlackChannelId: string;\n tenant: string;\n connectionStatus: string;\n errorLabel: string | null;\n}) {\n return [knockSlackChannelId, tenant, connectionStatus, errorLabel]\n .filter((f) => f !== null && f !== undefined)\n .join(\"-\");\n}\n"],"names":["formatBadgeCount","count","formatTimestamp","ts","options","parsedTs","parseISO","formatted","intlFormatDistance","Date","locale","toSentenceCase","string","charAt","toUpperCase","slice","renderNodeOrFallback","node","fallback","undefined","feedProviderKey","userId","feedId","source","tenant","has_tenant","archived","filter","f","join","slackProviderKey","knockSlackChannelId","connectionStatus","errorLabel"],"mappings":"4GAIO,SAASA,EAAiBC,EAAgC,CACxDA,OAAAA,EAAQ,EAAI,KAAOA,CAC5B,CAMO,SAASC,EACdC,EACAC,EAAkC,GAClC,CACI,GAAA,CACIC,MAAAA,EAAWC,WAASH,CAAE,EAKrBI,OAJWC,EAAAA,mBAAmBH,EAAU,IAAII,KAAQ,CACzDC,OAAQN,EAAQM,MAAAA,CACjB,OAGS,CACHP,OAAAA,CACT,CACF,CAEO,SAASQ,EAAeC,EAAwB,CAC9CA,OAAAA,EAAOC,OAAO,CAAC,EAAEC,cAAgBF,EAAOG,MAAM,CAAC,CACxD,CAEgBC,SAAAA,EAAqBC,EAAiBC,EAAqB,CAClED,OAAAA,IAASE,OAAYF,EAAOC,CACrC,CAMO,SAASE,EACdC,EACAC,EACAlB,EAA6B,CAAA,EAC7B,CACO,MAAA,CACLiB,EACAC,EACAlB,EAAQmB,OACRnB,EAAQoB,OACRpB,EAAQqB,WACRrB,EAAQsB,QAAQ,EAEfC,UAAcC,GAAM,IAAuB,EAC3CC,KAAK,GAAG,CACb,CAMO,SAASC,EAAiB,CAC/BC,oBAAAA,EACAP,OAAAA,EACAQ,iBAAAA,EACAC,WAAAA,CAMF,EAAG,CACD,MAAO,CAACF,EAAqBP,EAAQQ,EAAkBC,CAAU,EAC9DN,OAAcC,GAAAA,GAAM,IAAuB,EAC3CC,KAAK,GAAG,CACb"}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const a=require("react"),d=require("zustand"),l=require("../../core/context/KnockProvider.js");require("@knocklabs/client");require("zustand/shallow");const f=require("../../core/utils.js"),k=require("../hooks/useNotifications.js"),b=e=>e&&typeof e=="object"&&"default"in e?e:{default:e};function p(e){if(e&&typeof e=="object"&&"default"in e)return e;const o=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(e){for(const t in e)if(t!=="default"){const r=Object.getOwnPropertyDescriptor(e,t);Object.defineProperty(o,t,r.get?r:{enumerable:!0,get:()=>e[t]})}}return o.default=e,Object.freeze(o)}const n=p(a),v=b(d),i=n.createContext(null),m=({feedId:e,children:o,defaultFeedOptions:t={},colorMode:r="light"})=>{const c=l.useKnockClient(),u=k(c,e,t),s=v.default(u.store);return n.createElement(i.Provider,{key:f.feedProviderKey(e,t),value:{knock:c,feedClient:u,useFeedStore:s,colorMode:r}},o)},y=()=>{const e=n.useContext(i);if(e===void 0)throw new Error("useKnockFeed must be used within a KnockFeedProvider");return e};exports.KnockFeedProvider=m;exports.useKnockFeed=y;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const a=require("react"),d=require("zustand"),l=require("../../core/context/KnockProvider.js");require("@knocklabs/client");require("zustand/shallow");const f=require("../../core/utils.js"),k=require("../hooks/useNotifications.js"),b=e=>e&&typeof e=="object"&&"default"in e?e:{default:e};function p(e){if(e&&typeof e=="object"&&"default"in e)return e;const o=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(e){for(const t in e)if(t!=="default"){const r=Object.getOwnPropertyDescriptor(e,t);Object.defineProperty(o,t,r.get?r:{enumerable:!0,get:()=>e[t]})}}return o.default=e,Object.freeze(o)}const n=p(a),m=b(d),i=n.createContext(void 0),v=({feedId:e,children:o,defaultFeedOptions:t={},colorMode:r="light"})=>{const c=l.useKnockClient(),u=k(c,e,t),s=n.useMemo(()=>m.default(u.store),[u]);return n.createElement(i.Provider,{key:f.feedProviderKey(c.userId,e,t),value:{knock:c,feedClient:u,useFeedStore:s,colorMode:r}},o)},y=()=>{const e=n.useContext(i);if(!e)throw new Error("useKnockFeed must be used within a KnockFeedProvider");return e};exports.KnockFeedProvider=v;exports.useKnockFeed=y;
2
2
  //# sourceMappingURL=KnockFeedProvider.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"KnockFeedProvider.js","sources":["../../../../../src/modules/feed/context/KnockFeedProvider.tsx"],"sourcesContent":["import Knock, {\n Feed,\n FeedClientOptions,\n FeedStoreState,\n} from \"@knocklabs/client\";\nimport * as React from \"react\";\nimport { PropsWithChildren } from \"react\";\nimport create, { UseBoundStore } from \"zustand\";\n\nimport { useKnockClient } from \"../../core\";\nimport { ColorMode } from \"../../core/constants\";\nimport { feedProviderKey } from \"../../core/utils\";\nimport useNotifications from \"../hooks/useNotifications\";\n\nexport interface KnockFeedProviderState {\n knock: Knock;\n feedClient: Feed;\n useFeedStore: UseBoundStore<FeedStoreState>;\n colorMode: ColorMode;\n}\n\nconst FeedStateContext = React.createContext<KnockFeedProviderState | null>(\n null,\n);\n\nexport interface KnockFeedProviderProps {\n // Feed props\n feedId: string;\n\n // Extra options\n colorMode?: ColorMode;\n\n // Feed client options\n defaultFeedOptions?: FeedClientOptions;\n}\n\nexport const KnockFeedProvider: React.FC<\n PropsWithChildren<KnockFeedProviderProps>\n> = ({ feedId, children, defaultFeedOptions = {}, colorMode = \"light\" }) => {\n const knock = useKnockClient();\n const feedClient = useNotifications(knock, feedId, defaultFeedOptions);\n const useFeedStore = create<FeedStoreState>(feedClient.store);\n\n return (\n <FeedStateContext.Provider\n key={feedProviderKey(feedId, defaultFeedOptions)}\n value={{\n knock,\n feedClient,\n useFeedStore,\n colorMode,\n }}\n >\n {children}\n </FeedStateContext.Provider>\n );\n};\n\nexport const useKnockFeed = (): KnockFeedProviderState => {\n const context = React.useContext(FeedStateContext);\n if (context === undefined) {\n throw new Error(\"useKnockFeed must be used within a KnockFeedProvider\");\n }\n return context as KnockFeedProviderState;\n};\n"],"names":["FeedStateContext","React","createContext","KnockFeedProvider","feedId","children","defaultFeedOptions","colorMode","knock","useKnockClient","feedClient","useNotifications","useFeedStore","create","store","feedProviderKey","useKnockFeed","context","useContext","undefined","Error"],"mappings":"ksBAqBMA,EAAmBC,EAAMC,cAC7B,IACF,EAaaC,EAETA,CAAC,CAAEC,OAAAA,EAAQC,SAAAA,EAAUC,mBAAAA,EAAqB,CAAC,EAAGC,UAAAA,EAAY,OAAQ,IAAM,CAC1E,MAAMC,EAAQC,EAAAA,iBACRC,EAAaC,EAAiBH,EAAOJ,EAAQE,CAAkB,EAC/DM,EAAeC,EAAAA,QAAuBH,EAAWI,KAAK,EAG1D,OAAAb,EAAA,cAACD,EAAiB,SAAjB,CACC,IAAKe,EAAAA,gBAAgBX,EAAQE,CAAkB,EAC/C,MAAO,CACLE,MAAAA,EACAE,WAAAA,EACAE,aAAAA,EACAL,UAAAA,CAAAA,GAGDF,CACH,CAEJ,EAEaW,EAAeA,IAA8B,CAClDC,MAAAA,EAAUhB,EAAMiB,WAAWlB,CAAgB,EACjD,GAAIiB,IAAYE,OACR,MAAA,IAAIC,MAAM,sDAAsD,EAEjEH,OAAAA,CACT"}
1
+ {"version":3,"file":"KnockFeedProvider.js","sources":["../../../../../src/modules/feed/context/KnockFeedProvider.tsx"],"sourcesContent":["import Knock, {\n Feed,\n FeedClientOptions,\n FeedStoreState,\n} from \"@knocklabs/client\";\nimport * as React from \"react\";\nimport { PropsWithChildren } from \"react\";\nimport create, { UseBoundStore } from \"zustand\";\n\nimport { useKnockClient } from \"../../core\";\nimport { ColorMode } from \"../../core/constants\";\nimport { feedProviderKey } from \"../../core/utils\";\nimport useNotifications from \"../hooks/useNotifications\";\n\nexport interface KnockFeedProviderState {\n knock: Knock;\n feedClient: Feed;\n useFeedStore: UseBoundStore<FeedStoreState>;\n colorMode: ColorMode;\n}\n\nconst FeedStateContext = React.createContext<\n KnockFeedProviderState | undefined\n>(undefined);\n\nexport interface KnockFeedProviderProps {\n // Feed props\n feedId: string;\n\n // Extra options\n colorMode?: ColorMode;\n\n // Feed client options\n defaultFeedOptions?: FeedClientOptions;\n}\n\nexport const KnockFeedProvider: React.FC<\n PropsWithChildren<KnockFeedProviderProps>\n> = ({ feedId, children, defaultFeedOptions = {}, colorMode = \"light\" }) => {\n const knock = useKnockClient();\n const feedClient = useNotifications(knock, feedId, defaultFeedOptions);\n\n const useFeedStore = React.useMemo(\n () => create<FeedStoreState>(feedClient.store),\n [feedClient],\n );\n\n return (\n <FeedStateContext.Provider\n key={feedProviderKey(knock.userId, feedId, defaultFeedOptions)}\n value={{\n knock,\n feedClient,\n useFeedStore,\n colorMode,\n }}\n >\n {children}\n </FeedStateContext.Provider>\n );\n};\n\nexport const useKnockFeed = (): KnockFeedProviderState => {\n const context = React.useContext(FeedStateContext);\n\n if (!context) {\n throw new Error(\"useKnockFeed must be used within a KnockFeedProvider\");\n }\n\n return context;\n};\n"],"names":["FeedStateContext","React","createContext","undefined","KnockFeedProvider","feedId","children","defaultFeedOptions","colorMode","knock","useKnockClient","feedClient","useNotifications","useFeedStore","useMemo","create","store","feedProviderKey","userId","useKnockFeed","context","useContext","Error"],"mappings":"ksBAqBMA,EAAmBC,EAAMC,cAE7BC,MAAS,EAaEC,EAETA,CAAC,CAAEC,OAAAA,EAAQC,SAAAA,EAAUC,mBAAAA,EAAqB,CAAC,EAAGC,UAAAA,EAAY,OAAQ,IAAM,CAC1E,MAAMC,EAAQC,EAAAA,iBACRC,EAAaC,EAAiBH,EAAOJ,EAAQE,CAAkB,EAE/DM,EAAeZ,EAAMa,QACzB,IAAMC,EAAAA,QAAuBJ,EAAWK,KAAK,EAC7C,CAACL,CAAU,CACb,EAGE,OAAAV,EAAA,cAACD,EAAiB,SAAjB,CACC,IAAKiB,kBAAgBR,EAAMS,OAAQb,EAAQE,CAAkB,EAC7D,MAAO,CACLE,MAAAA,EACAE,WAAAA,EACAE,aAAAA,EACAL,UAAAA,CAAAA,GAGDF,CACH,CAEJ,EAEaa,EAAeA,IAA8B,CAClDC,MAAAA,EAAUnB,EAAMoB,WAAWrB,CAAgB,EAEjD,GAAI,CAACoB,EACG,MAAA,IAAIE,MAAM,sDAAsD,EAGjEF,OAAAA,CACT"}
@@ -1,28 +1,28 @@
1
1
  import m from "@knocklabs/client";
2
- import o from "react";
2
+ import f from "react";
3
3
  import s from "zustand/shallow";
4
- function a(u, n, r, t = {}) {
5
- u.authenticate(n, r, {
6
- onUserTokenExpiring: t == null ? void 0 : t.onUserTokenExpiring,
7
- timeBeforeExpirationInMs: t == null ? void 0 : t.timeBeforeExpirationInMs
4
+ function l(u, r, n, e = {}) {
5
+ u.authenticate(r, n, {
6
+ onUserTokenExpiring: e == null ? void 0 : e.onUserTokenExpiring,
7
+ timeBeforeExpirationInMs: e == null ? void 0 : e.timeBeforeExpirationInMs
8
8
  });
9
9
  }
10
- function R(u, n, r, t = {}) {
11
- const f = o.useRef(), l = o.useRef(), c = o.useMemo(() => {
12
- const e = l.current || {};
13
- return s(t, e) ? e : t;
14
- }, [t]);
15
- return o.useMemo(() => {
16
- const e = f.current;
17
- if (e && e.isAuthenticated() && (e.userId !== n || e.userToken !== r))
18
- return a(e, n, r, c), e;
19
- e && e.teardown();
10
+ function R(u, r, n, e = {}) {
11
+ const o = f.useRef(), a = f.useRef(), c = f.useMemo(() => {
12
+ const t = a.current || {};
13
+ return s(e, t) ? t : (a.current = e, e);
14
+ }, [e]);
15
+ return f.useMemo(() => {
16
+ const t = o.current;
17
+ if (t && t.isAuthenticated() && (t.userId !== r || t.userToken !== n))
18
+ return l(t, r, n, c), t;
19
+ t && t.teardown();
20
20
  const i = new m(u, {
21
21
  host: c.host,
22
22
  logLevel: c.logLevel
23
23
  });
24
- return a(i, n, r, c), f.current = i, i;
25
- }, [u, n, r, c]);
24
+ return l(i, r, n, c), o.current = i, i;
25
+ }, [u, r, n, c]);
26
26
  }
27
27
  export {
28
28
  R as default
@@ -1 +1 @@
1
- {"version":3,"file":"useAuthenticatedKnockClient.mjs","sources":["../../../../../src/modules/core/hooks/useAuthenticatedKnockClient.ts"],"sourcesContent":["import Knock, { AuthenticateOptions, KnockOptions } from \"@knocklabs/client\";\nimport React from \"react\";\nimport shallow from \"zustand/shallow\";\n\nfunction authenticateWithOptions(\n knock: Knock,\n userId: string,\n userToken?: string,\n options: AuthenticateOptions = {},\n) {\n knock.authenticate(userId, userToken, {\n onUserTokenExpiring: options?.onUserTokenExpiring,\n timeBeforeExpirationInMs: options?.timeBeforeExpirationInMs,\n });\n}\n\nexport type AuthenticatedKnockClientOptions = KnockOptions &\n AuthenticateOptions;\n\nfunction useAuthenticatedKnockClient(\n apiKey: string,\n userId: string,\n userToken?: string,\n options: AuthenticatedKnockClientOptions = {},\n) {\n const knockRef = React.useRef<Knock | undefined>();\n const optionsRef = React.useRef<AuthenticatedKnockClientOptions>();\n\n // Shallow compare options so that we ensure that we have a stable\n // set of options between re-renders.\n const stableOptions = React.useMemo(() => {\n const currentOptions = optionsRef.current || {};\n return shallow(options, currentOptions) ? currentOptions : options;\n }, [options]);\n\n return React.useMemo(() => {\n const currentKnock = knockRef.current;\n\n // If the userId and the userToken changes then just reauth\n if (\n currentKnock &&\n currentKnock.isAuthenticated() &&\n (currentKnock.userId !== userId || currentKnock.userToken !== userToken)\n ) {\n authenticateWithOptions(currentKnock, userId, userToken, stableOptions);\n return currentKnock;\n }\n\n if (currentKnock) {\n currentKnock.teardown();\n }\n\n // Otherwise instantiate a new Knock client\n const knock = new Knock(apiKey, {\n host: stableOptions.host,\n logLevel: stableOptions.logLevel,\n });\n\n authenticateWithOptions(knock, userId, userToken, stableOptions);\n knockRef.current = knock;\n\n return knock;\n }, [apiKey, userId, userToken, stableOptions]);\n}\n\nexport default useAuthenticatedKnockClient;\n"],"names":["authenticateWithOptions","knock","userId","userToken","options","authenticate","onUserTokenExpiring","timeBeforeExpirationInMs","useAuthenticatedKnockClient","apiKey","knockRef","React","useRef","optionsRef","stableOptions","useMemo","currentOptions","current","shallow","currentKnock","isAuthenticated","teardown","Knock","host","logLevel"],"mappings":";;;AAIA,SAASA,EACPC,GACAC,GACAC,GACAC,IAA+B,CAAA,GAC/B;AACMC,EAAAA,EAAAA,aAAaH,GAAQC,GAAW;AAAA,IACpCG,qBAAqBF,KAAAA,gBAAAA,EAASE;AAAAA,IAC9BC,0BAA0BH,KAAAA,gBAAAA,EAASG;AAAAA,EAAAA,CACpC;AACH;AAKA,SAASC,EACPC,GACAP,GACAC,GACAC,IAA2C,CAAA,GAC3C;AACMM,QAAAA,IAAWC,EAAMC,UACjBC,IAAaF,EAAMC,UAInBE,IAAgBH,EAAMI,QAAQ,MAAM;AAClCC,UAAAA,IAAiBH,EAAWI,WAAW;AAC7C,WAAOC,EAAQd,GAASY,CAAc,IAAIA,IAAiBZ;AAAAA,EAAAA,GAC1D,CAACA,CAAO,CAAC;AAELO,SAAAA,EAAMI,QAAQ,MAAM;AACzB,UAAMI,IAAeT,EAASO;AAI5BE,QAAAA,KACAA,EAAaC,gBAAgB,MAC5BD,EAAajB,WAAWA,KAAUiB,EAAahB,cAAcA;AAEtCgB,aAAAA,EAAAA,GAAcjB,GAAQC,GAAWW,CAAa,GAC/DK;AAGT,IAAIA,KACFA,EAAaE,SAAS;AAIlBpB,UAAAA,IAAQ,IAAIqB,EAAMb,GAAQ;AAAA,MAC9Bc,MAAMT,EAAcS;AAAAA,MACpBC,UAAUV,EAAcU;AAAAA,IAAAA,CACzB;AAEuBvB,WAAAA,EAAAA,GAAOC,GAAQC,GAAWW,CAAa,GAC/DJ,EAASO,UAAUhB,GAEZA;AAAAA,KACN,CAACQ,GAAQP,GAAQC,GAAWW,CAAa,CAAC;AAC/C;"}
1
+ {"version":3,"file":"useAuthenticatedKnockClient.mjs","sources":["../../../../../src/modules/core/hooks/useAuthenticatedKnockClient.ts"],"sourcesContent":["import Knock, { AuthenticateOptions, KnockOptions } from \"@knocklabs/client\";\nimport React from \"react\";\nimport shallow from \"zustand/shallow\";\n\nfunction authenticateWithOptions(\n knock: Knock,\n userId: string,\n userToken?: string,\n options: AuthenticateOptions = {},\n) {\n knock.authenticate(userId, userToken, {\n onUserTokenExpiring: options?.onUserTokenExpiring,\n timeBeforeExpirationInMs: options?.timeBeforeExpirationInMs,\n });\n}\n\nexport type AuthenticatedKnockClientOptions = KnockOptions &\n AuthenticateOptions;\n\nfunction useAuthenticatedKnockClient(\n apiKey: string,\n userId: string,\n userToken?: string,\n options: AuthenticatedKnockClientOptions = {},\n) {\n const knockRef = React.useRef<Knock | undefined>();\n const optionsRef = React.useRef<AuthenticatedKnockClientOptions>();\n\n // Shallow compare options so that we ensure that we have a stable\n // set of options between re-renders.\n const stableOptions = React.useMemo(() => {\n const currentOptions = optionsRef.current || {};\n\n if (shallow(options, currentOptions)) {\n return currentOptions;\n }\n\n optionsRef.current = options;\n return options;\n }, [options]);\n\n return React.useMemo(() => {\n const currentKnock = knockRef.current;\n\n // If the userId and the userToken changes then just reauth\n if (\n currentKnock &&\n currentKnock.isAuthenticated() &&\n (currentKnock.userId !== userId || currentKnock.userToken !== userToken)\n ) {\n authenticateWithOptions(currentKnock, userId, userToken, stableOptions);\n return currentKnock;\n }\n\n if (currentKnock) {\n currentKnock.teardown();\n }\n\n // Otherwise instantiate a new Knock client\n const knock = new Knock(apiKey, {\n host: stableOptions.host,\n logLevel: stableOptions.logLevel,\n });\n\n authenticateWithOptions(knock, userId, userToken, stableOptions);\n knockRef.current = knock;\n\n return knock;\n }, [apiKey, userId, userToken, stableOptions]);\n}\n\nexport default useAuthenticatedKnockClient;\n"],"names":["authenticateWithOptions","knock","userId","userToken","options","authenticate","onUserTokenExpiring","timeBeforeExpirationInMs","useAuthenticatedKnockClient","apiKey","knockRef","React","useRef","optionsRef","stableOptions","useMemo","currentOptions","current","shallow","currentKnock","isAuthenticated","teardown","Knock","host","logLevel"],"mappings":";;;AAIA,SAASA,EACPC,GACAC,GACAC,GACAC,IAA+B,CAAA,GAC/B;AACMC,EAAAA,EAAAA,aAAaH,GAAQC,GAAW;AAAA,IACpCG,qBAAqBF,KAAAA,gBAAAA,EAASE;AAAAA,IAC9BC,0BAA0BH,KAAAA,gBAAAA,EAASG;AAAAA,EAAAA,CACpC;AACH;AAKA,SAASC,EACPC,GACAP,GACAC,GACAC,IAA2C,CAAA,GAC3C;AACMM,QAAAA,IAAWC,EAAMC,UACjBC,IAAaF,EAAMC,UAInBE,IAAgBH,EAAMI,QAAQ,MAAM;AAClCC,UAAAA,IAAiBH,EAAWI,WAAW;AAEzCC,WAAAA,EAAQd,GAASY,CAAc,IAC1BA,KAGTH,EAAWI,UAAUb,GACdA;AAAAA,EAAAA,GACN,CAACA,CAAO,CAAC;AAELO,SAAAA,EAAMI,QAAQ,MAAM;AACzB,UAAMI,IAAeT,EAASO;AAI5BE,QAAAA,KACAA,EAAaC,gBAAgB,MAC5BD,EAAajB,WAAWA,KAAUiB,EAAahB,cAAcA;AAEtCgB,aAAAA,EAAAA,GAAcjB,GAAQC,GAAWW,CAAa,GAC/DK;AAGT,IAAIA,KACFA,EAAaE,SAAS;AAIlBpB,UAAAA,IAAQ,IAAIqB,EAAMb,GAAQ;AAAA,MAC9Bc,MAAMT,EAAcS;AAAAA,MACpBC,UAAUV,EAAcU;AAAAA,IAAAA,CACzB;AAEuBvB,WAAAA,EAAAA,GAAOC,GAAQC,GAAWW,CAAa,GAC/DJ,EAASO,UAAUhB,GAEZA;AAAAA,KACN,CAACQ,GAAQP,GAAQC,GAAWW,CAAa,CAAC;AAC/C;"}
@@ -2,11 +2,11 @@ import { parseISO as o, intlFormatDistance as c } from "date-fns";
2
2
  function u(e) {
3
3
  return e > 9 ? "9+" : e;
4
4
  }
5
- function l(e, r = {}) {
5
+ function l(e, t = {}) {
6
6
  try {
7
- const t = o(e);
8
- return c(t, /* @__PURE__ */ new Date(), {
9
- locale: r.locale
7
+ const r = o(e);
8
+ return c(r, /* @__PURE__ */ new Date(), {
9
+ locale: t.locale
10
10
  });
11
11
  } catch {
12
12
  return e;
@@ -15,19 +15,19 @@ function l(e, r = {}) {
15
15
  function d(e) {
16
16
  return e.charAt(0).toUpperCase() + e.slice(1);
17
17
  }
18
- function f(e, r) {
19
- return e !== void 0 ? e : r;
18
+ function f(e, t) {
19
+ return e !== void 0 ? e : t;
20
20
  }
21
- function m(e, r = {}) {
22
- return [e, r.source, r.tenant, r.has_tenant, r.archived].filter((t) => t != null).join("-");
21
+ function m(e, t, r = {}) {
22
+ return [e, t, r.source, r.tenant, r.has_tenant, r.archived].filter((n) => n != null).join("-");
23
23
  }
24
24
  function s({
25
25
  knockSlackChannelId: e,
26
- tenant: r,
27
- connectionStatus: t,
26
+ tenant: t,
27
+ connectionStatus: r,
28
28
  errorLabel: n
29
29
  }) {
30
- return [e, r, t, n].filter((a) => a != null).join("-");
30
+ return [e, t, r, n].filter((a) => a != null).join("-");
31
31
  }
32
32
  export {
33
33
  m as feedProviderKey,
@@ -1 +1 @@
1
- {"version":3,"file":"utils.mjs","sources":["../../../../src/modules/core/utils.ts"],"sourcesContent":["import { FeedClientOptions } from \"@knocklabs/client\";\nimport { intlFormatDistance, parseISO } from \"date-fns\";\nimport { ReactNode } from \"react\";\n\nexport function formatBadgeCount(count: number): string | number {\n return count > 9 ? \"9+\" : count;\n}\n\ntype FormatTimestampOptions = {\n locale?: string | string[];\n};\n\nexport function formatTimestamp(\n ts: string,\n options: FormatTimestampOptions = {},\n) {\n try {\n const parsedTs = parseISO(ts);\n const formatted = intlFormatDistance(parsedTs, new Date(), {\n locale: options.locale,\n });\n\n return formatted;\n } catch (e) {\n return ts;\n }\n}\n\nexport function toSentenceCase(string: string): string {\n return string.charAt(0).toUpperCase() + string.slice(1);\n}\n\nexport function renderNodeOrFallback(node: ReactNode, fallback: ReactNode) {\n return node !== undefined ? node : fallback;\n}\n\n/*\n Used to build a consistent key for the KnockFeedProvider so that React knows when\n to trigger a re-render of the context when a key property changes.\n*/\nexport function feedProviderKey(\n userFeedId: string,\n options: FeedClientOptions = {},\n) {\n return [\n userFeedId,\n options.source,\n options.tenant,\n options.has_tenant,\n options.archived,\n ]\n .filter((f) => f !== null && f !== undefined)\n .join(\"-\");\n}\n\n/*\n Used to build a consistent key for the KnockSlackProvider so that React knows when\n to trigger a re-render of the context when a key property changes.\n*/\nexport function slackProviderKey({\n knockSlackChannelId,\n tenant,\n connectionStatus,\n errorLabel,\n}: {\n knockSlackChannelId: string;\n tenant: string;\n connectionStatus: string;\n errorLabel: string | null;\n}) {\n return [knockSlackChannelId, tenant, connectionStatus, errorLabel]\n .filter((f) => f !== null && f !== undefined)\n .join(\"-\");\n}\n"],"names":["formatBadgeCount","count","formatTimestamp","ts","options","parsedTs","parseISO","formatted","intlFormatDistance","Date","locale","toSentenceCase","string","charAt","toUpperCase","slice","renderNodeOrFallback","node","fallback","undefined","feedProviderKey","userFeedId","source","tenant","has_tenant","archived","filter","f","join","slackProviderKey","knockSlackChannelId","connectionStatus","errorLabel"],"mappings":";AAIO,SAASA,EAAiBC,GAAgC;AACxDA,SAAAA,IAAQ,IAAI,OAAOA;AAC5B;AAMO,SAASC,EACdC,GACAC,IAAkC,IAClC;AACI,MAAA;AACIC,UAAAA,IAAWC,EAASH,CAAE;AAKrBI,WAJWC,EAAmBH,GAAU,oBAAII,QAAQ;AAAA,MACzDC,QAAQN,EAAQM;AAAAA,IAAAA,CACjB;AAAA,UAGS;AACHP,WAAAA;AAAAA,EACT;AACF;AAEO,SAASQ,EAAeC,GAAwB;AAC9CA,SAAAA,EAAOC,OAAO,CAAC,EAAEC,gBAAgBF,EAAOG,MAAM,CAAC;AACxD;AAEgBC,SAAAA,EAAqBC,GAAiBC,GAAqB;AAClED,SAAAA,MAASE,SAAYF,IAAOC;AACrC;AAMO,SAASE,EACdC,GACAjB,IAA6B,IAC7B;AACA,SAAO,CACLiB,GACAjB,EAAQkB,QACRlB,EAAQmB,QACRnB,EAAQoB,YACRpB,EAAQqB,QAAQ,EAEfC,OAAQC,OAAMA,KAAM,IAAuB,EAC3CC,KAAK,GAAG;AACb;AAMO,SAASC,EAAiB;AAAA,EAC/BC,qBAAAA;AAAAA,EACAP,QAAAA;AAAAA,EACAQ,kBAAAA;AAAAA,EACAC,YAAAA;AAMF,GAAG;AACD,SAAO,CAACF,GAAqBP,GAAQQ,GAAkBC,CAAU,EAC9DN,OAAQC,CAAMA,MAAAA,KAAM,IAAuB,EAC3CC,KAAK,GAAG;AACb;"}
1
+ {"version":3,"file":"utils.mjs","sources":["../../../../src/modules/core/utils.ts"],"sourcesContent":["import { FeedClientOptions } from \"@knocklabs/client\";\nimport { intlFormatDistance, parseISO } from \"date-fns\";\nimport { ReactNode } from \"react\";\n\nexport function formatBadgeCount(count: number): string | number {\n return count > 9 ? \"9+\" : count;\n}\n\ntype FormatTimestampOptions = {\n locale?: string | string[];\n};\n\nexport function formatTimestamp(\n ts: string,\n options: FormatTimestampOptions = {},\n) {\n try {\n const parsedTs = parseISO(ts);\n const formatted = intlFormatDistance(parsedTs, new Date(), {\n locale: options.locale,\n });\n\n return formatted;\n } catch (e) {\n return ts;\n }\n}\n\nexport function toSentenceCase(string: string): string {\n return string.charAt(0).toUpperCase() + string.slice(1);\n}\n\nexport function renderNodeOrFallback(node: ReactNode, fallback: ReactNode) {\n return node !== undefined ? node : fallback;\n}\n\n/*\n Used to build a consistent key for the KnockFeedProvider so that React knows when\n to trigger a re-render of the context when a key property changes.\n*/\nexport function feedProviderKey(\n userId: string | undefined,\n feedId: string,\n options: FeedClientOptions = {},\n) {\n return [\n userId,\n feedId,\n options.source,\n options.tenant,\n options.has_tenant,\n options.archived,\n ]\n .filter((f) => f !== null && f !== undefined)\n .join(\"-\");\n}\n\n/*\n Used to build a consistent key for the KnockSlackProvider so that React knows when\n to trigger a re-render of the context when a key property changes.\n*/\nexport function slackProviderKey({\n knockSlackChannelId,\n tenant,\n connectionStatus,\n errorLabel,\n}: {\n knockSlackChannelId: string;\n tenant: string;\n connectionStatus: string;\n errorLabel: string | null;\n}) {\n return [knockSlackChannelId, tenant, connectionStatus, errorLabel]\n .filter((f) => f !== null && f !== undefined)\n .join(\"-\");\n}\n"],"names":["formatBadgeCount","count","formatTimestamp","ts","options","parsedTs","parseISO","formatted","intlFormatDistance","Date","locale","toSentenceCase","string","charAt","toUpperCase","slice","renderNodeOrFallback","node","fallback","undefined","feedProviderKey","userId","feedId","source","tenant","has_tenant","archived","filter","f","join","slackProviderKey","knockSlackChannelId","connectionStatus","errorLabel"],"mappings":";AAIO,SAASA,EAAiBC,GAAgC;AACxDA,SAAAA,IAAQ,IAAI,OAAOA;AAC5B;AAMO,SAASC,EACdC,GACAC,IAAkC,IAClC;AACI,MAAA;AACIC,UAAAA,IAAWC,EAASH,CAAE;AAKrBI,WAJWC,EAAmBH,GAAU,oBAAII,QAAQ;AAAA,MACzDC,QAAQN,EAAQM;AAAAA,IAAAA,CACjB;AAAA,UAGS;AACHP,WAAAA;AAAAA,EACT;AACF;AAEO,SAASQ,EAAeC,GAAwB;AAC9CA,SAAAA,EAAOC,OAAO,CAAC,EAAEC,gBAAgBF,EAAOG,MAAM,CAAC;AACxD;AAEgBC,SAAAA,EAAqBC,GAAiBC,GAAqB;AAClED,SAAAA,MAASE,SAAYF,IAAOC;AACrC;AAMO,SAASE,EACdC,GACAC,GACAlB,IAA6B,CAAA,GAC7B;AACO,SAAA,CACLiB,GACAC,GACAlB,EAAQmB,QACRnB,EAAQoB,QACRpB,EAAQqB,YACRrB,EAAQsB,QAAQ,EAEfC,OAAQC,OAAMA,KAAM,IAAuB,EAC3CC,KAAK,GAAG;AACb;AAMO,SAASC,EAAiB;AAAA,EAC/BC,qBAAAA;AAAAA,EACAP,QAAAA;AAAAA,EACAQ,kBAAAA;AAAAA,EACAC,YAAAA;AAMF,GAAG;AACD,SAAO,CAACF,GAAqBP,GAAQQ,GAAkBC,CAAU,EAC9DN,OAAQC,CAAMA,MAAAA,KAAM,IAAuB,EAC3CC,KAAK,GAAG;AACb;"}
@@ -5,27 +5,27 @@ import "@knocklabs/client";
5
5
  import "zustand/shallow";
6
6
  import { feedProviderKey as a } from "../../core/utils.mjs";
7
7
  import k from "../hooks/useNotifications.mjs";
8
- const i = o.createContext(null), C = ({
8
+ const i = o.createContext(void 0), F = ({
9
9
  feedId: e,
10
10
  children: c,
11
- defaultFeedOptions: t = {},
11
+ defaultFeedOptions: n = {},
12
12
  colorMode: s = "light"
13
13
  }) => {
14
- const r = d(), n = k(r, e, t), m = u(n.store);
15
- return /* @__PURE__ */ o.createElement(i.Provider, { key: a(e, t), value: {
16
- knock: r,
17
- feedClient: n,
14
+ const t = d(), r = k(t, e, n), m = o.useMemo(() => u(r.store), [r]);
15
+ return /* @__PURE__ */ o.createElement(i.Provider, { key: a(t.userId, e, n), value: {
16
+ knock: t,
17
+ feedClient: r,
18
18
  useFeedStore: m,
19
19
  colorMode: s
20
20
  } }, c);
21
- }, F = () => {
21
+ }, l = () => {
22
22
  const e = o.useContext(i);
23
- if (e === void 0)
23
+ if (!e)
24
24
  throw new Error("useKnockFeed must be used within a KnockFeedProvider");
25
25
  return e;
26
26
  };
27
27
  export {
28
- C as KnockFeedProvider,
29
- F as useKnockFeed
28
+ F as KnockFeedProvider,
29
+ l as useKnockFeed
30
30
  };
31
31
  //# sourceMappingURL=KnockFeedProvider.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"KnockFeedProvider.mjs","sources":["../../../../../src/modules/feed/context/KnockFeedProvider.tsx"],"sourcesContent":["import Knock, {\n Feed,\n FeedClientOptions,\n FeedStoreState,\n} from \"@knocklabs/client\";\nimport * as React from \"react\";\nimport { PropsWithChildren } from \"react\";\nimport create, { UseBoundStore } from \"zustand\";\n\nimport { useKnockClient } from \"../../core\";\nimport { ColorMode } from \"../../core/constants\";\nimport { feedProviderKey } from \"../../core/utils\";\nimport useNotifications from \"../hooks/useNotifications\";\n\nexport interface KnockFeedProviderState {\n knock: Knock;\n feedClient: Feed;\n useFeedStore: UseBoundStore<FeedStoreState>;\n colorMode: ColorMode;\n}\n\nconst FeedStateContext = React.createContext<KnockFeedProviderState | null>(\n null,\n);\n\nexport interface KnockFeedProviderProps {\n // Feed props\n feedId: string;\n\n // Extra options\n colorMode?: ColorMode;\n\n // Feed client options\n defaultFeedOptions?: FeedClientOptions;\n}\n\nexport const KnockFeedProvider: React.FC<\n PropsWithChildren<KnockFeedProviderProps>\n> = ({ feedId, children, defaultFeedOptions = {}, colorMode = \"light\" }) => {\n const knock = useKnockClient();\n const feedClient = useNotifications(knock, feedId, defaultFeedOptions);\n const useFeedStore = create<FeedStoreState>(feedClient.store);\n\n return (\n <FeedStateContext.Provider\n key={feedProviderKey(feedId, defaultFeedOptions)}\n value={{\n knock,\n feedClient,\n useFeedStore,\n colorMode,\n }}\n >\n {children}\n </FeedStateContext.Provider>\n );\n};\n\nexport const useKnockFeed = (): KnockFeedProviderState => {\n const context = React.useContext(FeedStateContext);\n if (context === undefined) {\n throw new Error(\"useKnockFeed must be used within a KnockFeedProvider\");\n }\n return context as KnockFeedProviderState;\n};\n"],"names":["FeedStateContext","React","createContext","KnockFeedProvider","feedId","children","defaultFeedOptions","colorMode","knock","useKnockClient","feedClient","useNotifications","useFeedStore","create","store","feedProviderKey","useKnockFeed","context","useContext","undefined","Error"],"mappings":";;;;;;;AAqBA,MAAMA,IAAmBC,EAAMC,cAC7B,IACF,GAaaC,IAETA,CAAC;AAAA,EAAEC,QAAAA;AAAAA,EAAQC,UAAAA;AAAAA,EAAUC,oBAAAA,IAAqB,CAAC;AAAA,EAAGC,WAAAA,IAAY;AAAQ,MAAM;AAC1E,QAAMC,IAAQC,KACRC,IAAaC,EAAiBH,GAAOJ,GAAQE,CAAkB,GAC/DM,IAAeC,EAAuBH,EAAWI,KAAK;AAG1D,SAAA,gBAAAb,EAAA,cAACD,EAAiB,UAAjB,EACC,KAAKe,EAAgBX,GAAQE,CAAkB,GAC/C,OAAO;AAAA,IACLE,OAAAA;AAAAA,IACAE,YAAAA;AAAAA,IACAE,cAAAA;AAAAA,IACAL,WAAAA;AAAAA,EAAAA,KAGDF,CACH;AAEJ,GAEaW,IAAeA,MAA8B;AAClDC,QAAAA,IAAUhB,EAAMiB,WAAWlB,CAAgB;AACjD,MAAIiB,MAAYE;AACR,UAAA,IAAIC,MAAM,sDAAsD;AAEjEH,SAAAA;AACT;"}
1
+ {"version":3,"file":"KnockFeedProvider.mjs","sources":["../../../../../src/modules/feed/context/KnockFeedProvider.tsx"],"sourcesContent":["import Knock, {\n Feed,\n FeedClientOptions,\n FeedStoreState,\n} from \"@knocklabs/client\";\nimport * as React from \"react\";\nimport { PropsWithChildren } from \"react\";\nimport create, { UseBoundStore } from \"zustand\";\n\nimport { useKnockClient } from \"../../core\";\nimport { ColorMode } from \"../../core/constants\";\nimport { feedProviderKey } from \"../../core/utils\";\nimport useNotifications from \"../hooks/useNotifications\";\n\nexport interface KnockFeedProviderState {\n knock: Knock;\n feedClient: Feed;\n useFeedStore: UseBoundStore<FeedStoreState>;\n colorMode: ColorMode;\n}\n\nconst FeedStateContext = React.createContext<\n KnockFeedProviderState | undefined\n>(undefined);\n\nexport interface KnockFeedProviderProps {\n // Feed props\n feedId: string;\n\n // Extra options\n colorMode?: ColorMode;\n\n // Feed client options\n defaultFeedOptions?: FeedClientOptions;\n}\n\nexport const KnockFeedProvider: React.FC<\n PropsWithChildren<KnockFeedProviderProps>\n> = ({ feedId, children, defaultFeedOptions = {}, colorMode = \"light\" }) => {\n const knock = useKnockClient();\n const feedClient = useNotifications(knock, feedId, defaultFeedOptions);\n\n const useFeedStore = React.useMemo(\n () => create<FeedStoreState>(feedClient.store),\n [feedClient],\n );\n\n return (\n <FeedStateContext.Provider\n key={feedProviderKey(knock.userId, feedId, defaultFeedOptions)}\n value={{\n knock,\n feedClient,\n useFeedStore,\n colorMode,\n }}\n >\n {children}\n </FeedStateContext.Provider>\n );\n};\n\nexport const useKnockFeed = (): KnockFeedProviderState => {\n const context = React.useContext(FeedStateContext);\n\n if (!context) {\n throw new Error(\"useKnockFeed must be used within a KnockFeedProvider\");\n }\n\n return context;\n};\n"],"names":["FeedStateContext","React","createContext","undefined","KnockFeedProvider","feedId","children","defaultFeedOptions","colorMode","knock","useKnockClient","feedClient","useNotifications","useFeedStore","useMemo","create","store","feedProviderKey","userId","useKnockFeed","context","useContext","Error"],"mappings":";;;;;;;AAqBA,MAAMA,IAAmBC,EAAMC,cAE7BC,MAAS,GAaEC,IAETA,CAAC;AAAA,EAAEC,QAAAA;AAAAA,EAAQC,UAAAA;AAAAA,EAAUC,oBAAAA,IAAqB,CAAC;AAAA,EAAGC,WAAAA,IAAY;AAAQ,MAAM;AAC1E,QAAMC,IAAQC,KACRC,IAAaC,EAAiBH,GAAOJ,GAAQE,CAAkB,GAE/DM,IAAeZ,EAAMa,QACzB,MAAMC,EAAuBJ,EAAWK,KAAK,GAC7C,CAACL,CAAU,CACb;AAGE,SAAA,gBAAAV,EAAA,cAACD,EAAiB,UAAjB,EACC,KAAKiB,EAAgBR,EAAMS,QAAQb,GAAQE,CAAkB,GAC7D,OAAO;AAAA,IACLE,OAAAA;AAAAA,IACAE,YAAAA;AAAAA,IACAE,cAAAA;AAAAA,IACAL,WAAAA;AAAAA,EAAAA,KAGDF,CACH;AAEJ,GAEaa,IAAeA,MAA8B;AAClDC,QAAAA,IAAUnB,EAAMoB,WAAWrB,CAAgB;AAEjD,MAAI,CAACoB;AACG,UAAA,IAAIE,MAAM,sDAAsD;AAGjEF,SAAAA;AACT;"}
@@ -1 +1 @@
1
- {"version":3,"file":"useAuthenticatedKnockClient.d.ts","sourceRoot":"","sources":["../../../../../src/modules/core/hooks/useAuthenticatedKnockClient.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAgB7E,MAAM,MAAM,+BAA+B,GAAG,YAAY,GACxD,mBAAmB,CAAC;AAEtB,iBAAS,2BAA2B,CAClC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,SAAS,CAAC,EAAE,MAAM,EAClB,OAAO,GAAE,+BAAoC,SAwC9C;AAED,eAAe,2BAA2B,CAAC"}
1
+ {"version":3,"file":"useAuthenticatedKnockClient.d.ts","sourceRoot":"","sources":["../../../../../src/modules/core/hooks/useAuthenticatedKnockClient.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAgB7E,MAAM,MAAM,+BAA+B,GAAG,YAAY,GACxD,mBAAmB,CAAC;AAEtB,iBAAS,2BAA2B,CAClC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,SAAS,CAAC,EAAE,MAAM,EAClB,OAAO,GAAE,+BAAoC,SA8C9C;AAED,eAAe,2BAA2B,CAAC"}
@@ -7,7 +7,7 @@ type FormatTimestampOptions = {
7
7
  export declare function formatTimestamp(ts: string, options?: FormatTimestampOptions): string;
8
8
  export declare function toSentenceCase(string: string): string;
9
9
  export declare function renderNodeOrFallback(node: ReactNode, fallback: ReactNode): ReactNode;
10
- export declare function feedProviderKey(userFeedId: string, options?: FeedClientOptions): string;
10
+ export declare function feedProviderKey(userId: string | undefined, feedId: string, options?: FeedClientOptions): string;
11
11
  export declare function slackProviderKey({ knockSlackChannelId, tenant, connectionStatus, errorLabel, }: {
12
12
  knockSlackChannelId: string;
13
13
  tenant: string;
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../../src/modules/core/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAEtD,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAElC,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAE/D;AAED,KAAK,sBAAsB,GAAG;IAC5B,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;CAC5B,CAAC;AAEF,wBAAgB,eAAe,CAC7B,EAAE,EAAE,MAAM,EACV,OAAO,GAAE,sBAA2B,UAYrC;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAErD;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,aAExE;AAMD,wBAAgB,eAAe,CAC7B,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE,iBAAsB,UAWhC;AAMD,wBAAgB,gBAAgB,CAAC,EAC/B,mBAAmB,EACnB,MAAM,EACN,gBAAgB,EAChB,UAAU,GACX,EAAE;IACD,mBAAmB,EAAE,MAAM,CAAC;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,gBAAgB,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B,UAIA"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../../src/modules/core/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAEtD,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAElC,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAE/D;AAED,KAAK,sBAAsB,GAAG;IAC5B,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;CAC5B,CAAC;AAEF,wBAAgB,eAAe,CAC7B,EAAE,EAAE,MAAM,EACV,OAAO,GAAE,sBAA2B,UAYrC;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAErD;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,aAExE;AAMD,wBAAgB,eAAe,CAC7B,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,iBAAsB,UAYhC;AAMD,wBAAgB,gBAAgB,CAAC,EAC/B,mBAAmB,EACnB,MAAM,EACN,gBAAgB,EAChB,UAAU,GACX,EAAE;IACD,mBAAmB,EAAE,MAAM,CAAC;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,gBAAgB,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B,UAIA"}
@@ -1 +1 @@
1
- {"version":3,"file":"KnockFeedProvider.d.ts","sourceRoot":"","sources":["../../../../../src/modules/feed/context/KnockFeedProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EACZ,IAAI,EACJ,iBAAiB,EACjB,cAAc,EACf,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,iBAAiB,EAAE,MAAM,OAAO,CAAC;AAC1C,OAAe,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAGhD,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAIjD,MAAM,WAAW,sBAAsB;IACrC,KAAK,EAAE,KAAK,CAAC;IACb,UAAU,EAAE,IAAI,CAAC;IACjB,YAAY,EAAE,aAAa,CAAC,cAAc,CAAC,CAAC;IAC5C,SAAS,EAAE,SAAS,CAAC;CACtB;AAMD,MAAM,WAAW,sBAAsB;IAErC,MAAM,EAAE,MAAM,CAAC;IAGf,SAAS,CAAC,EAAE,SAAS,CAAC;IAGtB,kBAAkB,CAAC,EAAE,iBAAiB,CAAC;CACxC;AAED,eAAO,MAAM,iBAAiB,EAAE,KAAK,CAAC,EAAE,CACtC,iBAAiB,CAAC,sBAAsB,CAAC,CAmB1C,CAAC;AAEF,eAAO,MAAM,YAAY,QAAO,sBAM/B,CAAC"}
1
+ {"version":3,"file":"KnockFeedProvider.d.ts","sourceRoot":"","sources":["../../../../../src/modules/feed/context/KnockFeedProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EACZ,IAAI,EACJ,iBAAiB,EACjB,cAAc,EACf,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,iBAAiB,EAAE,MAAM,OAAO,CAAC;AAC1C,OAAe,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAGhD,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAIjD,MAAM,WAAW,sBAAsB;IACrC,KAAK,EAAE,KAAK,CAAC;IACb,UAAU,EAAE,IAAI,CAAC;IACjB,YAAY,EAAE,aAAa,CAAC,cAAc,CAAC,CAAC;IAC5C,SAAS,EAAE,SAAS,CAAC;CACtB;AAMD,MAAM,WAAW,sBAAsB;IAErC,MAAM,EAAE,MAAM,CAAC;IAGf,SAAS,CAAC,EAAE,SAAS,CAAC;IAGtB,kBAAkB,CAAC,EAAE,iBAAiB,CAAC;CACxC;AAED,eAAO,MAAM,iBAAiB,EAAE,KAAK,CAAC,EAAE,CACtC,iBAAiB,CAAC,sBAAsB,CAAC,CAuB1C,CAAC;AAEF,eAAO,MAAM,YAAY,QAAO,sBAQ/B,CAAC"}
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@knocklabs/react-core",
3
3
  "description": "A set of React components to build notification experiences powered by Knock",
4
4
  "author": "@knocklabs",
5
- "version": "0.2.16",
5
+ "version": "0.2.17",
6
6
  "license": "MIT",
7
7
  "main": "dist/cjs/index.js",
8
8
  "module": "dist/esm/index.mjs",
@@ -48,7 +48,7 @@
48
48
  "react": "^16.11.0 || ^17.0.0 || ^18.0.0"
49
49
  },
50
50
  "dependencies": {
51
- "@knocklabs/client": "^0.10.6",
51
+ "@knocklabs/client": "^0.10.7",
52
52
  "date-fns": "^3.3.1",
53
53
  "swr": "^2.2.5",
54
54
  "zustand": "^3.7.2"
@@ -30,7 +30,13 @@ function useAuthenticatedKnockClient(
30
30
  // set of options between re-renders.
31
31
  const stableOptions = React.useMemo(() => {
32
32
  const currentOptions = optionsRef.current || {};
33
- return shallow(options, currentOptions) ? currentOptions : options;
33
+
34
+ if (shallow(options, currentOptions)) {
35
+ return currentOptions;
36
+ }
37
+
38
+ optionsRef.current = options;
39
+ return options;
34
40
  }, [options]);
35
41
 
36
42
  return React.useMemo(() => {
@@ -39,11 +39,13 @@ export function renderNodeOrFallback(node: ReactNode, fallback: ReactNode) {
39
39
  to trigger a re-render of the context when a key property changes.
40
40
  */
41
41
  export function feedProviderKey(
42
- userFeedId: string,
42
+ userId: string | undefined,
43
+ feedId: string,
43
44
  options: FeedClientOptions = {},
44
45
  ) {
45
46
  return [
46
- userFeedId,
47
+ userId,
48
+ feedId,
47
49
  options.source,
48
50
  options.tenant,
49
51
  options.has_tenant,
@@ -19,9 +19,9 @@ export interface KnockFeedProviderState {
19
19
  colorMode: ColorMode;
20
20
  }
21
21
 
22
- const FeedStateContext = React.createContext<KnockFeedProviderState | null>(
23
- null,
24
- );
22
+ const FeedStateContext = React.createContext<
23
+ KnockFeedProviderState | undefined
24
+ >(undefined);
25
25
 
26
26
  export interface KnockFeedProviderProps {
27
27
  // Feed props
@@ -39,11 +39,15 @@ export const KnockFeedProvider: React.FC<
39
39
  > = ({ feedId, children, defaultFeedOptions = {}, colorMode = "light" }) => {
40
40
  const knock = useKnockClient();
41
41
  const feedClient = useNotifications(knock, feedId, defaultFeedOptions);
42
- const useFeedStore = create<FeedStoreState>(feedClient.store);
42
+
43
+ const useFeedStore = React.useMemo(
44
+ () => create<FeedStoreState>(feedClient.store),
45
+ [feedClient],
46
+ );
43
47
 
44
48
  return (
45
49
  <FeedStateContext.Provider
46
- key={feedProviderKey(feedId, defaultFeedOptions)}
50
+ key={feedProviderKey(knock.userId, feedId, defaultFeedOptions)}
47
51
  value={{
48
52
  knock,
49
53
  feedClient,
@@ -58,8 +62,10 @@ export const KnockFeedProvider: React.FC<
58
62
 
59
63
  export const useKnockFeed = (): KnockFeedProviderState => {
60
64
  const context = React.useContext(FeedStateContext);
61
- if (context === undefined) {
65
+
66
+ if (!context) {
62
67
  throw new Error("useKnockFeed must be used within a KnockFeedProvider");
63
68
  }
64
- return context as KnockFeedProviderState;
69
+
70
+ return context;
65
71
  };